/*
 * 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.BufferedReader;
import java.io.FilterReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.Template.WrongEncodingException;
import freemarker.template.Version;
import freemarker.template._TemplateAPI;
import freemarker.template.utility.NullArgumentException;

/**
 * The parsed representation of a template that's not yet bound to the {@link Template} properties that doesn't
 * influence the result of the parsing. This information wasn't separated from {@link Template} in FreeMarker 2.3.x,
 * and was factored out from it into this class in 2.4.0, to allow more efficient caching.
 * 
 * @since 2.4.0
 */
public final class UnboundTemplate {

    public static final String DEFAULT_NAMESPACE_PREFIX = "D";
    public static final String NO_NS_PREFIX = "N";

    private final String sourceName;
    private final Configuration cfg;
    private final ParserConfiguration parserCfg;
    private final Version templateLanguageVersion;
    
    /** Attributes added via {@code <#ftl attributes=...>}. */
    private LinkedHashMap<String, Object> customAttributes;
    private final Map<String, UnboundCallable> unboundCallables = new HashMap<String, UnboundCallable>(0);
    // Earlier it was a Vector, so I thought the safest is to keep it synchronized:
    private final List<LibraryLoad> imports = Collections.synchronizedList(new ArrayList<LibraryLoad>(0));
    private final TemplateElement rootElement;
    private String defaultNamespaceURI;
    private final int actualTagSyntax;
    private final int actualNamingConvention;
    private OutputFormat outputFormat;
    private boolean autoEscaping;
    
    private final String templateSpecifiedEncoding;
    
    private final ArrayList lines = new ArrayList();
    
    private Map<String, String> prefixToNamespaceURIMapping;
    private Map<String, String> namespaceURIToPrefixMapping;

    /**
     * @param reader
     *            Reads the template source code
     * @param cfg
     *            The FreeMarker configuration settings; the resulting {@link UnboundTemplate} will be bound to this.
     * @param customParserCfg
     *            Overrides the parsing related configuration settings of the {@link Configuration} parameter; can be
     *            {@code null}. See the similar paramter of
     *            {@link Template#Template(String, String, Reader, Configuration, ParserConfiguration, String)} for more
     *            details.
     * @param assumedEncoding
     *            This is the name of the charset that we are supposed to be using. This is only needed to check if the
     *            encoding specified in the {@code #ftl} header (if any) matches this. If this is non-{@code null} and
     *            they don't match, a {@link WrongEncodingException} will be thrown by the parser.
     * @param sourceName
     *            Shown in error messages as the template "file" location.
     */
    UnboundTemplate(Reader reader, String sourceName, Configuration cfg, ParserConfiguration customParserCfg,
            String assumedEncoding)
            throws IOException {
        NullArgumentException.check(cfg);
        this.cfg = cfg;
        this.parserCfg = customParserCfg != null ? customParserCfg : cfg;
        this.sourceName = sourceName;
        this.templateLanguageVersion = normalizeTemplateLanguageVersion(
                getParserConfiguration().getIncompatibleImprovements());

        LineTableBuilder ltbReader;
        try {
            if (!(reader instanceof BufferedReader) && !(reader instanceof StringReader)) {
                reader = new BufferedReader(reader, 0x1000);
            }
            ltbReader = new LineTableBuilder(reader);
            reader = ltbReader;

            try {
                FMParser parser = new FMParser(this, reader, assumedEncoding, getParserConfiguration());
                
                TemplateElement rootElement;
                try {
                    rootElement = parser.Root();
                } catch (IndexOutOfBoundsException exc) {
                    // There's a JavaCC bug where the Reader throws a RuntimeExcepton and then JavaCC fails with
                    // IndexOutOfBoundsException. If that wasn't the case, we just rethrow. Otherwise we suppress the
                    // IndexOutOfBoundsException and let the real cause to be thrown later. 
                    if (!ltbReader.hasFailure()) {
                        throw exc;
                    }
                    rootElement = null;
                }
                this.rootElement = rootElement;
                
                this.actualTagSyntax = parser._getLastTagSyntax();
                this.actualNamingConvention = parser._getLastNamingConvention();
                this.templateSpecifiedEncoding = parser._getTemplateSpecifiedEncoding();
            } catch (TokenMgrError exc) {
                // TokenMgrError VS ParseException is not an interesting difference for the user, so we just convert it
                // to ParseException
                throw exc.toParseException(this);
            }
        } catch (ParseException e) {
            e.setTemplateName(getSourceName());
            throw e;
        } finally {
            reader.close();
        }
        
        // Throws any exception that JavaCC has silently treated as EOF:
        ltbReader.throwFailure();

        if (prefixToNamespaceURIMapping != null) {
            prefixToNamespaceURIMapping = Collections.unmodifiableMap(prefixToNamespaceURIMapping);
            namespaceURIToPrefixMapping = Collections.unmodifiableMap(namespaceURIToPrefixMapping);
        }
    }
    
