/*
 *  ====================================================================
 *  The Apache Software License, Version 1.1
 *
 *  Copyright (c) 2002 The Apache Software Foundation.  All rights
 *  reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *  1. Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 *  2. Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in
 *  the documentation and/or other materials provided with the
 *  distribution.
 *
 *  3. The end-user documentation included with the redistribution,
 *  if any, must include the following acknowledgment:
 *  "This product includes software developed by the
 *  Apache Software Foundation (http://www.apache.org/)."
 *  Alternately, this acknowledgment may appear in the software itself,
 *  if and wherever such third-party acknowledgments normally appear.
 *
 *  4. The names "Apache" and "Apache Software Foundation" and
 *  "Apache Tapestry" must not be used to endorse or promote products
 *  derived from this software without prior written permission. For
 *  written permission, please contact apache@apache.org.
 *
 *  5. Products derived from this software may not be called "Apache",
 *  "Apache Tapestry", nor may "Apache" appear in their name, without
 *  prior written permission of the Apache Software Foundation.
 *
 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 *  ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 *  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 *  SUCH DAMAGE.
 *  ====================================================================
 *
 *  This software consists of voluntary contributions made by many
 *  individuals on behalf of the Apache Software Foundation.  For more
 *  information on the Apache Software Foundation, please see
 *  <http://www.apache.org/>.
 */
package net.sf.tapestry.engine;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import net.sf.tapestry.ApplicationRuntimeException;
import net.sf.tapestry.IAsset;
import net.sf.tapestry.IComponent;
import net.sf.tapestry.IMarkupWriter;
import net.sf.tapestry.IRenderDescription;
import net.sf.tapestry.IRequestCycle;
import net.sf.tapestry.IResourceResolver;
import net.sf.tapestry.ITemplateSource;
import net.sf.tapestry.NoSuchComponentException;
import net.sf.tapestry.Tapestry;
import net.sf.tapestry.parse.ComponentTemplate;
import net.sf.tapestry.parse.ITemplateParserDelegate;
import net.sf.tapestry.parse.TemplateParseException;
import net.sf.tapestry.parse.TemplateParser;
import net.sf.tapestry.parse.TemplateToken;
import net.sf.tapestry.spec.ComponentSpecification;
import net.sf.tapestry.util.MultiKey;

