/*
 * Copyright (c) 2015, 2018, 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 propertiesparser.gen;

import static java.util.stream.Collectors.toList;

import propertiesparser.parser.Message;
import propertiesparser.parser.MessageFile;
import propertiesparser.parser.MessageInfo;
import propertiesparser.parser.MessageLine;
import propertiesparser.parser.MessageType;
import propertiesparser.parser.MessageType.CompoundType;
import propertiesparser.parser.MessageType.CustomType;
import propertiesparser.parser.MessageType.SimpleType;
import propertiesparser.parser.MessageType.UnionType;
import propertiesparser.parser.MessageType.Visitor;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ClassGenerator {

    /** Empty string - used to generate indentation padding. */
    private final static String INDENT_STRING = "                                                                   ";

    /** Default indentation step. */
    private final static int INDENT_WIDTH = 4;

    /** File-backed property file containing basic code stubs. */
    static Properties stubs;

    static {
        //init properties from file
        stubs = new Properties();
        String resourcePath = "/propertiesparser/resources/templates.properties";
        try (InputStream in = ClassGenerator.class.getResourceAsStream(resourcePath)) {
            stubs.load(in);
        } catch (IOException ex) {
            throw new AssertionError(ex);
        }
    }

    /**
     * Supported stubs in the property file.
     */
    enum StubKind {
        TOPLEVEL("toplevel.decl"),
        FACTORY_CLASS("nested.decl"),
        IMPORT("import.decl"),
        FACTORY_METHOD_DECL("factory.decl.method"),
        FACTORY_METHOD_ARG("factory.decl.method.arg"),
        FACTORY_METHOD_BODY("factory.decl.method.body"),
        FACTORY_METHOD_BODY_LINT("factory.decl.method.body.lint"),
        FACTORY_FIELD("factory.decl.field"),
        FACTORY_FIELD_LINT("factory.decl.field.lint"),
        WILDCARDS_EXTENDS("wildcards.extends"),
        SUPPRESS_WARNINGS("suppress.warnings"),
        LINT_CATEGORY("lint.category");

        /** stub key (as it appears in the property file) */
        String key;

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

        /**
         * Subst a list of arguments into a given stub.
         */
        String format(Object... args) {
            return MessageFormat.format((String)stubs.get(key), args);
        }
    }

    /**
     * Nested factory class kind. There are multiple sub-factories, one for each kind of commonly used
     * diagnostics (i.e. error, warnings, note, fragment). An additional category is defined for
     * those resource keys whose prefix doesn't match any predefined category.
     */
    enum FactoryKind {
        ERR("err", "Error", "Errors"),
        WARN("warn", "Warning", "Warnings"),
        LINT_WARN("warn", "LintWarning", "LintWarnings"),
        NOTE("note", "Note", "Notes"),
        MISC("misc", "Fragment", "Fragments"),
        OTHER(null, null, null);

        /** The prefix for this factory kind (i.e. 'err'). */
        String prefix;

        /** The type of the factory method/fields in this class. */
        String keyClazz;

        /** The class name to be used for this factory. */
        String factoryClazz;

        FactoryKind(String prefix, String keyClazz, String factoryClazz) {
            this.prefix = prefix;
            this.keyClazz = keyClazz;
            this.factoryClazz = factoryClazz;
        }

        /**
         * Utility method for parsing a factory kind from a resource key prefix.
         */
        static FactoryKind of(Entry<String, Message> messageEntry) {
            String prefix = messageEntry.getKey().split("\\.")[1];
            FactoryKind selected = null;
            for (FactoryKind k : FactoryKind.values()) {
                if (k.prefix == null || k.prefix.equals(prefix)) {
                    selected = k;
                    break;
                }
            }
            if (selected == WARN) {
                for (MessageLine line : messageEntry.getValue().getLines(false)) {
                    if (line.isLint()) {
                        selected = LINT_WARN;
                        break;
                    }
                }
            }
            return selected;
        }
    }

    /**
     * Main entry-point: generate a Java enum-like set of nested factory classes into given output
     * folder. The factories are populated as mandated by the comments in the input resource file.
     */
    public void generateFactory(MessageFile messageFile, File outDir) {
        Map<FactoryKind, List<Map.Entry<String, Message>>> groupedEntries =
                messageFile.messages.entrySet().stream()
                        .collect(
                                Collectors.groupingBy(
                                        FactoryKind::of,
                                        TreeMap::new,
                                        toList()));
        //generate nested classes
        List<String> nestedDecls = new ArrayList<>();
        Set<String> importedTypes = new TreeSet<>();
        for (Map.Entry<FactoryKind, List<Map.Entry<String, Message>>> entry : groupedEntries.entrySet()) {
            if (entry.getKey() == FactoryKind.OTHER) continue;
            //emit members
            String members = entry.getValue().stream()
                    .flatMap(e -> generateFactoryMethodsAndFields(entry.getKey(), e.getKey(), e.getValue()).stream())
                    .collect(Collectors.joining("\n\n"));
            //emit nested class
            String factoryDecl =
                    StubKind.FACTORY_CLASS.format(entry.getKey().factoryClazz, indent(members, 1));
            nestedDecls.add(indent(factoryDecl, 1));
            //add imports
            entry.getValue().stream().forEach(e ->
                    importedTypes.addAll(importedTypes(e.getValue().getMessageInfo().getTypes())));
        }
        String clazz = StubKind.TOPLEVEL.format(
                packageName(messageFile.file),
                String.join("\n", generateImports(importedTypes)),
                toplevelName(messageFile.file),
                String.join("\n", nestedDecls));
        try (FileWriter fw = new FileWriter(new File(outDir, toplevelName(messageFile.file) + ".java"))) {
            fw.append(clazz);
        } catch (Throwable ex) {
            throw new AssertionError(ex);
        }
    }

    /**
     * Indent a string to a given level.
     */
    String indent(String s, int level) {
        return Stream.of(s.split("\n"))
                .map(sub -> INDENT_STRING.substring(0, level * INDENT_WIDTH) + sub)
                .collect(Collectors.joining("\n"));
    }

    /**
     * Retrieve package part of given file object.
     */
    String packageName(File file) {
        String path = file.getAbsolutePath();
        int begin = path.lastIndexOf(File.separatorChar + "com" + File.separatorChar);
        String packagePath = path.substring(begin + 1, path.lastIndexOf(File.separatorChar));
        String packageName =  packagePath.replace(File.separatorChar, '.');
        return packageName;
    }

    /**
     * Form the name of the toplevel factory class.
     */
    public static String toplevelName(File file) {
        return Stream.of(file.getName().split("\\."))
                .map(s -> Character.toUpperCase(s.charAt(0)) + s.substring(1))
                .collect(Collectors.joining(""));
    }

    /**
     * Generate a list of import declarations given a set of imported types.
     */
    List<String> generateImports(Set<String> importedTypes) {
        List<String> importDecls = new ArrayList<>();
        for (String it : importedTypes) {
            importDecls.add(StubKind.IMPORT.format(it));
        }
        return importDecls;
    }

    /**
     * Generate a list of factory methods/fields to be added to a given factory nested class.
     */
    List<String> generateFactoryMethodsAndFields(FactoryKind k, String key, Message msg) {
        MessageInfo msgInfo = msg.getMessageInfo();
        List<MessageLine> lines = msg.getLines(false);
        String javadoc = lines.stream()
                .filter(ml -> !ml.isInfo() && !ml.isEmptyOrComment())
                .map(ml -> ml.text)
                .collect(Collectors.joining("\n *"));
        String[] keyParts = key.split("\\.");
        String lintCategory = lines.stream()
                .filter(MessageLine::isLint)
                .map(MessageLine::lintCategory)
                .findFirst().orElse(null);
        //System.out.println("category for " + key + " = " + lintCategory);
        String factoryName = factoryName(key);
        if (msgInfo.getTypes().isEmpty()) {
            //generate field
            String factoryField;
            if (lintCategory == null) {
                factoryField = StubKind.FACTORY_FIELD.format(k.keyClazz, factoryName,
                        "\"" + keyParts[0] + "\"",
                        "\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"",
                        javadoc);
            } else {
                factoryField = StubKind.FACTORY_FIELD_LINT.format(k.keyClazz, factoryName,
                        StubKind.LINT_CATEGORY.format("\"" + lintCategory + "\""),
                        "\"" + keyParts[0] + "\"",
                        "\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"",
                        javadoc);
            }
            return Collections.singletonList(factoryField);
        } else {
            //generate method
            List<String> factoryMethods = new ArrayList<>();
            for (List<MessageType> msgTypes : normalizeTypes(0, msgInfo.getTypes())) {
                List<String> types = generateTypes(msgTypes);
                List<String> argNames = argNames(types.size());
                String suppressionString = needsSuppressWarnings(msgTypes) ?
                        StubKind.SUPPRESS_WARNINGS.format() : "";
                String methodBody;
                if (lintCategory == null) {
                    methodBody = StubKind.FACTORY_METHOD_BODY.format(k.keyClazz,
                            "\"" + keyParts[0] + "\"",
                            "\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"",
                            argNames.stream().collect(Collectors.joining(", ")));
                } else {
                    methodBody = StubKind.FACTORY_METHOD_BODY_LINT.format(k.keyClazz,
                            StubKind.LINT_CATEGORY.format("\"" + lintCategory + "\""),
                            "\"" + keyParts[0] + "\"",
                            "\"" + Stream.of(keyParts).skip(2).collect(Collectors.joining(".")) + "\"",
                            argNames.stream().collect(Collectors.joining(", ")));
                }
                String factoryMethod = StubKind.FACTORY_METHOD_DECL.format(suppressionString, k.keyClazz,
                        factoryName, argDecls(types, argNames).stream().collect(Collectors.joining(", ")),
                        indent(methodBody, 1),
                        javadoc);
                factoryMethods.add(factoryMethod);
            }
            return factoryMethods;
        }
    }

    /**
     * Form the name of a factory method/field given a resource key.
     */
    String factoryName(String key) {
        return Stream.of(key.split("[\\.-]"))
                .skip(2)
                .map(s -> Character.toUpperCase(s.charAt(0)) + s.substring(1))
                .collect(Collectors.joining(""));
    }

    /**
     * Generate a formal parameter list given a list of types and names.
     */
    List<String> argDecls(List<String> types, List<String> args) {
        List<String> argNames = new ArrayList<>();
        for (int i = 0 ; i < types.size() ; i++) {
            argNames.add(types.get(i) + " " + args.get(i));
        }
        return argNames;
    }

    /**
     * Generate a list of formal parameter names given a size.
     */
    List<String> argNames(int size) {
        List<String> argNames = new ArrayList<>();
        for (int i = 0 ; i < size ; i++) {
            argNames.add(StubKind.FACTORY_METHOD_ARG.format(i));
        }
        return argNames;
    }

    /**
     * Convert a (normalized) parsed type into a string-based representation of some Java type.
     */
    List<String> generateTypes(List<MessageType> msgTypes) {
        return msgTypes.stream().map(t -> t.accept(stringVisitor, null)).collect(Collectors.toList());
    }
    //where
        Visitor<String, Void> stringVisitor = new Visitor<String, Void>() {
            @Override
            public String visitCustomType(CustomType t, Void aVoid) {
                String customType = t.typeString;
                return customType.substring(customType.lastIndexOf('.') + 1);
            }

            @Override
            public String visitSimpleType(SimpleType t, Void aVoid) {
                return t.clazz;
            }

            @Override
            public String visitCompoundType(CompoundType t, Void aVoid) {
                return StubKind.WILDCARDS_EXTENDS.format(t.kind.clazz.clazz,
                        t.elemtype.accept(this, null));
            }

            @Override
            public String visitUnionType(UnionType t, Void aVoid) {
                throw new AssertionError("Union types should have been denormalized!");
            }
        };

    /**
     * See if any of the parsed types in the given list needs warning suppression.
     */
    boolean needsSuppressWarnings(List<MessageType> msgTypes) {
        return msgTypes.stream().anyMatch(t -> t.accept(suppressWarningsVisitor, null));
    }
    //where
    Visitor<Boolean, Void> suppressWarningsVisitor = new Visitor<Boolean, Void>() {
        @Override
        public Boolean visitCustomType(CustomType t, Void aVoid) {
            //play safe
            return true;
        }
        @Override
        public Boolean visitSimpleType(SimpleType t, Void aVoid) {
            switch (t) {
                case LIST:
                case SET:
                    return true;
                default:
                    return false;
            }
        }

        @Override
        public Boolean visitCompoundType(CompoundType t, Void aVoid) {
            return t.elemtype.accept(this, null);
        }

        @Override
        public Boolean visitUnionType(UnionType t, Void aVoid) {
            return needsSuppressWarnings(Arrays.asList(t.choices));
        }
    };

    /**
     * Retrieve a list of types that need to be imported, so that the factory body can refer
     * to the types in the given list using simple names.
     */
    Set<String> importedTypes(List<MessageType> msgTypes) {
        Set<String> imports = new TreeSet<>();
        msgTypes.forEach(t -> t.accept(importVisitor, imports));
        return imports;
    }
    //where
    Visitor<Void, Set<String>> importVisitor = new Visitor<Void, Set<String>>() {
        @Override
        public Void visitCustomType(CustomType t, Set<String> imports) {
            imports.add(t.typeString);
            return null;
        }

        @Override
        public Void visitSimpleType(SimpleType t, Set<String> imports) {
            if (t.qualifier != null) {
                imports.add(t.qualifier + "." + t.clazz);
            }
            return null;
        }

        @Override
        public Void visitCompoundType(CompoundType t, Set<String> imports) {
            visitSimpleType(t.kind.clazz, imports);
            t.elemtype.accept(this, imports);
            return null;
        }

        @Override
        public Void visitUnionType(UnionType t, Set<String> imports) {
            Stream.of(t.choices).forEach(c -> c.accept(this, imports));
            return null;
        }
    };

    /**
     * Normalize parsed types in a comment line. If one or more types in the line contains alternatives,
     * this routine generate a list of 'overloaded' normalized signatures.
     */
    List<List<MessageType>> normalizeTypes(int idx, List<MessageType> msgTypes) {
        if (msgTypes.size() == idx) return Collections.singletonList(Collections.emptyList());
        MessageType head = msgTypes.get(idx);
        List<List<MessageType>> buf = new ArrayList<>();
        for (MessageType alternative : head.accept(normalizeVisitor, null)) {
            for (List<MessageType> rest : normalizeTypes(idx + 1, msgTypes)) {
                List<MessageType> temp = new ArrayList<>(rest);
                temp.add(0, alternative);
                buf.add(temp);
            }
        }
        return buf;
    }
    //where
    Visitor<List<MessageType>, Void> normalizeVisitor = new Visitor<List<MessageType>, Void>() {
        @Override
        public List<MessageType> visitCustomType(CustomType t, Void aVoid) {
            return Collections.singletonList(t);
        }

        @Override
        public List<MessageType> visitSimpleType(SimpleType t, Void aVoid) {
            return Collections.singletonList(t);
        }

        @Override
        public List<MessageType> visitCompoundType(CompoundType t, Void aVoid) {
            return t.elemtype.accept(this, null).stream()
                    .map(nt -> new CompoundType(t.kind, nt))
                    .collect(Collectors.toList());
        }

        @Override
        public List<MessageType> visitUnionType(UnionType t, Void aVoid) {
            return Stream.of(t.choices)
                    .flatMap(t2 -> t2.accept(this, null).stream())
                    .collect(Collectors.toList());
        }
    };
}