    /**
     * Creates a plain text (unparsed) template. 
     */
    static UnboundTemplate newPlainTextUnboundTemplate(String content, String sourceName, Configuration cfg) {
        UnboundTemplate template;
        try {
            template = new UnboundTemplate(new StringReader("X"), sourceName, cfg, null, null);
        } catch (IOException e) {
            throw new BugException("Plain text template creation failed", e);
        }
        ((TextBlock) template.rootElement).replaceText(content);
        return template;
    }
    
    private static Version normalizeTemplateLanguageVersion(Version incompatibleImprovements) {
        _TemplateAPI.checkVersionNotNullAndSupported(incompatibleImprovements);
        int v = incompatibleImprovements.intValue();
        if (v < _TemplateAPI.VERSION_INT_2_3_19) {
            return Configuration.VERSION_2_3_0;
        } else if (v > _TemplateAPI.VERSION_INT_2_3_21) {
            return Configuration.VERSION_2_3_21;
        } else { // if 2.3.19 or 2.3.20 or 2.3.21
            return incompatibleImprovements;
        }
    }
    
    /**
     * Returns a string representing the raw template text in canonical form.
     */
    @Override
    public String toString() {
        StringWriter sw = new StringWriter();
        try {
            dump(sw);
        } catch (IOException ioe) {
            throw new RuntimeException(ioe.getMessage());
        }
        return sw.toString();
    }

    /**
     * The name that was actually used to load this template from the {@link TemplateLoader} (or from other custom
     * storage mechanism). This is what should be shown in error messages as the error location.
     * 
     * @see Template#getSourceName()
     */
    public String getSourceName() {
        return sourceName;
    }

    /**
     * Return the template language (FTL) version used by this template. For now (2.3.21) this is the same as
     * {@link Configuration#getIncompatibleImprovements()}, except that it's normalized to the lowest version where the
     * template language was changed.
     */
    public Version getTemplateLanguageVersion() {
        return templateLanguageVersion;
    }

    /**
     * See {@link Template#getActualTagSyntax()}.
     */
    public int getActualTagSyntax() {
        return actualTagSyntax;
    }
    
    /**
     * See {@link Template#getActualNamingConvention()}.
     */
    public int getActualNamingConvention() {
        return actualNamingConvention;
    }
    
    /**
     * See {@link Template#getOutputFormat()}.
     */
    public OutputFormat getOutputFormat() {
        return outputFormat;
    }
    
    /**
     * Meant to be called by the parser only. 
     */
    void setOutputFormat(OutputFormat outputFormat) {
        this.outputFormat = outputFormat;
    }
    
    /**
     * See {@link Template#getAutoEscaping()}.
     */
    public boolean getAutoEscaping() {
        return autoEscaping;
    }

    /**
     * Meant to be called by the parser only. 
     */
    void setAutoEscaping(boolean autoEscaping) {
        this.autoEscaping = autoEscaping;
    }
    
    public Configuration getConfiguration() {
        return cfg;
    }
    
    /**
     * Returns the parser configuration that was in effect when creating this template; never {@code null}.
     * See {@link Template#getParserConfiguration()} for details.
     */
    public ParserConfiguration getParserConfiguration() {
        return parserCfg;
    }

    /**
     * Dump the raw template in canonical form.
     */
    public void dump(PrintStream ps) {
        ps.print(rootElement.getCanonicalForm());
    }

    /**
     * Dump the raw template in canonical form.
     */
    public void dump(Writer out) throws IOException {
        out.write(rootElement.getCanonicalForm());
    }

    /**
     * Called by code internally to maintain a table of macros
     */
    void addUnboundCallable(UnboundCallable unboundCallable) {
        unboundCallables.put(unboundCallable.getName(), unboundCallable);
    }

    /**
     * Called by code internally to maintain a list of imports
     */
    void addImport(LibraryLoad libLoad) {
        imports.add(libLoad);
    }

