/*
 * 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.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template._TemplateAPI;
import freemarker.template.utility.ClassUtil;


/**
 * For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
 * This class is to work around the lack of module system in Java, i.e., so that other FreeMarker packages can
 * access things inside this package that users shouldn't. 
 */ 
public class _CoreAPI {
    
    public static final String ERROR_MESSAGE_HR = "----";

    // Can't be instantiated
    private _CoreAPI() { }

    private static void addName(Set<String> allNames, Set<String> lcNames, Set<String> ccNames,
            String commonName) {
        allNames.add(commonName);
        lcNames.add(commonName);
        ccNames.add(commonName);
    }
    
    private static void addName(Set<String> allNames, Set<String> lcNames, Set<String> ccNames,
            String lcName, String ccName) {
        allNames.add(lcName);
        allNames.add(ccName);
        lcNames.add(lcName);
        ccNames.add(ccName);
    }
    
    public static final Set<String> ALL_BUILT_IN_DIRECTIVE_NAMES;
    public static final Set<String> LEGACY_BUILT_IN_DIRECTIVE_NAMES;
    public static final Set<String> CAMEL_CASE_BUILT_IN_DIRECTIVE_NAMES;
    static {
        Set<String> allNames = new TreeSet();
        Set<String> lcNames = new TreeSet();
        Set<String> ccNames = new TreeSet();
        
        addName(allNames, lcNames, ccNames, "assign");
        addName(allNames, lcNames, ccNames, "attempt");
        addName(allNames, lcNames, ccNames, "autoesc", "autoEsc");
        addName(allNames, lcNames, ccNames, "break");
        addName(allNames, lcNames, ccNames, "call");
        addName(allNames, lcNames, ccNames, "case");
        addName(allNames, lcNames, ccNames, "comment");
        addName(allNames, lcNames, ccNames, "compress");
        addName(allNames, lcNames, ccNames, "default");
        addName(allNames, lcNames, ccNames, "else");
        addName(allNames, lcNames, ccNames, "elseif", "elseIf");
        addName(allNames, lcNames, ccNames, "escape");
        addName(allNames, lcNames, ccNames, "fallback");
        addName(allNames, lcNames, ccNames, "flush");
        addName(allNames, lcNames, ccNames, "foreach", "forEach");
        addName(allNames, lcNames, ccNames, "ftl");
        addName(allNames, lcNames, ccNames, "function");
        addName(allNames, lcNames, ccNames, "global");
        addName(allNames, lcNames, ccNames, "if");
        addName(allNames, lcNames, ccNames, "import");
        addName(allNames, lcNames, ccNames, "include");
        addName(allNames, lcNames, ccNames, "items");
        addName(allNames, lcNames, ccNames, "list");
        addName(allNames, lcNames, ccNames, "local");
        addName(allNames, lcNames, ccNames, "lt");
        addName(allNames, lcNames, ccNames, "macro");
        addName(allNames, lcNames, ccNames, "nested");
        addName(allNames, lcNames, ccNames, "noautoesc", "noAutoEsc");
        addName(allNames, lcNames, ccNames, "noescape", "noEscape");
        addName(allNames, lcNames, ccNames, "noparse", "noParse");
        addName(allNames, lcNames, ccNames, "nt");
        addName(allNames, lcNames, ccNames, "outputformat", "outputFormat");
        addName(allNames, lcNames, ccNames, "recover");
        addName(allNames, lcNames, ccNames, "recurse");
        addName(allNames, lcNames, ccNames, "return");
        addName(allNames, lcNames, ccNames, "rt");
        addName(allNames, lcNames, ccNames, "sep");
        addName(allNames, lcNames, ccNames, "setting");
        addName(allNames, lcNames, ccNames, "stop");
        addName(allNames, lcNames, ccNames, "switch");
        addName(allNames, lcNames, ccNames, "t");
        addName(allNames, lcNames, ccNames, "transform");
        addName(allNames, lcNames, ccNames, "visit");
        
        ALL_BUILT_IN_DIRECTIVE_NAMES = Collections.unmodifiableSet(allNames);
        LEGACY_BUILT_IN_DIRECTIVE_NAMES = Collections.unmodifiableSet(lcNames);
        CAMEL_CASE_BUILT_IN_DIRECTIVE_NAMES = Collections.unmodifiableSet(ccNames);
    }
    
