/*
 * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.tools.javap;

import com.sun.tools.classfile.Annotation;
import com.sun.tools.classfile.TypeAnnotation;
import com.sun.tools.classfile.Annotation.Annotation_element_value;
import com.sun.tools.classfile.Annotation.Array_element_value;
import com.sun.tools.classfile.Annotation.Class_element_value;
import com.sun.tools.classfile.Annotation.Enum_element_value;
import com.sun.tools.classfile.Annotation.Primitive_element_value;
import com.sun.tools.classfile.ConstantPool;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Descriptor;
import com.sun.tools.classfile.Descriptor.InvalidDescriptor;

/**
 *  A writer for writing annotations as text.
 *
 *  <p><b>This is NOT part of any supported API.
 *  If you write code that depends on this, you do so at your own risk.
 *  This code and its internal interfaces are subject to change or
 *  deletion without notice.</b>
 */
public class AnnotationWriter extends BasicWriter {
    static AnnotationWriter instance(Context context) {
        AnnotationWriter instance = context.get(AnnotationWriter.class);
        if (instance == null)
            instance = new AnnotationWriter(context);
        return instance;
    }

    protected AnnotationWriter(Context context) {
        super(context);
        classWriter = ClassWriter.instance(context);
        constantWriter = ConstantWriter.instance(context);
    }

    public void write(Annotation annot) {
        write(annot, false);
    }

    public void write(Annotation annot, boolean resolveIndices) {
        writeDescriptor(annot.type_index, resolveIndices);
        boolean showParens = annot.num_element_value_pairs > 0 || !resolveIndices;
        if (showParens)
            print("(");
        for (int i = 0; i < annot.num_element_value_pairs; i++) {
            if (i > 0)
                print(",");
            write(annot.element_value_pairs[i], resolveIndices);
        }
        if (showParens)
            print(")");
    }

    public void write(TypeAnnotation annot) {
        write(annot, true, false);
    }

    public void write(TypeAnnotation annot, boolean showOffsets, boolean resolveIndices) {
        write(annot.annotation, resolveIndices);
        print(": ");
        write(annot.position, showOffsets);
    }

    public void write(TypeAnnotation.Position pos, boolean showOffsets) {
        print(pos.type);

        switch (pos.type) {
        // instanceof
        case INSTANCEOF:
        // new expression
        case NEW:
        // constructor/method reference receiver
        case CONSTRUCTOR_REFERENCE:
        case METHOD_REFERENCE:
            if (showOffsets) {
                print(", offset=");
                print(pos.offset);
            }
            break;
        // local variable
        case LOCAL_VARIABLE:
        // resource variable
        case RESOURCE_VARIABLE:
            if (pos.lvarOffset == null) {
                print(", lvarOffset is Null!");
                break;
            }
            print(", {");
            for (int i = 0; i < pos.lvarOffset.length; ++i) {
                if (i != 0) print("; ");
                if (showOffsets) {
                    print("start_pc=");
                    print(pos.lvarOffset[i]);
                }
                print(", length=");
                print(pos.lvarLength[i]);
                print(", index=");
                print(pos.lvarIndex[i]);
            }
            print("}");
            break;
        // exception parameter
        case EXCEPTION_PARAMETER:
            print(", exception_index=");
            print(pos.exception_index);
            break;
        // method receiver
        case METHOD_RECEIVER:
            // Do nothing
            break;
        // type parameter
        case CLASS_TYPE_PARAMETER:
        case METHOD_TYPE_PARAMETER:
            print(", param_index=");
            print(pos.parameter_index);
            break;
        // type parameter bound
        case CLASS_TYPE_PARAMETER_BOUND:
        case METHOD_TYPE_PARAMETER_BOUND:
            print(", param_index=");
            print(pos.parameter_index);
            print(", bound_index=");
            print(pos.bound_index);
            break;
        // class extends or implements clause
        case CLASS_EXTENDS:
            print(", type_index=");
            print(pos.type_index);
            break;
        // throws
        case THROWS:
            print(", type_index=");
            print(pos.type_index);
            break;
        // method parameter
        case METHOD_FORMAL_PARAMETER:
            print(", param_index=");
            print(pos.parameter_index);
            break;
        // type cast
        case CAST:
        // method/constructor/reference type argument
        case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
        case METHOD_INVOCATION_TYPE_ARGUMENT:
        case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
        case METHOD_REFERENCE_TYPE_ARGUMENT:
            if (showOffsets) {
                print(", offset=");
                print(pos.offset);
            }
            print(", type_index=");
            print(pos.type_index);
            break;
        // We don't need to worry about these
        case METHOD_RETURN:
        case FIELD:
            break;
        case UNKNOWN:
            throw new AssertionError("AnnotationWriter: UNKNOWN target type should never occur!");
        default:
            throw new AssertionError("AnnotationWriter: Unknown target type for position: " + pos);
        }

        // Append location data for generics/arrays.
        if (!pos.location.isEmpty()) {
            print(", location=");
            print(pos.location);
        }
    }

