//  Copyright 2004, 2008 The Apache Software Foundation
//
// Licensed 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 org.apache.tapestry.engine;

import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tapestry.*;
import org.apache.tapestry.parse.*;
import org.apache.tapestry.spec.IApplicationSpecification;
import org.apache.tapestry.spec.IComponentSpecification;
import org.apache.tapestry.util.*;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;

/**
 * Default implementation of {@link ITemplateSource}.  Templates, once parsed, stay in memory until explicitly cleared.
 * <p/>
 * <p>An instance of this class acts as a singleton shared by all sessions, so it must be threadsafe.
 *
 * @author Howard Lewis Ship
 * @version $Id$
 */

public class DefaultTemplateSource implements ITemplateSource, IRenderDescription
{
    private static final Log LOG = LogFactory.getLog(DefaultTemplateSource.class);

    // The name of the component/application/etc property that will be used to
    // determine the encoding to use when loading the template

    private static final String TEMPLATE_ENCODING_PROPERTY_NAME = "org.apache.tapestry.template-encoding";

    // Cache of previously retrieved templates.  Key is a multi-key of 
    // specification resource path and locale (local may be null), value
    // is the ComponentTemplate.

    private final Map _cache = new ConcurrentHashMap();

    // Previously read templates; key is the IResourceLocation, value
    // is the ComponentTemplate.

    private final Map _templates = new ConcurrentHashMap();

    private final ResourceLockManager _resourceLockManager = new ResourceLockManager();

    /**
     * Number of tokens (each template contains multiple tokens).
     */

    private int _tokenCount;

    private static final int BUFFER_SIZE = 2000;

    private TemplateParser _parser;

    /**
     * @since 2.2 *
     */

    private IResourceLocation _applicationRootLocation;

    /**
     * @since 3.0 *
     */

    private ITemplateSourceDelegate _delegate;

    /**
     * Clears the template cache.  This is used during debugging.
     */

    public void reset()
    {
        _cache.clear();
        _templates.clear();
        _resourceLockManager.clear();

        _tokenCount = 0;
    }

    /**
     * Reads the template for the component.
     * <p/>
     * <p>Returns null if the template can't be found.
     */

    public ComponentTemplate getTemplate(IRequestCycle cycle, IComponent component)
    {
        IComponentSpecification specification = component.getSpecification();
        IResourceLocation specificationLocation = specification.getSpecificationLocation();

        Locale locale = component.getPage().getLocale();

        Object key = new MultiKey(new Object[]{specificationLocation, locale}, false);

        ComponentTemplate result = searchCache(key);
        if (result != null)
            return result;

        _resourceLockManager.lock(key);

        try
        {
            result = searchCache(key);
            if (result != null)
                return result;

            result = findTemplate(cycle, specificationLocation, component, locale);

            if (result == null)
            {
                result = getTemplateFromDelegate(cycle, component, locale);

                if (result != null)
                    return result;

                String stringKey =
                        component.getSpecification().isPageSpecification()
                        ? "DefaultTemplateSource.no-template-for-page"
                        : "DefaultTemplateSource.no-template-for-component";

                throw new ApplicationRuntimeException(
                        Tapestry.format(stringKey, component.getExtendedId(), locale),
                        component,
                        component.getLocation(),
                        null);
            }

            saveToCache(key, result);

            return result;
        }
        finally
        {
            _resourceLockManager.unlock(key);
        }

    }

    private ComponentTemplate searchCache(Object key)
    {
        return (ComponentTemplate) _cache.get(key);
    }

    private void saveToCache(Object key, ComponentTemplate template)
    {
        _cache.put(key, template);

    }

    private ComponentTemplate getTemplateFromDelegate(
            IRequestCycle cycle,
            IComponent component,
            Locale locale)
    {
        if (_delegate == null)
        {
            IEngine engine = cycle.getEngine();
            IApplicationSpecification spec = engine.getSpecification();

            if (spec.checkExtension(Tapestry.TEMPLATE_SOURCE_DELEGATE_EXTENSION_NAME))
                _delegate =
                        (ITemplateSourceDelegate) spec.getExtension(
                                Tapestry.TEMPLATE_SOURCE_DELEGATE_EXTENSION_NAME,
                                ITemplateSourceDelegate.class);
            else
                _delegate = NullTemplateSourceDelegate.getSharedInstance();

        }

        return _delegate.findTemplate(cycle, component, locale);
    }

    /**
     * Finds the template for the given component, using the following rules: <ul> <li>If the component has a $template
     * asset, use that <li>Look for a template in the same folder as the component <li>If a page in the application
     * namespace, search in the application root <li>Fail! </ul>
     *
     * @return the template, or null if not found
     */

