// Copyright 2005 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;

import java.util.ArrayList;
import java.util.List;

import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.HiveMind;
import org.apache.hivemind.Location;
import org.apache.hivemind.util.Defense;

/**
 * Constants and static methods.
 * 
 * @author Howard M. Lewis Ship
 * @since 4.0
 */
public class TapestryUtils
{
    private static final char QUOTE = '\'';

    private static final char BACKSLASH = '\\';

    private static final String EMPTY_QUOTES = "''";

    /**
     * Stores an attribute into the request cycle, verifying that no object with that key is already
     * present.
     * 
     * @param cycle
     *            the cycle to store the attribute into
     * @param key
     *            the key to store the attribute as
     * @param object
     *            the attribute value to store
     * @throws IllegalStateException
     *             if a non-null value has been stored into the cycle with the provided key.
     */

    public static void storeUniqueAttribute(IRequestCycle cycle, String key, Object object)
    {
        Defense.notNull(cycle, "cycle");
        Defense.notNull(key, "key");
        Defense.notNull(object, "object");

        Object existing = cycle.getAttribute(key);
        if (existing != null)
            throw new IllegalStateException(TapestryMessages.nonUniqueAttribute(
                    object,
                    key,
                    existing));

        cycle.setAttribute(key, object);
    }

    public static final String PAGE_RENDER_SUPPORT_ATTRIBUTE = "org.apache.tapestry.PageRenderSupport";

    public static final String FORM_ATTRIBUTE = "org.apache.tapestry.Form";

    /**
     * Stores the support object using {@link #storeUniqueAttribute(IRequestCycle, String, Object)}.
     */

    public static void storePageRenderSupport(IRequestCycle cycle, PageRenderSupport support)
    {
        storeUniqueAttribute(cycle, PAGE_RENDER_SUPPORT_ATTRIBUTE, support);
    }

    /**
     * Store the IForm instance using {@link #storeUniqueAttribute(IRequestCycle, String, Object)}.
     */

    public static void storeForm(IRequestCycle cycle, IForm form)
    {
        storeUniqueAttribute(cycle, FORM_ATTRIBUTE, form);
    }

    /**
     * Gets the previously stored {@link org.apache.tapestry.PageRenderSupport}&nbsp;object.
     * 
     * @param cycle
     *            the request cycle storing the support object
     * @param component
     *            the component which requires the support (used to report exceptions)
     * @throws ApplicationRuntimeException
     *             if no support object has been stored
     */

    public static PageRenderSupport getPageRenderSupport(IRequestCycle cycle, IComponent component)
    {
        Defense.notNull(component, "component");

        PageRenderSupport result = getOptionalPageRenderSupport(cycle);
        if (result == null)
            throw new ApplicationRuntimeException(TapestryMessages.noPageRenderSupport(component),
                    component.getLocation(), null);

        return result;
    }

    /**
     * Gets the previously stored {@link IForm} object.
     * 
     * @param cycle
     *            the request cycle storing the support object
     * @param component
     *            the component which requires the form (used to report exceptions)
     * @throws ApplicationRuntimeException
     *             if no form object has been stored
     */
    public static IForm getForm(IRequestCycle cycle, IComponent component)
    {
        Defense.notNull(cycle, "cycle");
        Defense.notNull(component, "component");

        IForm result = (IForm) cycle.getAttribute(FORM_ATTRIBUTE);

        if (result == null)
            throw new ApplicationRuntimeException(TapestryMessages.noForm(component), component
                    .getLocation(), null);

        return result;
    }

    public static void removePageRenderSupport(IRequestCycle cycle)
    {
        cycle.removeAttribute(PAGE_RENDER_SUPPORT_ATTRIBUTE);
    }

    public static void removeForm(IRequestCycle cycle)
    {
        cycle.removeAttribute(FORM_ATTRIBUTE);
    }

    /**
     * Returns the {@link PageRenderSupport}&nbsp;object if previously stored, or null otherwise.
     * This is used in the rare case that a component wishes to adjust its behavior based on whether
     * the page render support services are avaiable (typically, adjust for whether enclosed by a
     * Body component, or not).
     */

    public static PageRenderSupport getOptionalPageRenderSupport(IRequestCycle cycle)
    {
        return (PageRenderSupport) cycle.getAttribute(PAGE_RENDER_SUPPORT_ATTRIBUTE);
    }

    /**
     * Splits a string using the default delimiter of ','.
     */

    public static String[] split(String input)
    {
        return split(input, ',');
    }

    /**
     * Splits a single string into an array of strings, using a specific delimiter character.
     */

    public static String[] split(String input, char delimiter)
    {
        if (HiveMind.isBlank(input))
            return new String[0];

        List strings = new ArrayList();

        char[] buffer = input.toCharArray();

        int start = 0;
        int length = 0;

        for (int i = 0; i < buffer.length; i++)
        {
            if (buffer[i] != delimiter)
            {
                length++;
                continue;
            }

            // Consecutive delimiters will result in a sequence
            // of empty strings.

            String token = new String(buffer, start, length);
            strings.add(token);

            start = i + 1;
            length = 0;
        }

        // If the string contains no delimiters, then
        // wrap it an an array and return it.

        if (start == 0 && length == buffer.length)
        {
            return new String[]
            { input };
        }

        // The final token.
        String token = new String(buffer, start, length);
        strings.add(token);

        return (String[]) strings.toArray(new String[strings.size()]);
    }

    /**
     * Enquotes a string within single quotes, ready for insertion as part of a block of JavaScript.
     * Single quotes and backslashes within the input string are properly escaped.
     */

    public static String enquote(String input)
    {
        if (input == null)
            return EMPTY_QUOTES;

        char[] chars = input.toCharArray();

        // Add room for the two quotes and a couple of escaped characters

        StringBuffer buffer = new StringBuffer(chars.length + 5);

        buffer.append(QUOTE);

        for (int i = 0; i < chars.length; i++)
        {
            char ch = chars[i];

            if (ch == QUOTE || ch == BACKSLASH)
                buffer.append(BACKSLASH);

            buffer.append(ch);
        }

        buffer.append(QUOTE);

        return buffer.toString();
    }

    /**
     * A Tapestry component id is a little more liberal than an XML NMTOKEN. NMTOKEN must be
     * [A-Za-z][A-Za-z0-9:_.-]*, but a component id might include a leading dollar sign (for an
     * anonymous component with a fabricated id).
     */

    public static String convertTapestryIdToNMToken(String baseId)
    {
        String result = baseId.replace('$', '_');

        while (result.startsWith("_"))
            result = result.substring(1);

        return result;
    }

    /**
     * Converts a clientId into a client-side DOM reference; i.e.
     * <code>document.getElementById('<i>id</i>')</code>.
     */

    public static String buildClientElementReference(String clientId)
    {
        Defense.notNull(clientId, "clientId");

        return "document.getElementById('" + clientId + "')";
    }

    /**
     * Used by some generated code; obtains a component and ensures it is of the correct type.
     */

    public static IComponent getComponent(IComponent container, String componentId,
            Class expectedType, Location location)
    {
        Defense.notNull(container, "container");
        Defense.notNull(componentId, "componentId");
        Defense.notNull(expectedType, "expectedType");
        // Don't always have a location

        IComponent component = null;

        try
        {
            component = container.getComponent(componentId);
        }
        catch (Exception ex)
        {
            throw new ApplicationRuntimeException(ex.getMessage(), location, ex);
        }

        if (!expectedType.isAssignableFrom(component.getClass()))
            throw new ApplicationRuntimeException(TapestryMessages.componentWrongType(
                    component,
                    expectedType), location, null);

        return component;
    }
}