/*
 * Copyright (c) 2010, 2014, 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.
 *
 * 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.
 */

import java.io.*;
import java.util.*;
import java.util.List;
import javax.tools.*;

import com.sun.tools.javac.api.*;
import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.DiagnosticPart;
import com.sun.tools.javac.api.Formattable.LocalizedString;
import com.sun.tools.javac.code.Flags.Flag;
import com.sun.tools.javac.code.Kinds.KindName;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.file.*;
import com.sun.tools.javac.main.Main;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.parser.Tokens.TokenKind;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration;
import javax.lang.model.SourceVersion;

/**
 * Compiler factory for instances of Example.Compiler that use custom
 * DiagnosticFormatter and Messages objects to track the types of args
 * when when localizing diagnostics.
 * The compiler objects only support "output" mode, not "check" mode.
 */
class ArgTypeCompilerFactory implements Example.Compiler.Factory {
    // Same code as Example.Compiler.DefaultFactory, but the names resolve differently
    public Example.Compiler getCompiler(List<String> opts, boolean verbose) {
        String first;
        String[] rest;
        if (opts == null || opts.isEmpty()) {
            first = null;
            rest = new String[0];
        } else {
            first = opts.get(0);
            rest = opts.subList(1, opts.size()).toArray(new String[opts.size() - 1]);
        }
        if (first == null || first.equals("jsr199"))
            return new Jsr199Compiler(verbose, rest);
        else if (first.equals("simple"))
            return new SimpleCompiler(verbose);
        else if (first.equals("backdoor"))
            return new BackdoorCompiler(verbose);
        else
            throw new IllegalArgumentException(first);
    }

    /**
     * Compile using the JSR 199 API.  The diagnostics generated are
     * scanned for resource keys.   Not all diagnostic keys are generated
     * via the JSR 199 API -- for example, rich diagnostics are not directly
     * accessible, and some diagnostics generated by the file manager may
     * not be generated (for example, the JSR 199 file manager does not see
     * -Xlint:path).
     */
    static class Jsr199Compiler extends Example.Compiler {
        List<String> fmOpts;

        Jsr199Compiler(boolean verbose, String... args) {
            super(verbose);
            for (int i = 0; i < args.length; i++) {
                String arg = args[i];
                if (arg.equals("-filemanager") && (i + 1 < args.length)) {
                    fmOpts = Arrays.asList(args[++i].split(","));
                } else
                    throw new IllegalArgumentException(arg);
            }
        }

        @Override
        boolean run(PrintWriter out, Set<String> keys, boolean raw, List<String> opts, List<File> files) {
            assert out != null && keys == null;

            if (verbose)
                System.err.println("run_jsr199: " + opts + " " + files);

            JavacTool tool = JavacTool.create();

            StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
            if (fmOpts != null)
                fm = new FileManager(fm, fmOpts);

            Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files);