    public void write(Annotation.element_value_pair pair) {
        write(pair, false);
    }

    public void write(Annotation.element_value_pair pair, boolean resolveIndices) {
        writeIndex(pair.element_name_index, resolveIndices);
        print("=");
        write(pair.value, resolveIndices);
    }

    public void write(Annotation.element_value value) {
        write(value, false);
    }

    public void write(Annotation.element_value value, boolean resolveIndices) {
        ev_writer.write(value, resolveIndices);
    }

    private void writeDescriptor(int index, boolean resolveIndices) {
        if (resolveIndices) {
            try {
                ConstantPool constant_pool = classWriter.getClassFile().constant_pool;
                Descriptor d = new Descriptor(index);
                print(d.getFieldType(constant_pool));
                return;
            } catch (ConstantPoolException | InvalidDescriptor ignore) {
            }
        }

        print("#" + index);
    }

    private void writeIndex(int index, boolean resolveIndices) {
        if (resolveIndices) {
            print(constantWriter.stringValue(index));
        } else
            print("#" + index);
    }

    element_value_Writer ev_writer = new element_value_Writer();

    class element_value_Writer implements Annotation.element_value.Visitor<Void,Boolean> {
        public void write(Annotation.element_value value, boolean resolveIndices) {
            value.accept(this, resolveIndices);
        }

        public Void visitPrimitive(Primitive_element_value ev, Boolean resolveIndices) {
            if (resolveIndices)
                writeIndex(ev.const_value_index, resolveIndices);
            else
                print(((char) ev.tag) + "#" + ev.const_value_index);
            return null;
        }

        public Void visitEnum(Enum_element_value ev, Boolean resolveIndices) {
            if (resolveIndices) {
                writeIndex(ev.type_name_index, resolveIndices);
                print(".");
                writeIndex(ev.const_name_index, resolveIndices);
            } else
                print(((char) ev.tag) + "#" + ev.type_name_index + ".#" + ev.const_name_index);
            return null;
        }

        public Void visitClass(Class_element_value ev, Boolean resolveIndices) {
            if (resolveIndices) {
                writeIndex(ev.class_info_index, resolveIndices);
                print(".class");
            } else
                print(((char) ev.tag) + "#" + ev.class_info_index);
            return null;
        }

        public Void visitAnnotation(Annotation_element_value ev, Boolean resolveIndices) {
            print((char) ev.tag);
            AnnotationWriter.this.write(ev.annotation_value, resolveIndices);
            return null;
        }

        public Void visitArray(Array_element_value ev, Boolean resolveIndices) {
            print("[");
            for (int i = 0; i < ev.num_values; i++) {
                if (i > 0)
                    print(",");
                write(ev.values[i], resolveIndices);
            }
            print("]");
            return null;
        }

    }

    private ClassWriter classWriter;
    private ConstantWriter constantWriter;
}