    private ComponentTemplate findTemplate(
            IRequestCycle cycle,
            IResourceLocation location,
            IComponent component,
            Locale locale)
    {
        IAsset templateAsset = component.getAsset(TEMPLATE_ASSET_NAME);

        if (templateAsset != null)
            return readTemplateFromAsset(cycle, component, templateAsset);

        String name = location.getName();
        int dotx = name.lastIndexOf('.');
        String templateBaseName = name.substring(0, dotx + 1) + getTemplateExtension(component);

        ComponentTemplate result =
                findStandardTemplate(cycle, location, component, templateBaseName, locale);

        if (result == null
                && component.getSpecification().isPageSpecification()
                && component.getNamespace().isApplicationNamespace())
            result = findPageTemplateInApplicationRoot(cycle, component, templateBaseName, locale);

        return result;
    }

    private ComponentTemplate findPageTemplateInApplicationRoot(
            IRequestCycle cycle,
            IComponent component,
            String templateBaseName,
            Locale locale)
    {
        if (LOG.isDebugEnabled())
            LOG.debug("Checking for " + templateBaseName + " in application root");

        if (_applicationRootLocation == null)
            _applicationRootLocation = Tapestry.getApplicationRootLocation(cycle);

        IResourceLocation baseLocation =
                _applicationRootLocation.getRelativeLocation(templateBaseName);
        IResourceLocation localizedLocation = baseLocation.getLocalization(locale);

        if (localizedLocation == null)
            return null;

        return getOrParseTemplate(cycle, localizedLocation, component);
    }

    /**
     * Reads an asset to get the template.
     */

    private ComponentTemplate readTemplateFromAsset(
            IRequestCycle cycle,
            IComponent component,
            IAsset asset)
    {
        InputStream stream = asset.getResourceAsStream(cycle);

        char[] templateData = null;

        try
        {
            String encoding = getTemplateEncoding(cycle, component, null);

            templateData = readTemplateStream(stream, encoding);

            stream.close();
        }
        catch (IOException ex)
        {
            throw new ApplicationRuntimeException(
                    Tapestry.format("DefaultTemplateSource.unable-to-read-template", asset),
                    ex);
        }

        IResourceLocation resourceLocation = asset.getResourceLocation();

        return constructTemplateInstance(cycle, templateData, resourceLocation, component);
    }

    /**
     * Search for the template corresponding to the resource and the locale. This may be in the template map already, or
     * may involve reading and parsing the template.
     *
     * @return the template, or null if not found.
     */

    private ComponentTemplate findStandardTemplate(
            IRequestCycle cycle,
            IResourceLocation location,
            IComponent component,
            String templateBaseName,
            Locale locale)
    {
        if (LOG.isDebugEnabled())
            LOG.debug(
                    "Searching for localized version of template for "
                            + location
                            + " in locale "
                            + locale.getDisplayName());

        IResourceLocation baseTemplateLocation = location.getRelativeLocation(templateBaseName);

        IResourceLocation localizedTemplateLocation = baseTemplateLocation.getLocalization(locale);

        if (localizedTemplateLocation == null)
            return null;

        return getOrParseTemplate(cycle, localizedTemplateLocation, component);

    }

    /**
     * Returns a previously parsed template at the specified location (which must already be localized).  If not already
     * in the template Map, then the location is parsed and stored into the templates Map, then returned.
     */

    private ComponentTemplate getOrParseTemplate(
            IRequestCycle cycle,
            IResourceLocation location,
            IComponent component)
    {

        ComponentTemplate result = (ComponentTemplate) _templates.get(location);
        if (result != null)
            return result;

        // Ok, see if it exists.

        result = parseTemplate(cycle, location, component);

        if (result != null)
            _templates.put(location, result);

        return result;
    }

    /**
     * Reads the template for the given resource; returns null if the resource doesn't exist.  Note that this method is
     * only invoked from a synchronized block, so there shouldn't be threading issues here.
     */

    private ComponentTemplate parseTemplate(
            IRequestCycle cycle,
            IResourceLocation location,
            IComponent component)
    {
        String encoding = getTemplateEncoding(cycle, component, location.getLocale());

        char[] templateData = readTemplate(location, encoding);
        if (templateData == null)
            return null;

        return constructTemplateInstance(cycle, templateData, location, component);
    }

    /**
     * This method is currently synchronized, because {@link TemplateParser} is not threadsafe.  Another good candidate
     * for a pooling mechanism, especially because parsing a template may take a while.
     */

    private synchronized ComponentTemplate constructTemplateInstance(
            IRequestCycle cycle,
            char[] templateData,
            IResourceLocation location,
            IComponent component)
    {
        if (_parser == null)
            _parser = new TemplateParser();

        ITemplateParserDelegate delegate = new TemplateParserDelegateImpl(component, cycle);

        TemplateToken[] tokens;

        try
        {
            tokens = _parser.parse(templateData, delegate, location);
        }
        catch (TemplateParseException ex)
        {
            throw new ApplicationRuntimeException(
                    Tapestry.format("DefaultTemplateSource.unable-to-parse-template", location),
                    ex);
        }

        if (LOG.isDebugEnabled())
            LOG.debug("Parsed " + tokens.length + " tokens from template");

        _tokenCount += tokens.length;

        return new ComponentTemplate(templateData, tokens);
    }