            Context c = initContext();
            JavacTaskImpl t = (JavacTaskImpl) tool.getTask(out, fm, null, opts, null, fos, c);
            return t.call();
        }
    }


    /**
     * Run the test using the standard simple entry point.
     */
    static class SimpleCompiler extends Example.Compiler {
        SimpleCompiler(boolean verbose) {
            super(verbose);
        }

        @Override
        boolean run(PrintWriter out, Set<String> keys, boolean raw, List<String> opts, List<File> files) {
            assert out != null && keys == null;

            if (verbose)
                System.err.println("run_simple: " + opts + " " + files);

            List<String> args = new ArrayList<String>();

            args.addAll(opts);
            for (File f: files)
                args.add(f.getPath());

            Main main = new Main("javac", out);
            Context c = initContext();
            JavacFileManager.preRegister(c); // can't create it until Log has been set up
            Main.Result result = main.compile(args.toArray(new String[args.size()]), c);

            return result.isOK();
        }
    }

    static class BackdoorCompiler extends Example.Compiler {
        BackdoorCompiler(boolean verbose) {
            super(verbose);
        }

        @Override
        boolean run(PrintWriter out, Set<String> keys, boolean raw, List<String> opts, List<File> files) {
            assert out != null && keys == null;

            if (verbose)
                System.err.println("run_simple: " + opts + " " + files);

            List<String> args = new ArrayList<String>(opts);
            for (File f: files)
                args.add(f.getPath());

            Context c = initContext();
            JavacFileManager.preRegister(c); // can't create it until Log has been set up
            Main m = new Main("javac", out);
            Main.Result result = m.compile(args.toArray(new String[args.size()]), c);

            return result.isOK();
        }
    }

    private static Context initContext() {
        Context context = new Context();
        ArgTypeMessages.preRegister(context);
        Options options = Options.instance(context);
        options.addListener(() -> {
            Log log = Log.instance(context);
            log.setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options));
        });
        return context;
    }

    // <editor-fold defaultstate="collapsed" desc="Custom Javac components">

    /**
     * Diagnostic formatter which reports formats a diag as a series of lines
     * containing a key, and a possibly empty set of descriptive strings for the
     * arg types.
     */
    static class ArgTypeDiagnosticFormatter extends AbstractDiagnosticFormatter {

        ArgTypeDiagnosticFormatter(Options options) {
            super(null, new SimpleConfiguration(options,
                    EnumSet.of(DiagnosticPart.SUMMARY,
                    DiagnosticPart.DETAILS,
                    DiagnosticPart.SUBDIAGNOSTICS)));
        }

        @Override
        protected String formatDiagnostic(JCDiagnostic d, Locale locale) {
            return formatMessage(d, locale);
        }

        @Override
        public String formatMessage(JCDiagnostic d, Locale l) {
            StringBuilder buf = new StringBuilder();
            formatMessage(d, buf);
            return buf.toString();
        }

        private void formatMessage(JCDiagnostic d, StringBuilder buf) {
            String key = d.getCode();
            Object[] args = d.getArgs();
            // report the primary arg types, without recursing into diag fragments
            buf.append(getKeyArgsString(key, args));
            // report details for any diagnostic fragments
            for (Object arg: args) {
                if (arg instanceof JCDiagnostic) {
                    buf.append("\n");
                    formatMessage((JCDiagnostic) arg, buf);
                }
            }
            // report details for any subdiagnostics
            for (String s: formatSubdiagnostics(d, null)) {
                buf.append("\n");
                buf.append(s);
            }
        }

        @Override
        public boolean isRaw() {
            return true;
        }
    }

    /**
     * Diagnostic formatter which "localizes" a message as a line
     * containing a key, and a possibly empty set of descriptive strings for the
     * arg types.
     */
    static class ArgTypeMessages extends JavacMessages {
        static void preRegister(Context context) {
            context.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() {
                public JavacMessages make(Context c) {
                    return new ArgTypeMessages(c) {
                        @Override
                        public String getLocalizedString(Locale l, String key, Object... args) {
                            return getKeyArgsString(key, args);
                        }
                    };
                }
            });
        }

        ArgTypeMessages(Context context) {
            super(context);
        }
    }

    /**
     * Utility method to generate a string for key and args
     */
    static String getKeyArgsString(String key, Object... args) {
        StringBuilder buf = new StringBuilder();
        buf.append(key);
        String sep = ": ";
        for (Object o : args) {
            buf.append(sep);
            buf.append(getArgTypeOrStringValue(o));
            sep = ", ";
        }
        return buf.toString();
    }

    static boolean showStringValues = false;

    static String getArgTypeOrStringValue(Object o) {
        if (showStringValues && o instanceof String)
            return "\"" + o + "\"";
        return getArgType(o);
    }

    static String getArgType(Object o) {
        if (o == null)
            return "null";
        if (o instanceof Name)
            return "name";
        if (o instanceof Boolean)
            return "boolean";
        if (o instanceof Integer)
            return "number";
        if (o instanceof String)
            return "string";
        if (o instanceof Flag)
            return "modifier";
        if (o instanceof KindName)
            return "symbol kind";
        if (o instanceof TokenKind)
            return "token";
        if (o instanceof Symbol)
            return "symbol";
        if (o instanceof Type)
            return "type";
        if (o instanceof List) {
            List<?> l = (List<?>) o;
            if (l.isEmpty())
                return "list";
            else
                return "list of " + getArgType(l.get(0));
        }
        if (o instanceof ListBuffer)
            return getArgType(((ListBuffer) o).toList());
        if (o instanceof Set) {
            Set<?> s = (Set<?>) o;
            if (s.isEmpty())
                return "set";
            else
                return "set of " + getArgType(s.iterator().next());
        }
        if (o instanceof SourceVersion)
            return "source version";
        if (o instanceof FileObject || o instanceof File)
            return "file name";
        if (o instanceof JCDiagnostic)
            return "message segment";
        if (o instanceof LocalizedString)
            return "message segment";  // only instance is "no arguments"
        String s = o.getClass().getSimpleName();
        return (s.isEmpty() ? o.getClass().getName() : s);
    }

    // </editor-fold>

}
