/*
 * Copyright (c) 2009, 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.javac.util;

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;

import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.Printer;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Types;

import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.util.LayoutCharacters.*;
import static com.sun.tools.javac.util.RichDiagnosticFormatter.RichConfiguration.*;

/**
 * A rich diagnostic formatter is a formatter that provides better integration
 * with javac's type system. A diagostic is first preprocessed in order to keep
 * track of each types/symbols in it; after these informations are collected,
 * the diagnostic is rendered using a standard formatter, whose type/symbol printer
 * has been replaced by a more refined version provided by this rich formatter.
 * The rich formatter currently enables three different features: (i) simple class
 * names - that is class names are displayed used a non qualified name (thus
 * omitting package info) whenever possible - (ii) where clause list - a list of
 * additional subdiagnostics that provide specific info about type-variables,
 * captured types, intersection types that occur in the diagnostic that is to be
 * formatted and (iii) type-variable disambiguation - when the diagnostic refers
 * to two different type-variables with the same name, their representation is
 * disambiguated by appending an index to the type variable name.
 *
 * <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 RichDiagnosticFormatter extends
        ForwardingDiagnosticFormatter<JCDiagnostic, AbstractDiagnosticFormatter> {

    final Symtab syms;
    final Types types;
    final JCDiagnostic.Factory diags;
    final JavacMessages messages;

    /* name simplifier used by this formatter */
    protected ClassNameSimplifier nameSimplifier;

    /* type/symbol printer used by this formatter */
    private RichPrinter printer;

    /* map for keeping track of a where clause associated to a given type */
    Map<WhereClauseKind, Map<Type, JCDiagnostic>> whereClauses;

    /** Get the DiagnosticFormatter instance for this context. */
    public static RichDiagnosticFormatter instance(Context context) {
        RichDiagnosticFormatter instance = context.get(RichDiagnosticFormatter.class);
        if (instance == null)
            instance = new RichDiagnosticFormatter(context);
        return instance;
    }

    protected RichDiagnosticFormatter(Context context) {
        super((AbstractDiagnosticFormatter)Log.instance(context).getDiagnosticFormatter());
        setRichPrinter(new RichPrinter());
        this.syms = Symtab.instance(context);
        this.diags = JCDiagnostic.Factory.instance(context);
        this.types = Types.instance(context);
        this.messages = JavacMessages.instance(context);
        whereClauses = new EnumMap<>(WhereClauseKind.class);
        configuration = new RichConfiguration(Options.instance(context), formatter);
        for (WhereClauseKind kind : WhereClauseKind.values())
            whereClauses.put(kind, new LinkedHashMap<Type, JCDiagnostic>());
    }

    @Override
    public String format(JCDiagnostic diag, Locale l) {
        StringBuilder sb = new StringBuilder();
        nameSimplifier = new ClassNameSimplifier();
        for (WhereClauseKind kind : WhereClauseKind.values())
            whereClauses.get(kind).clear();
        preprocessDiagnostic(diag);
        sb.append(formatter.format(diag, l));
        if (getConfiguration().isEnabled(RichFormatterFeature.WHERE_CLAUSES)) {
            List<JCDiagnostic> clauses = getWhereClauses();
            String indent = formatter.isRaw() ? "" :
                formatter.indentString(DetailsInc);
            for (JCDiagnostic d : clauses) {
                String whereClause = formatter.format(d, l);
                if (whereClause.length() > 0) {
                    sb.append('\n' + indent + whereClause);
                }
            }
        }
        return sb.toString();
    }

    @Override
    public String formatMessage(JCDiagnostic diag, Locale l) {
        nameSimplifier = new ClassNameSimplifier();
        preprocessDiagnostic(diag);
        return super.formatMessage(diag, l);
    }

    /**
     * Sets the type/symbol printer used by this formatter.
     * @param printer the rich printer to be set
     */
    protected void setRichPrinter(RichPrinter printer) {
        this.printer = printer;
        formatter.setPrinter(printer);
    }

    /**
     * Gets the type/symbol printer used by this formatter.
     * @return type/symbol rich printer
     */
    protected RichPrinter getRichPrinter() {
        return printer;
    }

    /**
     * Preprocess a given diagnostic by looking both into its arguments and into
     * its subdiagnostics (if any). This preprocessing is responsible for
     * generating info corresponding to features like where clauses, name
     * simplification, etc.
     *
     * @param diag the diagnostic to be preprocessed
     */
    protected void preprocessDiagnostic(JCDiagnostic diag) {
        for (Object o : diag.getArgs()) {
            if (o != null) {
                preprocessArgument(o);
            }
        }
        if (diag.isMultiline()) {
            for (JCDiagnostic d : diag.getSubdiagnostics())
                preprocessDiagnostic(d);
        }
    }

    /**
     * Preprocess a diagnostic argument. A type/symbol argument is
     * preprocessed by specialized type/symbol preprocessors.
     *
     * @param arg the argument to be translated
     */
    protected void preprocessArgument(Object arg) {
        if (arg instanceof Type) {
            preprocessType((Type)arg);
        }
        else if (arg instanceof Symbol) {
            preprocessSymbol((Symbol)arg);
        }
        else if (arg instanceof JCDiagnostic) {
            preprocessDiagnostic((JCDiagnostic)arg);
        }
        else if (arg instanceof Iterable<?>) {
            for (Object o : (Iterable<?>)arg) {
                preprocessArgument(o);
            }
        }
    }

    /**
     * Build a list of multiline diagnostics containing detailed info about
     * type-variables, captured types, and intersection types
     *
     * @return where clause list
     */
    protected List<JCDiagnostic> getWhereClauses() {
        List<JCDiagnostic> clauses = List.nil();
        for (WhereClauseKind kind : WhereClauseKind.values()) {
            List<JCDiagnostic> lines = List.nil();
            for (Map.Entry<Type, JCDiagnostic> entry : whereClauses.get(kind).entrySet()) {
                lines = lines.prepend(entry.getValue());
            }
            if (!lines.isEmpty()) {
                String key = kind.key();
                if (lines.size() > 1)
                    key += ".1";
                JCDiagnostic d = diags.fragment(key, whereClauses.get(kind).keySet());
                d = new JCDiagnostic.MultilineDiagnostic(d, lines.reverse());
                clauses = clauses.prepend(d);
            }
        }
        return clauses.reverse();
    }

    private int indexOf(Type type, WhereClauseKind kind) {
        int index = 1;
        for (Type t : whereClauses.get(kind).keySet()) {
            if (t.tsym == type.tsym) {
                return index;
            }
            if (kind != WhereClauseKind.TYPEVAR ||
                    t.toString().equals(type.toString())) {
                index++;
            }
        }
        return -1;
    }

    private boolean unique(TypeVar typevar) {
        int found = 0;
        for (Type t : whereClauses.get(WhereClauseKind.TYPEVAR).keySet()) {
            if (t.toString().equals(typevar.toString())) {
                found++;
            }
        }
        if (found < 1)
            throw new AssertionError("Missing type variable in where clause " + typevar);
        return found == 1;
    }
    //where
    /**
     * This enum defines all posssible kinds of where clauses that can be
     * attached by a rich diagnostic formatter to a given diagnostic
     */
    enum WhereClauseKind {

        /** where clause regarding a type variable */
        TYPEVAR("where.description.typevar"),
        /** where clause regarding a captured type */
        CAPTURED("where.description.captured"),
        /** where clause regarding an intersection type */
        INTERSECTION("where.description.intersection");

        /** resource key for this where clause kind */
        private final String key;

        WhereClauseKind(String key) {
            this.key = key;
        }

        String key() {
            return key;
        }
    }

    // <editor-fold defaultstate="collapsed" desc="name simplifier">
    /**
     * A name simplifier keeps track of class names usages in order to determine
     * whether a class name can be compacted or not. Short names are not used
     * if a conflict is detected, e.g. when two classes with the same simple
     * name belong to different packages - in this case the formatter reverts
     * to fullnames as compact names might lead to a confusing diagnostic.
     */
    protected class ClassNameSimplifier {

        /* table for keeping track of all short name usages */
        Map<Name, List<Symbol>> nameClashes = new HashMap<>();

        /**
         * Add a name usage to the simplifier's internal cache
         */
        protected void addUsage(Symbol sym) {
            Name n = sym.getSimpleName();
            List<Symbol> conflicts = nameClashes.get(n);
            if (conflicts == null) {
                conflicts = List.nil();
            }
            if (!conflicts.contains(sym))
                nameClashes.put(n, conflicts.append(sym));
        }

        public String simplify(Symbol s) {
            String name = s.getQualifiedName().toString();
            if (!s.type.isCompound() && !s.type.isPrimitive()) {
                List<Symbol> conflicts = nameClashes.get(s.getSimpleName());
                if (conflicts == null ||
                    (conflicts.size() == 1 &&
                    conflicts.contains(s))) {
                    List<Name> l = List.nil();
                    Symbol s2 = s;
                    while (s2.type.hasTag(CLASS) &&
                            s2.type.getEnclosingType().hasTag(CLASS) &&
                            s2.owner.kind == Kinds.TYP) {
                        l = l.prepend(s2.getSimpleName());
                        s2 = s2.owner;
                    }
                    l = l.prepend(s2.getSimpleName());
                    StringBuilder buf = new StringBuilder();
                    String sep = "";
                    for (Name n2 : l) {
                        buf.append(sep);
                        buf.append(n2);
                        sep = ".";
                    }
                    name = buf.toString();
                }
            }
            return name;
        }
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="rich printer">
    /**
     * Enhanced type/symbol printer that provides support for features like simple names
     * and type variable disambiguation. This enriched printer exploits the info
     * discovered during type/symbol preprocessing. This printer is set on the delegate
     * formatter so that rich type/symbol info can be properly rendered.
     */
    protected class RichPrinter extends Printer {

        @Override
        public String localize(Locale locale, String key, Object... args) {
            return formatter.localize(locale, key, args);
        }

        @Override
        public String capturedVarId(CapturedType t, Locale locale) {
            return indexOf(t, WhereClauseKind.CAPTURED) + "";
        }

        @Override
        public String visitType(Type t, Locale locale) {
            String s = super.visitType(t, locale);
            if (t == syms.botType)
                s = localize(locale, "compiler.misc.type.null");
            return s;
        }

        @Override
        public String visitCapturedType(CapturedType t, Locale locale) {
            if (getConfiguration().isEnabled(RichFormatterFeature.WHERE_CLAUSES)) {
                return localize(locale,
                    "compiler.misc.captured.type",
                    indexOf(t, WhereClauseKind.CAPTURED));
            }
            else
                return super.visitCapturedType(t, locale);
        }

        @Override
        public String visitClassType(ClassType t, Locale locale) {
            if (t.isCompound() &&
                    getConfiguration().isEnabled(RichFormatterFeature.WHERE_CLAUSES)) {
                return localize(locale,
                        "compiler.misc.intersection.type",
                        indexOf(t, WhereClauseKind.INTERSECTION));
            }
            else
                return super.visitClassType(t, locale);
        }

        @Override
        protected String className(ClassType t, boolean longform, Locale locale) {
            Symbol sym = t.tsym;
            if (sym.name.length() == 0 ||
                    !getConfiguration().isEnabled(RichFormatterFeature.SIMPLE_NAMES)) {
                return super.className(t, longform, locale);
            }
            else if (longform)
                return nameSimplifier.simplify(sym).toString();
            else
                return sym.name.toString();
        }

        @Override
        public String visitTypeVar(TypeVar t, Locale locale) {
            if (unique(t) ||
                    !getConfiguration().isEnabled(RichFormatterFeature.UNIQUE_TYPEVAR_NAMES)) {
                return t.toString();
            }
            else {
                return localize(locale,
                        "compiler.misc.type.var",
                        t.toString(), indexOf(t, WhereClauseKind.TYPEVAR));
            }
        }

        @Override
        public String visitClassSymbol(ClassSymbol s, Locale locale) {
            if (s.type.isCompound()) {
                return visit(s.type, locale);
            }
            String name = nameSimplifier.simplify(s);
            if (name.length() == 0 ||
                    !getConfiguration().isEnabled(RichFormatterFeature.SIMPLE_NAMES)) {
                return super.visitClassSymbol(s, locale);
            }
            else {
                return name;
            }
        }

        @Override
        public String visitMethodSymbol(MethodSymbol s, Locale locale) {
            String ownerName = visit(s.owner, locale);
            if (s.isStaticOrInstanceInit()) {
               return ownerName;
            } else {
                String ms = (s.name == s.name.table.names.init)
                    ? ownerName
                    : s.name.toString();
                if (s.type != null) {
                    if (s.type.hasTag(FORALL)) {
                        ms = "<" + visitTypes(s.type.getTypeArguments(), locale) + ">" + ms;
                    }
                    ms += "(" + printMethodArgs(
                            s.type.getParameterTypes(),
                            (s.flags() & VARARGS) != 0,
                            locale) + ")";
                }
                return ms;
            }
        }
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="type scanner">
    /**
     * Preprocess a given type looking for (i) additional info (where clauses) to be
     * added to the main diagnostic (ii) names to be compacted.
     */
    protected void preprocessType(Type t) {
        typePreprocessor.visit(t);
    }
    //where
    protected Types.UnaryVisitor<Void> typePreprocessor =
            new Types.UnaryVisitor<Void>() {

        public Void visit(List<Type> ts) {
            for (Type t : ts)
                visit(t);
            return null;
        }

        @Override
        public Void visitForAll(ForAll t, Void ignored) {
            visit(t.tvars);
            visit(t.qtype);
            return null;
        }

        @Override
        public Void visitMethodType(MethodType t, Void ignored) {
            visit(t.argtypes);
            visit(t.restype);
            return null;
        }

        @Override
        public Void visitErrorType(ErrorType t, Void ignored) {
            Type ot = t.getOriginalType();
            if (ot != null)
                visit(ot);
            return null;
        }

        @Override
        public Void visitArrayType(ArrayType t, Void ignored) {
            visit(t.elemtype);
            return null;
        }

        @Override
        public Void visitWildcardType(WildcardType t, Void ignored) {
            visit(t.type);
            return null;
        }

        public Void visitType(Type t, Void ignored) {
            return null;
        }

        @Override
        public Void visitCapturedType(CapturedType t, Void ignored) {
            if (indexOf(t, WhereClauseKind.CAPTURED) == -1) {
                String suffix = t.lower == syms.botType ? ".1" : "";
                JCDiagnostic d = diags.fragment("where.captured"+ suffix, t, t.bound, t.lower, t.wildcard);
                whereClauses.get(WhereClauseKind.CAPTURED).put(t, d);
                visit(t.wildcard);
                visit(t.lower);
                visit(t.bound);
            }
            return null;
        }

        @Override
        public Void visitClassType(ClassType t, Void ignored) {
            if (t.isCompound()) {
                if (indexOf(t, WhereClauseKind.INTERSECTION) == -1) {
                    Type supertype = types.supertype(t);
                    List<Type> interfaces = types.interfaces(t);
                    JCDiagnostic d = diags.fragment("where.intersection", t, interfaces.prepend(supertype));
                    whereClauses.get(WhereClauseKind.INTERSECTION).put(t, d);
                    visit(supertype);
                    visit(interfaces);
                }
            } else if (t.tsym.name.isEmpty()) {
                //anon class
                ClassType norm = (ClassType) t.tsym.type;
                if (norm != null) {
                    if (norm.interfaces_field != null && norm.interfaces_field.nonEmpty()) {
                        visit(norm.interfaces_field.head);
                    } else {
                        visit(norm.supertype_field);
                    }
                }
            }
            nameSimplifier.addUsage(t.tsym);
            visit(t.getTypeArguments());
            if (t.getEnclosingType() != Type.noType)
                visit(t.getEnclosingType());
            return null;
        }

        @Override
        public Void visitTypeVar(TypeVar t, Void ignored) {
            if (indexOf(t, WhereClauseKind.TYPEVAR) == -1) {
                //access the bound type and skip error types
                Type bound = t.bound;
                while ((bound instanceof ErrorType))
                    bound = ((ErrorType)bound).getOriginalType();
                //retrieve the bound list - if the type variable
                //has not been attributed the bound is not set
                List<Type> bounds = (bound != null) &&
                        (bound.hasTag(CLASS) || bound.hasTag(TYPEVAR)) ?
                    types.getBounds(t) :
                    List.<Type>nil();

                nameSimplifier.addUsage(t.tsym);

                boolean boundErroneous = bounds.head == null ||
                                         bounds.head.hasTag(NONE) ||
                                         bounds.head.hasTag(ERROR);

                if ((t.tsym.flags() & SYNTHETIC) == 0) {
                    //this is a true typevar
                    JCDiagnostic d = diags.fragment("where.typevar" +
                        (boundErroneous ? ".1" : ""), t, bounds,
                        Kinds.kindName(t.tsym.location()), t.tsym.location());
                    whereClauses.get(WhereClauseKind.TYPEVAR).put(t, d);
                    symbolPreprocessor.visit(t.tsym.location(), null);
                    visit(bounds);
                } else {
                    Assert.check(!boundErroneous);
                    //this is a fresh (synthetic) tvar
                    JCDiagnostic d = diags.fragment("where.fresh.typevar", t, bounds);
                    whereClauses.get(WhereClauseKind.TYPEVAR).put(t, d);
                    visit(bounds);
                }

            }
            return null;
        }
    };
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="symbol scanner">
    /**
     * Preprocess a given symbol looking for (i) additional info (where clauses) to be
     * added to the main diagnostic (ii) names to be compacted
     */
    protected void preprocessSymbol(Symbol s) {
        symbolPreprocessor.visit(s, null);
    }
    //where
    protected Types.DefaultSymbolVisitor<Void, Void> symbolPreprocessor =
            new Types.DefaultSymbolVisitor<Void, Void>() {

        @Override
        public Void visitClassSymbol(ClassSymbol s, Void ignored) {
            if (s.type.isCompound()) {
                typePreprocessor.visit(s.type);
            } else {
                nameSimplifier.addUsage(s);
            }
            return null;
        }

        @Override
        public Void visitSymbol(Symbol s, Void ignored) {
            return null;
        }

        @Override
        public Void visitMethodSymbol(MethodSymbol s, Void ignored) {
            visit(s.owner, null);
            if (s.type != null)
                typePreprocessor.visit(s.type);
            return null;
        }
    };
    // </editor-fold>

    @Override
    public RichConfiguration getConfiguration() {
        //the following cast is always safe - see init
        return (RichConfiguration)configuration;
    }

    /**
     * Configuration object provided by the rich formatter.
     */
    public static class RichConfiguration extends ForwardingDiagnosticFormatter.ForwardingConfiguration {

        /** set of enabled rich formatter's features */
        protected java.util.EnumSet<RichFormatterFeature> features;

        @SuppressWarnings("fallthrough")
        public RichConfiguration(Options options, AbstractDiagnosticFormatter formatter) {
            super(formatter.getConfiguration());
            features = formatter.isRaw() ? EnumSet.noneOf(RichFormatterFeature.class) :
                EnumSet.of(RichFormatterFeature.SIMPLE_NAMES,
                    RichFormatterFeature.WHERE_CLAUSES,
                    RichFormatterFeature.UNIQUE_TYPEVAR_NAMES);
            String diagOpts = options.get("diags");
            if (diagOpts != null) {
                for (String args: diagOpts.split(",")) {
                    if (args.equals("-where")) {
                        features.remove(RichFormatterFeature.WHERE_CLAUSES);
                    }
                    else if (args.equals("where")) {
                        features.add(RichFormatterFeature.WHERE_CLAUSES);
                    }
                    if (args.equals("-simpleNames")) {
                        features.remove(RichFormatterFeature.SIMPLE_NAMES);
                    }
                    else if (args.equals("simpleNames")) {
                        features.add(RichFormatterFeature.SIMPLE_NAMES);
                    }
                    if (args.equals("-disambiguateTvars")) {
                        features.remove(RichFormatterFeature.UNIQUE_TYPEVAR_NAMES);
                    }
                    else if (args.equals("disambiguateTvars")) {
                        features.add(RichFormatterFeature.UNIQUE_TYPEVAR_NAMES);
                    }
                }
            }
        }

        /**
         * Returns a list of all the features supported by the rich formatter.
         * @return list of supported features
         */
        public RichFormatterFeature[] getAvailableFeatures() {
            return RichFormatterFeature.values();
        }

        /**
         * Enable a specific feature on this rich formatter.
         * @param feature feature to be enabled
         */
        public void enable(RichFormatterFeature feature) {
            features.add(feature);
        }

        /**
         * Disable a specific feature on this rich formatter.
         * @param feature feature to be disabled
         */
        public void disable(RichFormatterFeature feature) {
            features.remove(feature);
        }

        /**
         * Is a given feature enabled on this formatter?
         * @param feature feature to be tested
         */
        public boolean isEnabled(RichFormatterFeature feature) {
            return features.contains(feature);
        }

        /**
         * The advanced formatting features provided by the rich formatter
         */
        public enum RichFormatterFeature {
            /** a list of additional info regarding a given type/symbol */
            WHERE_CLAUSES,
            /** full class names simplification (where possible) */
            SIMPLE_NAMES,
            /** type-variable names disambiguation */
            UNIQUE_TYPEVAR_NAMES
        }
    }
}