    /**
     * Returns the template source at the location specified by the coordinates given, or {@code null} if unavailable.
     * 
     * @param beginColumn
     *            the first column of the requested source, 1-based
     * @param beginLine
     *            the first line of the requested source, 1-based
     * @param endColumn
     *            the last column of the requested source, 1-based
     * @param endLine
     *            the last line of the requested source, 1-based
     * @see freemarker.core.TemplateObject#getSource()
     */
    public String getSource(int beginColumn,
            int beginLine,
            int endColumn,
            int endLine) {
        if (beginLine < 1 || endLine < 1) return null; // dynamically ?eval-ed expressions has no source available

        // Our container is zero-based.
        --beginLine;
        --beginColumn;
        --endColumn;
        --endLine;
        StringBuilder buf = new StringBuilder();
        for (int i = beginLine; i <= endLine; i++) {
            if (i < lines.size()) {
                buf.append(lines.get(i));
            }
        }
        int lastLineLength = lines.get(endLine).toString().length();
        int trailingCharsToDelete = lastLineLength - endColumn - 1;
        buf.delete(0, beginColumn);
        buf.delete(buf.length() - trailingCharsToDelete, buf.length());
        return buf.toString();
    }

    /**
     * Used internally by the parser.
     */
    void setCustomAttribute(String key, Object value) {
        LinkedHashMap<String, Object> attrs = customAttributes;
        if (attrs == null) {
            attrs = new LinkedHashMap<String, Object>();
            customAttributes = attrs;
        }
        attrs.put(key, value);
    }

    /**
     * Returns the {@link Map} of custom attributes that are normally coming from the {@code #ftl} header, or
     * {@code null} if there was none. The returned {@code Map} must not be modified, and might changes during
     * template parsing as new attributes are added by the parser (i.e., it's not a snapshot).
     */
    Map<String, ?> getCustomAttributes() {
        return this.customAttributes;
    }

    /**
     * @return the root TemplateElement object.
     */
    TemplateElement getRootTreeNode() {
        return rootElement;
    }

    Map<String, UnboundCallable> getUnboundCallables() {
        return unboundCallables;
    }

    List<LibraryLoad> getImports() {
        return imports;
    }

    /**
     * This is used internally.
     */
    void addPrefixToNamespaceURIMapping(String prefix, String nsURI) {
        if (nsURI.length() == 0) {
            throw new IllegalArgumentException("Cannot map empty string URI");
        }
        if (prefix.length() == 0) {
            throw new IllegalArgumentException("Cannot map empty string prefix");
        }
        if (prefix.equals(NO_NS_PREFIX)) {
            throw new IllegalArgumentException("The prefix: " + prefix
                    + " cannot be registered, it's reserved for special internal use.");
        }
        
        if (prefixToNamespaceURIMapping != null) {
            if (prefixToNamespaceURIMapping.containsKey(prefix)) {
                throw new IllegalArgumentException("The prefix: '" + prefix + "' was repeated. This is illegal.");
            }
            if (namespaceURIToPrefixMapping.containsKey(nsURI)) {
                throw new IllegalArgumentException("The namespace URI: " + nsURI
                        + " cannot be mapped to 2 different prefixes.");
            }
        }
        
        if (prefix.equals(DEFAULT_NAMESPACE_PREFIX)) {
            this.defaultNamespaceURI = nsURI;
        } else {
            if (prefixToNamespaceURIMapping == null) {
                prefixToNamespaceURIMapping = new HashMap<String, String>();                
                namespaceURIToPrefixMapping = new HashMap<String, String>();
            }
            prefixToNamespaceURIMapping.put(prefix, nsURI);
            namespaceURIToPrefixMapping.put(nsURI, prefix);
        }
    }

    public String getDefaultNamespaceURI() {
        return this.defaultNamespaceURI;
    }

    /**
     * @return The namespace URI mapped to this node value prefix, or {@code null}.
     */
    public String getNamespaceURIForPrefix(String prefix) {
        if (prefix.equals("")) {
            return defaultNamespaceURI == null ? "" : defaultNamespaceURI;
        }
        
        final Map<String, String> m = prefixToNamespaceURIMapping;
        return m != null ? m.get(prefix) : null;
    }
    
    /**
     * The encoding (charset name) specified by the template itself (as of 2.3.22, via {@code <#ftl encoding=...>}), or
     * {@code null} if none was specified.
     */
    public String getTemplateSpecifiedEncoding() {
        return templateSpecifiedEncoding;
    }