    /**
     * Returns the names of the currently supported "built-ins" ({@code expr?builtin_name}-like things).
     * 
     * @param namingConvention
     *            One of {@link Configuration#AUTO_DETECT_NAMING_CONVENTION},
     *            {@link Configuration#LEGACY_NAMING_CONVENTION}, and
     *            {@link Configuration#CAMEL_CASE_NAMING_CONVENTION}. If it's
     *            {@link Configuration#AUTO_DETECT_NAMING_CONVENTION} then the union of the names in all the naming
     *            conventions is returned.
     */
    public static Set<String> getSupportedBuiltInNames(int namingConvention) {
        Set<String> names;
        if (namingConvention == Configuration.AUTO_DETECT_NAMING_CONVENTION) {
            names = BuiltIn.BUILT_INS_BY_NAME.keySet();
        } else if (namingConvention == Configuration.LEGACY_NAMING_CONVENTION) {
            names = BuiltIn.SNAKE_CASE_NAMES;
        } else if (namingConvention == Configuration.CAMEL_CASE_NAMING_CONVENTION) {
            names = BuiltIn.CAMEL_CASE_NAMES;
        } else {
            throw new IllegalArgumentException("Unsupported naming convention constant: " + namingConvention);
        }
        return Collections.unmodifiableSet(names);
    }
    
    public static void appendInstructionStackItem(TemplateElement stackEl, StringBuilder sb) {
        Environment.appendInstructionStackItem(stackEl, sb);
    }
    
    public static TemplateElement[] getInstructionStackSnapshot(Environment env) {
        return env.getInstructionStackSnapshot();
    }
    
    public static void outputInstructionStack(
            TemplateElement[] instructionStackSnapshot, boolean terseMode, Writer pw) {
        Environment.outputInstructionStack(instructionStackSnapshot, terseMode, pw);
    }

    public static Map<String, ?> getCustomAttributes(UnboundTemplate unboundTemplate) {
        return unboundTemplate.getCustomAttributes();
    }
    
    /**
     * For emulating legacy {@link Template#addMacro(Macro)}.
     */
    public static void addMacro(UnboundTemplate unboundTemplate, Macro macro) {
        final UnboundCallable unboundCallable = macroToUnboundCallable(macro);
        unboundTemplate.addUnboundCallable(unboundCallable);
    }

    /**
     * In 2.4 {@link Macro} was split to {@link BoundCallable} and {@link UnboundCallable}, but because of BC
     * constraints sometimes we can only expect a {@link Macro}, but that can always converted to
     * {@link UnboundCallable}.
     */
    private static UnboundCallable macroToUnboundCallable(Macro macro) {
        if (macro instanceof UnboundCallable) {
            // It's coming from the AST:
            return (UnboundCallable) macro;
        } else if (macro instanceof BoundCallable) {
            // It's coming from an FTL variable:
            return ((BoundCallable) macro).getUnboundCallable(); 
        } else if (macro == null) {
            return null;
        } else {
            // Impossible, Macro should have only two subclasses.
            throw new BugException();
        }
    }

    public static void addImport(UnboundTemplate unboundTemplate, LibraryLoad libLoad) {
        unboundTemplate.addImport(libLoad);
    }
    
    public static UnboundTemplate newUnboundTemplate(Reader reader, String sourceName,
            Configuration cfg, ParserConfiguration parserCfg, String assumedEncoding) throws IOException {
        return new UnboundTemplate(reader, sourceName, cfg, parserCfg, assumedEncoding);
    }
    
    public static boolean isBoundCallable(Object obj) {
        return obj instanceof BoundCallable;
    }

    public static UnboundTemplate newPlainTextUnboundTemplate(String content, String sourceName, Configuration config) {
        return UnboundTemplate.newPlainTextUnboundTemplate(content, sourceName, config);
    }
    
    /** Used for implementing the deprecated {@link Template} method with similar name. */
    public static TemplateElement getRootTreeNode(UnboundTemplate unboundTemplate) {
        return unboundTemplate.getRootTreeNode();
    }
    
    /** Used for implementing the deprecated {@link Template} method with similar name. */
    public static Map<String, UnboundCallable> getUnboundCallables(UnboundTemplate unboundTemplate) {
        return unboundTemplate.getUnboundCallables();
    }

