/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package freemarker.core;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CodingErrorAction;
import java.util.Enumeration;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateModel;
import freemarker.template.utility.ClassUtil;
import freemarker.template.utility.StringUtil;

/**
 * Static methods and command-line tool for printing the AST of a template. 
 */
public class ASTPrinter {

    private final Configuration cfg;
    private int successfulCounter;
    private int failedCounter;
    
    static public void main(String[] args) throws IOException {
        if (args.length == 0) {
            usage();
            System.exit(-1);
        }
        
        ASTPrinter astp = new ASTPrinter(); 
        if (args[0].equalsIgnoreCase("-r")) {
            astp.mainRecursive(args);
        } else {
            astp.mainSingleTemplate(args);
        }
    }
    
    private ASTPrinter() {
        cfg = new Configuration();
        cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_20);
    }
    
    private void mainSingleTemplate(String[] args) throws IOException, FileNotFoundException {
        final String templateFileName;
        final String templateContent;
        if (args[0].startsWith("ftl:")) {
            templateFileName = null;
            templateContent = args[0];
        } else {
            templateFileName = args[0];
            templateContent = null;
        }
        
        Template t = new Template(
                templateFileName,
                templateFileName == null ? new StringReader(templateContent) : new FileReader(templateFileName),
                cfg);
        
        p(getASTAsString(t));
    }

    private void mainRecursive(String[] args) throws IOException {
        if (args.length != 4) {
            p("Number of arguments must be 4, but was: " + args.length);
            usage();
            System.exit(-1);
        }
        
        final String srcDirPath = args[1].trim();
        File srcDir = new File(srcDirPath);
        if (!srcDir.isDirectory()) {
            p("This should be an existing directory: " + srcDirPath);
            System.exit(-1);
        }
        
        Pattern fnPattern;
        try {
            fnPattern = Pattern.compile(args[2]);
        } catch (PatternSyntaxException e) {
            p(StringUtil.jQuote(args[2]) + " is not a valid regular expression");
            System.exit(-1);
            return;
        }
        
        final String dstDirPath = args[3].trim();
        File dstDir = new File(dstDirPath);
        if (!dstDir.isDirectory()) {
            p("This should be an existing directory: " + dstDirPath);
            System.exit(-1);
        }
        
        long startTime = System.currentTimeMillis();
        recurse(srcDir, fnPattern, dstDir);
        long endTime = System.currentTimeMillis();
        
        p("Templates successfully processed " + successfulCounter + ", failed " + failedCounter
                + ". Time taken: " + (endTime - startTime) / 1000.0 + " s");
    }
    
    private void recurse(File srcDir, Pattern fnPattern, File dstDir) throws IOException {
        File[] files = srcDir.listFiles();
        if (files == null) {
            throw new IOException("Failed to kust directory: " + srcDir);
        }
        for (File file : files) {
            if (file.isDirectory()) {
                recurse(file, fnPattern, new File(dstDir, file.getName()));
            } else {
                if (fnPattern.matcher(file.getName()).matches()) {
                    File dstFile = new File(dstDir, file.getName());
                    String res;
                    try {
                        Template t = new Template(file.getPath().replace('\\', '/'), loadIntoString(file), cfg);
                        res = getASTAsString(t);
                        successfulCounter++;
                    } catch (ParseException e) {
                        res = "<<<FAILED>>>\n" + e.getMessage();
                        failedCounter++;
                        p("");
                        p("-------------------------failed-------------------------");
                        p("Error message was saved into: " + dstFile.getAbsolutePath());
                        p("");
                        p(e.getMessage());
                    }
                    save(res, dstFile);
                }
            }
        }
    }

    private String loadIntoString(File file) throws IOException {
        long ln = file.length();
        if (ln < 0) {
            throw new IOException("Failed to get the length of " + file);
        }
        byte[] buffer = new byte[(int) ln];
        InputStream in = new FileInputStream(file);
        try {
            int offset = 0;
            int bytesRead;
            while (offset < buffer.length) {
                bytesRead = in.read(buffer, offset, buffer.length - offset);
                if (bytesRead == -1) {
                    throw new IOException("Unexpected end of file: " + file);
                }
                offset += bytesRead;
            }
        } finally {
            in.close();
        }
        
        try {
            return decode(buffer, Charset.forName("UTF-8"));
        } catch (CharacterCodingException e) {
            return decode(buffer, Charset.forName("ISO-8859-1"));
        }
    }

    private String decode(byte[] buffer, Charset charset) throws CharacterCodingException {
        return charset.newDecoder()
                .onMalformedInput(CodingErrorAction.REPORT).onUnmappableCharacter(CodingErrorAction.REPORT)
                .decode(ByteBuffer.wrap(buffer)).toString();
    }

    private void save(String astStr, File file) throws IOException {
        File parentDir = file.getParentFile();
        if (!parentDir.isDirectory() && !parentDir.mkdirs()) {
            throw new IOException("Failed to create parent directory: " + parentDir);
        }
        
        Writer w = new BufferedWriter(new FileWriter(file));
        try {
            w.write(astStr);
        } finally {
            w.close();
        }
    }

    private static void usage() {
        p("Prints template Abstract Syntax Tree (AST) as plain text.");
        p("Usage:");
        p("    java freemarker.core.PrintAST <templateFile>");
        p("    java freemarker.core.PrintAST ftl:<templateSource>");
        p("    java freemarker.core.PrintAST -r <src-directory> <regexp> <dst-directory>");
    }

    private static final String INDENTATION = "    ";

    public static String getASTAsString(String ftl) throws IOException {
        return getASTAsString(ftl, (Options) null);
    }
    
    public static String getASTAsString(String ftl, Options opts) throws IOException {
        return getASTAsString(null, ftl, opts);
    }

    public static String getASTAsString(String templateName, String ftl) throws IOException {
        return getASTAsString(templateName, ftl, null);
    }
    
    public static String getASTAsString(String templateName, String ftl, Options opts) throws IOException {
        Configuration cfg = new Configuration();
        Template t = new Template(templateName, ftl, cfg);
        return getASTAsString(t, opts);
    }

    public static String getASTAsString(Template t) throws IOException {
        return getASTAsString(t, null);
    }

    public static String getASTAsString(Template t, Options opts) throws IOException {
        validateAST(t);
        
        StringWriter out = new StringWriter();
        printNode(t.getRootTreeNode(), "", null, opts != null ? opts : Options.DEFAULT_INSTANCE, out);
        return out.toString();
    }
    
    public static void validateAST(Template t) throws InvalidASTException {
        final TemplateElement node = t.getRootTreeNode();
        if (node.getParentElement() != null) {
            throw new InvalidASTException("Root node parent must be null."
                    + "\nRoot node: " + node.dump(false)
                    + "\nParent"
                    + ": " + node.getParentElement().getClass() + ", " + node.getParentElement().dump(false));
        }
        validateAST(node);
    }

    private static void validateAST(TemplateElement te) {
        int childCount = te.getChildCount();
        for (int i = 0; i < childCount; i++) {
            TemplateElement child = te.getChild(i);
            TemplateElement parentElement = child.getParentElement();
            // As MixedContent.accept does nothing but return its regulatedChildren, it's optimized out in the final
            // AST tree. While it will be present as a child, the parent element also will have regularedChildren
            // that contains the children of the MixedContent directly. 
            if (parentElement instanceof MixedContent && parentElement.getParentElement() != null) {
                parentElement = parentElement.getParentElement();
            }
            if (parentElement != te) {
                throw new InvalidASTException("Wrong parent node."
                        + "\nNode: " + child.dump(false)
                        + "\nExpected parent: " + te.dump(false)
                        + "\nActual parent: " + parentElement.dump(false));
            }
            if (child.getIndex() != i) {
                throw new InvalidASTException("Wrong node index."
                        + "\nNode: " + child.dump(false)
                        + "\nExpected index: " + i
                        + "\nActual index: " + child.getIndex());
            }
        }
        if (te instanceof MixedContent && te.getChildCount() < 2) {
            throw new InvalidASTException("Mixed content with child count less than 2 should removed by optimizatoin, "
                    + "but found one with " + te.getChildCount() + " child(ren).");
        }
        TemplateElement[] regulatedChildren = te.getChildBuffer();
        if (regulatedChildren != null) {
            if (childCount == 0) {
                throw new InvalidASTException(
                        "regularChildren must be null when regularChild is 0."
                        + "\nNode: " + te.dump(false));
            }
            for (int i = 0; i < te.getChildCount(); i++) {
                if (regulatedChildren[i] == null) {
                    throw new InvalidASTException(
                            "regularChildren can't be null at index " + i
                            + "\nNode: " + te.dump(false));
                }
            }
            for (int i = te.getChildCount(); i < regulatedChildren.length; i++) {
                if (regulatedChildren[i] != null) {
                    throw new InvalidASTException(
                            "regularChildren can't be non-null at index " + i
                            + "\nNode: " + te.dump(false));
                }
            }
        } else {
            if (childCount != 0) {
                throw new InvalidASTException(
                        "regularChildren mustn't be null when regularChild isn't 0."
                        + "\nNode: " + te.dump(false));
            }
        }
    }

    private static void printNode(Object node, String ind, ParameterRole paramRole, Options opts, Writer out) throws IOException {
        if (node instanceof TemplateObject) {
            TemplateObject tObj = (TemplateObject) node;

            printNodeLineStart(paramRole, ind, out);
            out.write(tObj.getNodeTypeSymbol());
            printNodeLineEnd(node, out, opts);
            
            if (opts.getShowConstantValue() && node instanceof Expression) {
                TemplateModel tm = ((Expression) node).constantValue;
                if (tm != null) {
                    out.write(INDENTATION);
                    out.write(ind);
                    out.write("= const ");
                    out.write(ClassUtil.getFTLTypeDescription(tm));
                    out.write(' ');
                    out.write(tm.toString());
                    out.write('\n');
                }
            }
            
            int paramCnt = tObj.getParameterCount();
            for (int i = 0; i < paramCnt; i++) {
                ParameterRole role = tObj.getParameterRole(i);
                if (role == null) throw new NullPointerException("parameter role");
                Object value = tObj.getParameterValue(i);
                printNode(value, ind + INDENTATION, role, opts, out);
            }
            if (tObj instanceof TemplateElement) {
                Enumeration enu = ((TemplateElement) tObj).children();
                while (enu.hasMoreElements()) {
                    printNode(enu.nextElement(), INDENTATION + ind, null, opts, out);
                }
            }
        } else {
            printNodeLineStart(paramRole, ind, out);
            out.write(StringUtil.jQuote(node));
            printNodeLineEnd(node, out, opts);
        }
    }

    protected static void printNodeLineEnd(Object node, Writer out, Options opts) throws IOException {
        boolean commentStared = false;
        if (opts.getShowJavaClass()) {
            out.write("  // ");
            commentStared = true;
            out.write(ClassUtil.getShortClassNameOfObject(node, true));
        }
        if (opts.getShowLocation() && node instanceof TemplateObject) {
            if (!commentStared) {
                out.write("  // ");
                commentStared = true;
            } else {
                out.write("; ");
            }
            TemplateObject tObj = (TemplateObject) node;
            out.write("Location " + tObj.beginLine + ":" + tObj.beginColumn + "-" + tObj.endLine + ":" + tObj.endColumn);
        }
        out.write('\n');
    }

    private static void printNodeLineStart(ParameterRole paramRole, String ind, Writer out) throws IOException {
        out.write(ind);
        if (paramRole != null) {
            out.write("- ");
            out.write(paramRole.toString());
            out.write(": ");
        }
    }
    
    public static class Options {
        
        private final static Options DEFAULT_INSTANCE = new Options(); 
        
        private boolean showJavaClass = true;
        private boolean showConstantValue = false;
        private boolean showLocation = false;
        
        public boolean getShowJavaClass() {
            return showJavaClass;
        }
        
        public void setShowJavaClass(boolean showJavaClass) {
            this.showJavaClass = showJavaClass;
        }
        
        public boolean getShowConstantValue() {
            return showConstantValue;
        }
        
        public void setShowConstantValue(boolean showConstantValue) {
            this.showConstantValue = showConstantValue;
        }

        public boolean getShowLocation() {
            return showLocation;
        }

        public void setShowLocation(boolean showLocation) {
            this.showLocation = showLocation;
        }
        
    }
    
    private static void p(Object obj) {
        System.out.println(obj);
    }

    public static class InvalidASTException extends RuntimeException {

        public InvalidASTException(String message, Throwable cause) {
            super(message, cause);
        }

        public InvalidASTException(String message) {
            super(message);
        }
        
    }
}