    /**
     * @return the prefix mapped to this nsURI in this template. (Or null if there is none.)
     */
    public String getPrefixForNamespaceURI(String nsURI) {
        if (nsURI == null) {
            return null;
        }
        if (nsURI.length() == 0) {
            return defaultNamespaceURI == null ? "" : NO_NS_PREFIX;
        }
        if (nsURI.equals(defaultNamespaceURI)) {
            return "";
        }
        
        final Map<String, String> m = namespaceURIToPrefixMapping;
        return m != null ? m.get(nsURI) : null;
    }

    /**
     * @return the prefixed name, based on the ns_prefixes defined in this template's header for the local name and node
     *         namespace passed in as parameters.
     */
    public String getPrefixedName(String localName, String nsURI) {
        if (nsURI == null || nsURI.length() == 0) {
            if (defaultNamespaceURI != null) {
                return NO_NS_PREFIX + ":" + localName;
            } else {
                return localName;
            }
        }
        if (nsURI.equals(defaultNamespaceURI)) {
            return localName;
        }
        String prefix = getPrefixForNamespaceURI(nsURI);
        if (prefix == null) {
            return null;
        }
        return prefix + ":" + localName;
    }

    /**
     * @return an array of the {@link TemplateElement}s containing the given column and line numbers.
     */
    List<TemplateElement> containingElements(int column, int line) {
        final ArrayList<TemplateElement> elements = new ArrayList<TemplateElement>();
        TemplateElement element = rootElement;
        mainloop: while (element.contains(column, line)) {
            elements.add(element);
            for (Enumeration enumeration = element.children(); enumeration.hasMoreElements(); ) {
                TemplateElement elem = (TemplateElement) enumeration.nextElement();
                if (elem.contains(column, line)) {
                    element = elem;
                    continue mainloop;
                }
            }
            break;
        }
        return elements.isEmpty() ? null : elements;
    }

    /**
     * Reader that builds up the line table info for us, and also helps in working around JavaCC's exception
     * suppression.
     */
    private class LineTableBuilder extends FilterReader {
        
        private final StringBuilder lineBuf = new StringBuilder();
        int lastChar;
        boolean closed;
        
        /** Needed to work around JavaCC behavior where it silently treats any errors as EOF. */ 
        private Exception failure; 

        /**
         * @param r the character stream to wrap
         */
        LineTableBuilder(Reader r) {
            super(r);
        }
        
        public boolean hasFailure() {
            return failure != null;
        }

        public void throwFailure() throws IOException {
            if (failure != null) {
                if (failure instanceof IOException) {
                    throw (IOException) failure;
                }
                if (failure instanceof RuntimeException) {
                    throw (RuntimeException) failure;
                }
                throw new UndeclaredThrowableException(failure);
            }
        }

        @Override
        public int read() throws IOException {
            try {
                int c = in.read();
                handleChar(c);
                return c;
            } catch (Exception e) {
                throw rememberException(e);
            }
        }

        private IOException rememberException(Exception e) throws IOException {
            // JavaCC used to read from the Reader after it was closed. So we must not treat that as a failure. 
            if (!closed) {
                failure = e;
            }
            if (e instanceof IOException) {
                return (IOException) e;
            }
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            }
            throw new UndeclaredThrowableException(e);
        }

        @Override
        public int read(char cbuf[], int off, int len) throws IOException {
            try {
                int numchars = in.read(cbuf, off, len);
                for (int i = off; i < off + numchars; i++) {
                    char c = cbuf[i];
                    handleChar(c);
                }
                return numchars;
            } catch (Exception e) {
                throw rememberException(e);
            }
        }

        @Override
        public void close() throws IOException {
            if (lineBuf.length() > 0) {
                lines.add(lineBuf.toString());
                lineBuf.setLength(0);
            }
            super.close();
            closed = true;
        }

        private void handleChar(int c) {
            if (c == '\n' || c == '\r') {
                if (lastChar == '\r' && c == '\n') { // CRLF under Windoze
                    int lastIndex = lines.size() - 1;
                    String lastLine = (String) lines.get(lastIndex);
                    lines.set(lastIndex, lastLine + '\n');
                } else {
                    lineBuf.append((char) c);
                    lines.add(lineBuf.toString());
                    lineBuf.setLength(0);
                }
            } else if (c == '\t') {
                int numSpaces = 8 - (lineBuf.length() % 8);
                for (int i = 0; i < numSpaces; i++) {
                    lineBuf.append(' ');
                }
            } else {
                lineBuf.append((char) c);
            }
            lastChar = c;
        }
    }

}