    /** Used for implementing the deprecated {@link Template} method with similar name. */
    public static List getImports(UnboundTemplate unboundTemplate) {
        return unboundTemplate.getImports();
    }
    
    /** Used for implementing the deprecated {@link Template} method with similar name. */
    public static void addPrefixNSMapping(UnboundTemplate unboundTemplate, String prefix, String nsURI) {
        unboundTemplate.addPrefixToNamespaceURIMapping(prefix, nsURI);
    }
    
    /** Used for implementing the deprecated {@link Template} method with similar name. */
    public static List<TemplateElement> containingElements(UnboundTemplate unboundTemplate, int column, int line) {
        return unboundTemplate.containingElements(column, line);
    }
    
    /**
     * ATTENTION: This is used by https://github.com/kenshoo/freemarker-online. Don't break backward
     * compatibility without updating that project too! 
     */
    static final public void addThreadInterruptedChecks(Template template) {
        try {
            new ThreadInterruptionSupportTemplatePostProcessor().postProcess(template);
        } catch (TemplatePostProcessorException e) {
            throw new RuntimeException("Template post-processing failed", e);
        }
    }
    
    static final public void checkHasNoNestedContent(TemplateDirectiveBody body)
            throws NestedContentNotSupportedException {
        NestedContentNotSupportedException.check(body);
    }

    public static Map<String, Macro> createAdapterMacroMapForUnboundCallables(UnboundTemplate unboundTemplate) {
        return new AdapterMacroMap(getUnboundCallables(unboundTemplate));
    }
    
    /**
     * Wraps a {@code Map<String, UnboundCallable>} as if it was a {@code Map<String, Macro>}. This is for backward
     * compatibility. The important use case is being able to put any {@link Macro} subclass into this {@code Map},
     * despite that the backing {@link Macro} can only store {@code UnboundCallable}. Reading works a bit strangely,
     * because if you put a non-{@link UnboundCallable} value in, then get it with the same key, you get the
     * corresponding {@link UnboundCallable} back instead of the original object. That's also a {@code Macro} though. 
     */
    private static class AdapterMacroMap implements Map<String, Macro> {
        
        private final Map<String, UnboundCallable> adapted;

        public AdapterMacroMap(Map<String, UnboundCallable> unboundCallableMap) {
            this.adapted = unboundCallableMap;
        }

        public int size() {
            return adapted.size();
        }

        public boolean isEmpty() {
            return adapted.isEmpty();
        }

        public boolean containsKey(Object key) {
            return adapted.containsKey(key);
        }

        public boolean containsValue(Object value) {
            return adapted.containsValue(value);
        }

        public UnboundCallable get(Object key) {
            return adapted.get(key);
        }

        public UnboundCallable put(String key, Macro value) {
            return adapted.put(key, macroToUnboundCallable(value));
        }

        public UnboundCallable remove(Object key) {
            return adapted.remove(key);
        }

        public void putAll(Map<? extends String, ? extends Macro> t) {
            for (Map.Entry<? extends String, ? extends Macro> ent : t.entrySet()) {
                put(ent.getKey(), ent.getValue());
            }
        }

        public void clear() {
            adapted.clear();
        }

        public Set<String> keySet() {
            return adapted.keySet();
        }

        public Collection<Macro> values() {
            // According the Map API, this Collection doesn't allows adding elements, it's safe to treat as a
            // Collection<Macro>.
            return (Collection) adapted.values();
        }

        public Set<Entry<String, Macro>> entrySet() {
            // According the Map API, this set doesn't allows adding elements, but, the Map.Entry-s are still
            // modifiable.
            return new AdapterMacroMapEntrySet(adapted.entrySet());
        }

        @Override
        public boolean equals(Object o) {
            return adapted.equals(o);
        }

        @Override
        public int hashCode() {
            return adapted.hashCode();
        }
        
    }
    
    /** Helper for {@link AdapterMacroMap}. */
    private static class AdapterMacroMapEntrySet implements Set<Map.Entry<String, Macro>> {
        
        private final Set<Map.Entry<String, UnboundCallable>> adapted;