/**
 *  Default implementation of {@link ITemplateSource}.  Templates, once parsed,
 *  stay in memory until explicitly cleared.
 *
 *  <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);

    // 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 Map _cache = new HashMap();

    // Previously read templates; key is the HTML resource path, value
    // is the ComponentTemplate.

    private Map _templates = new HashMap();

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

    private int _tokenCount;

    private static final int BUFFER_SIZE = 2000;

    private IResourceResolver _resolver;
    private TemplateParser _parser;

    private static class ParserDelegate implements ITemplateParserDelegate
    {
        IComponent _component;

        ParserDelegate(IComponent component)
        {
            _component = component;
        }

        public boolean getKnownComponent(String componentId)
        {
            try
            {
                _component.getComponent(componentId);

                return true;
            }
            catch (NoSuchComponentException ex)
            {
                return false;
            }
        }

        public boolean getAllowBody(String componentId)
        {
            return _component.getComponent(componentId).getSpecification().getAllowBody();
        }
    }

    public DefaultTemplateSource(IResourceResolver resolver)
    {
        _resolver = resolver;
    }

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

    public void reset()
    {
        _cache = null;
        _templates.clear();

        _tokenCount = 0;
    }

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

    public ComponentTemplate getTemplate(IRequestCycle cycle, IComponent component)
    {
        ComponentSpecification specification = component.getSpecification();
        String specificationResourcePath = specification.getSpecificationResourcePath();
        Locale locale = component.getPage().getLocale();

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

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

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

        if (result == null)
        {
            String stringKey =
                (locale == null) ? "DefaultTemplateSource.no-template" : "DefaultTemplateSource.no-template-in-locale";

            throw new ApplicationRuntimeException(Tapestry.getString(stringKey, component.getExtendedId(), locale));
        }

        saveToCache(key, result);

        return result;
    }

    private synchronized ComponentTemplate searchCache(Object key)
    {
        if (_cache == null)
            return null;

        return (ComponentTemplate) _cache.get(key);

    }

    private synchronized void saveToCache(Object key, ComponentTemplate template)
    {
        if (_cache == null)
            _cache = new HashMap();

        _cache.put(key, template);

    }

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

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

        return findStandardTemplate(specificationResourcePath, component, locale);
    }

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

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

        char[] templateData = null;

        try
        {

            templateData = readTemplateStream(stream);

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

        return constructTokens(templateData, asset.toString(), 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.
     *
     **/

    private synchronized ComponentTemplate findStandardTemplate(
        String specificationResourcePath,
        IComponent component,
        Locale locale)
    {
        String candidatePath = null;
        String language = null;
        String country = null;

        if (LOG.isDebugEnabled())
            LOG.debug(
                "Searching for localized version of template for "
                    + specificationResourcePath
                    + " in locale "
                    + locale.getDisplayName());

        int dotx = specificationResourcePath.lastIndexOf('.');
        StringBuffer buffer = new StringBuffer(dotx + 20);
        buffer.append(specificationResourcePath.substring(0, dotx));
        int rawLength = buffer.length();
        int start = 2;

        if (locale != null)
        {
            country = locale.getCountry();
            if (country.length() > 0)
                start--;

            // This assumes that you never have the case where there's
            // a null language code and a non-null country code.

            language = locale.getLanguage();
            if (language.length() > 0)
                start--;
        }

        ComponentTemplate result = null;

        // On pass #0, we use language code and country code
        // On pass #1, we use language code
        // On pass #2, we use neither.
        // We skip pass #0 or #1 depending on whether the language code
        // and/or country code is null.

        for (int i = start; i < 3; i++)
        {
            buffer.setLength(rawLength);

            if (i < 2)
            {
                buffer.append('_');
                buffer.append(language);
            }

            if (i == 0)
            {
                buffer.append('_');
                buffer.append(country);
            }

            buffer.append(".html");

            candidatePath = buffer.toString();

            // See if it's been parsed before

            result = (ComponentTemplate) _templates.get(candidatePath);
            if (result != null)
                break;

            // Ok, see if it exists.

            result = parseTemplate(candidatePath, component);

            if (result != null)
            {
                _templates.put(candidatePath, result);
                break;
            }
        }

        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(String resourceName, IComponent component)
    {
        char[] templateData = readTemplate(resourceName);
        if (templateData == null)
            return null;

        return constructTokens(templateData, resourceName, component);
    }

    private ComponentTemplate constructTokens(char[] templateData, String resourceName, IComponent component)
    {
        if (_parser == null)
            _parser = new TemplateParser();

        ITemplateParserDelegate delegate = new ParserDelegate(component);

        TemplateToken[] tokens;

        try
        {
            tokens = _parser.parse(templateData, delegate, resourceName);
        }
        catch (TemplateParseException ex)
        {
            throw new ApplicationRuntimeException(
                Tapestry.getString("DefaultTemplateSource.unable-to-parse-template", resourceName),
                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(String resourceName)
    {
        URL url;
        InputStream stream = null;

        url = _resolver.getResource(resourceName);

        if (url == null)
            return null;

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

        try
        {
            stream = url.openStream();

            return readTemplateStream(stream);
        }
        catch (IOException ex)
        {
            throw new ApplicationRuntimeException(
                Tapestry.getString("DefaultTemplateSource.unable-to-read-template", resourceName),
                ex);
        }
        finally
        {
            try
            {
                if (stream != null)
                    stream.close();
            }
            catch (IOException e)
            {
                // Ignore it!
            }
        }

    }

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

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

        InputStreamReader reader = new InputStreamReader(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 synchronized String toString()
    {
        StringBuffer buffer = new StringBuffer("DefaultTemplateSource@");
        buffer.append(Integer.toHexString(hashCode()));

        buffer.append('[');

        if (_cache != null)
            buffer.append(_cache.keySet());

        if (_tokenCount > 0)
        {
            buffer.append(", ");
            buffer.append(_tokenCount);
            buffer.append(" tokens");
        }

        buffer.append(']');

        return buffer.toString();
    }

    /** @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("]");

    }
}