    /**
     * Reads the template, given the complete path to the resource.  Returns null if the resource doesn't exist.
     */

    private char[] readTemplate(IResourceLocation location, String encoding)
    {
        if (LOG.isDebugEnabled())
            LOG.debug("Reading template " + location);

        URL url = location.getResourceURL();

        if (url == null)
        {
            if (LOG.isDebugEnabled())
                LOG.debug("Template does not exist.");

            return null;
        }

        if (LOG.isDebugEnabled())
            LOG.debug("Reading template from URL " + url);

        InputStream stream = null;

        try
        {
            stream = url.openStream();

            return readTemplateStream(stream, encoding);
        }
        catch (IOException ex)
        {
            throw new ApplicationRuntimeException(
                    Tapestry.format("DefaultTemplateSource.unable-to-read-template", location),
                    ex);
        }
        finally
        {
            Tapestry.close(stream);
        }

    }

    /**
     * Reads a Stream into memory as an array of characters.
     */

    private char[] readTemplateStream(InputStream stream, String encoding) throws IOException
    {
        char[] charBuffer = new char[BUFFER_SIZE];
        StringBuffer buffer = new StringBuffer();

        InputStreamReader reader;
        if (encoding != null)
            reader = new InputStreamReader(new BufferedInputStream(stream), encoding);
        else
            reader = new InputStreamReader(new BufferedInputStream(stream));

        try
        {
            while (true)
            {
                int charsRead = reader.read(charBuffer, 0, BUFFER_SIZE);

                if (charsRead <= 0)
                    break;

                buffer.append(charBuffer, 0, charsRead);
            }
        }
        finally
        {
            reader.close();
        }

        // OK, now reuse the charBuffer variable to
        // produce the final result.

        int length = buffer.length();

        charBuffer = new char[length];

        // Copy the character out of the StringBuffer and into the
        // array.

        buffer.getChars(0, length, charBuffer, 0);

        return charBuffer;
    }

    public String toString()
    {
        ToStringBuilder builder = new ToStringBuilder(this);

        builder.append("tokenCount", _tokenCount);

        builder.append("templates", _templates.keySet());

        return builder.toString();
    }

    /**
     * Checks for the {@link Tapestry#TEMPLATE_EXTENSION_PROPERTY} in the component's specification, then in the
     * component's namespace's specification.  Returns {@link Tapestry#DEFAULT_TEMPLATE_EXTENSION} if not otherwise
     * overriden.
     */

    private String getTemplateExtension(IComponent component)
    {
        String extension =
                component.getSpecification().getProperty(Tapestry.TEMPLATE_EXTENSION_PROPERTY);

        if (extension != null)
            return extension;

        extension =
                component.getNamespace().getSpecification().getProperty(
                        Tapestry.TEMPLATE_EXTENSION_PROPERTY);

        if (extension != null)
            return extension;

        return Tapestry.DEFAULT_TEMPLATE_EXTENSION;
    }

    /**
     * @since 1.0.6 *
     */

    public synchronized void renderDescription(IMarkupWriter writer)
    {
        writer.print("DefaultTemplateSource[");

        if (_tokenCount > 0)
        {
            writer.print(_tokenCount);
            writer.print(" tokens");
        }

        if (_cache != null)
        {
            boolean first = true;
            Iterator i = _cache.entrySet().iterator();

            while (i.hasNext())
            {
                if (first)
                {
                    writer.begin("ul");
                    first = false;
                }

                Map.Entry e = (Map.Entry) i.next();
                Object key = e.getKey();
                ComponentTemplate template = (ComponentTemplate) e.getValue();

                writer.begin("li");
                writer.print(key.toString());
                writer.print(" (");
                writer.print(template.getTokenCount());
                writer.print(" tokens)");
                writer.println();
                writer.end();
            }

            if (!first)
            {
                writer.end(); // <ul>
                writer.beginEmpty("br");
            }
        }

        writer.print("]");

    }

    private String getTemplateEncoding(IRequestCycle cycle, IComponent component, Locale locale)
    {
        IPropertySource source = getComponentPropertySource(cycle, component);

        if (locale != null)
            source = new LocalizedPropertySource(locale, source);

        return getTemplateEncodingProperty(source);
    }

    private IPropertySource getComponentPropertySource(IRequestCycle cycle, IComponent component)
    {
        DelegatingPropertySource source = new DelegatingPropertySource();

        // Search for the encoding property in the following order:
        // First search the component specification
        source.addSource(new PropertyHolderPropertySource(component.getSpecification()));

        // Then search its library specification
        source.addSource(new PropertyHolderPropertySource(component.getNamespace().getSpecification()));

        // Then search the rest of the standard path
        source.addSource(cycle.getEngine().getPropertySource());

        return source;
    }

    private String getTemplateEncodingProperty(IPropertySource source)
    {
        return source.getPropertyValue(TEMPLATE_ENCODING_PROPERTY_NAME);
    }

}