        public AdapterMacroMapEntrySet(Set<Entry<String, UnboundCallable>> adapted) {
            this.adapted = adapted;
        }

        public int size() {
            return adapted.size();
        }

        public boolean isEmpty() {
            return adapted.isEmpty();
        }

        public boolean contains(Object o) {
            return adapted.contains(o);
        }

        public Iterator<Entry<String, Macro>> iterator() {
            return new AdapterMacroMapEntrySetIterator(adapted.iterator());
        }

        public Object[] toArray() {
            return adapted.toArray();
        }

        public <T> T[] toArray(T[] a) {
            return adapted.toArray(a);
        }

        public boolean add(Entry<String, Macro> o) {
            // Won't be allowed anyway
            return adapted.add((Entry) o);
        }

        public boolean remove(Object o) {
            return adapted.remove(o);
        }

        public boolean containsAll(Collection<?> c) {
            return adapted.containsAll(c);
        }

        public boolean addAll(Collection<? extends Entry<String, Macro>> c) {
            // Won't be allowed anyway
            return adapted.addAll((Collection) c);
        }

        public boolean retainAll(Collection<?> c) {
            return adapted.retainAll(c);
        }

        public boolean removeAll(Collection<?> c) {
            return adapted.removeAll(c);
        }

        public void clear() {
            adapted.clear();
        }

        @Override
        public boolean equals(Object o) {
            return adapted.equals(o);
        }

        @Override
        public int hashCode() {
            return adapted.hashCode();
        }
        
    }
    
    /** Helper for {@link AdapterMacroMap}. */
    private static class AdapterMacroMapEntrySetIterator implements Iterator<Map.Entry<String, Macro>> {
        
        private final Iterator<Map.Entry<String, UnboundCallable>> adapted;

        public AdapterMacroMapEntrySetIterator(Iterator<Entry<String, UnboundCallable>> adapted) {
            this.adapted = adapted;
        }

        public boolean hasNext() {
            return adapted.hasNext();
        }

        public Entry<String, Macro> next() {
            return new AdapterMacroMapEntry(adapted.next());
        }

        public void remove() {
            adapted.remove();
        }
        
    }
    
    /** Helper for {@link AdapterMacroMap}. */
    private static class AdapterMacroMapEntry implements Map.Entry<String, Macro> {
        
        private final Map.Entry<String, UnboundCallable> adapted;

        public AdapterMacroMapEntry(Entry<String, UnboundCallable> adapted) {
            this.adapted = adapted;
        }

        public String getKey() {
            return adapted.getKey();
        }

        public UnboundCallable getValue() {
            return adapted.getValue();
        }

        public UnboundCallable setValue(Macro value) {
            return adapted.setValue(macroToUnboundCallable(value));
        }

        @Override
        public boolean equals(Object o) {
            return adapted.equals(o);
        }

        @Override
        public int hashCode() {
            return adapted.hashCode();
        }
        
    }

    /**
     * @throws IllegalArgumentException
     *             if the type of the some of the values isn't as expected
     */
    public static void checkSettingValueItemsType(String somethingsSentenceStart, Class<?> expectedClass,
            Collection<? extends Object> values) {
        if (values == null) return;
        for (Object value : values) {
            if (!expectedClass.isInstance(value)) {
                throw new IllegalArgumentException(somethingsSentenceStart + " must be instances of "
                        + ClassUtil.getShortClassName(expectedClass) + ", but one of them was a(n) "
                        + ClassUtil.getShortClassNameOfObject(value) + ".");
            }
        }
    }
    
    /**
     * The work around the problematic cases where we should throw a {@link TemplateException}, but we are inside
     * a {@link TemplateModel} method and so we can only throw {@link TemplateModelException}-s.  
     */
    public static TemplateModelException ensureIsTemplateModelException(String modelOpMsg, TemplateException e) {
        if (e instanceof TemplateModelException) {
            return (TemplateModelException) e;
        } else {
            return new _TemplateModelException(
                    _TemplateAPI.getBlamedExpression(e), e.getCause(), e.getEnvironment(), modelOpMsg);
        }
    }
    
    public static TemplateElement getParentElement(TemplateElement te) {
        return te.getParentElement();
    }

    public static TemplateElement getChildElement(TemplateElement te, int index) {
        return te.getChild(index);
    }
    
}
