package org.apache.velocity.tools.generic;

/*
 * 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.
 */

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.velocity.tools.config.DefaultKey;

/**
 * <b>NOTE: This tools is considered "alpha" quality due to lack of testing
 * and a generally unpolished API.  Feel free to use but expect changes.
 * Also, this is not automatically provided via the default tools.xml file.
 * </b>
 *
 * <p>
 * A tool to make it easy to generate XML or HTML on the fly.  It uses a CSS-type
 * syntax with a vaguely jQuery-ish API to help you generate the markup you need.</p>
 * <pre>
 * Example uses in a template:
 *   #set( $foospan = $markup.span.id($foo.id).body($foo) )
 *   $markup.tag('table tr.bar td').body("This is $foospan")
 *
 * Output:
 *   &lt;table&gt;
 *     &lt;tr class="bar"&gt;
 *       &lt;td&gt;This is &lt;span id="foo1"&gt;my first foo.&lt;/span&gt;&lt;/td&gt;
 *     &lt;/tr&gt;
 *   &lt;/table&gt;
 *
 *
 * Example tools.xml config:
 * &lt;tools&gt;
 *   &lt;toolbox scope="application"&gt;
 *     &lt;tool class="org.apache.velocity.tools.generic.alpha.MarkupTool"/&gt;
 *   &lt;/toolbox&gt;
 * &lt;/tools&gt;
 * </pre>
 *
 * @author Nathan Bubna
 * @since VelocityTools 2.0
 * @version $Id$
 */
@DefaultKey("mark")
public class MarkupTool extends SafeConfig implements Serializable
{
    private static final long serialVersionUID = -777597069616274442L;

    public static final String DEFAULT_TAB = "  ";
    public static final String DEFAULT_DELIMITER = " ";

    private String tab = DEFAULT_TAB;
    private String delim = DEFAULT_DELIMITER;

    /**
     * Configuration
     * @param tab tab string
     */
    public void setTab(String tab)
    {
        if (isConfigLocked())
        {
            getLog().error("setTab() failure: configuration is locked");
        }
        else
        {
            this.tab = tab;
        }
    }

    public String getTab()
    {
        return this.tab;
    }

    public Tag get(String tag)
    {
        return tag(tag);
    }

    public Tag tag(String definition)
    {
        String[] tags = split(definition);
        Tag last = null;
        for (int i=0; i < tags.length; i++)
        {
            Tag tag = parse(tags[i]);
            if (last != null)
            {
                last.append(tag);
            }
            last = tag;
        }
        return last;
    }

    protected String[] split(String me)
    {
        //TODO: fix escaped delimiters
        return me.split(delim);
    }

    private static enum Mode { NAME, ID, CLASS, ATTR }
    protected Tag parse(String definition)
    {
        StringBuilder store = new StringBuilder();
        Tag tag = new Tag(this);
        Mode mode = Mode.NAME;
        for (int i=0; i < definition.length(); i++)
        {
            char c = definition.charAt(i);
            if (c == '#')
            {
                store = clear(mode, tag, store, true);
                mode = Mode.ID;
            }
            else if (c == '.')
            {
                store = clear(mode, tag, store, true);
                mode = Mode.CLASS;
            }
            else if (c == '[')
            {
                store = clear(mode, tag, store, true);
                mode = Mode.ATTR;
            }
            else if (c == ']')
            {
                store = clear(mode, tag, store, true);
                mode = Mode.NAME;
            }
            else
            {
                store.append(c);
            }
        }
        clear(mode, tag, store, false);
        return tag;
    }
    private StringBuilder clear(Mode mode, Tag tag, StringBuilder val, boolean emptyStore)
    {
        if (val.length() > 0)
        {
            String s = val.toString();
            switch (mode)
            {
                case NAME:
                    tag.name(s);
                    break;
                case ID:
                    tag.id(s);
                    break;
                case CLASS:
                    tag.addClass(s);
                    break;
                case ATTR:
                    if (s.indexOf('=') > 0)
                    {
                        String[] kv = s.split("=");
                        tag.attr(kv[0], kv[1]);
                    }
                    else
                    {
                        tag.attr(s, null);
                    }
                    break;
            }
            if (emptyStore)
            {
                return new StringBuilder();
            }
            return val;
        }
        else
        {
            // already is clean
            return val;
        }
    }

    public static class Tag
    {
        private MarkupTool tool;
        private Tag parent;
        private Object name;
        private Object id;
        private List<Object> classes;
        private Map<Object,Object> attributes;
        private List<Object> children;

        public Tag(MarkupTool tool)
        {
            this.tool = tool;
        }

        public Tag name(Object name)
        {
            this.name = name;
            return this;
        }

        public Tag id(Object id)
        {
            this.id = id;
            return this;
        }

        public Tag addClass(Object c)
        {
            if (c == null)
            {
                return null;
            }

            if (classes == null)
            {
                classes = new ArrayList<Object>();
            }
            classes.add(c);
            return this;
        }

        public Tag attr(Object k, Object v)
        {
            if (k == null)
            {
                return null;
            }
            if (attributes == null)
            {
                attributes = new HashMap<Object,Object>();
            }
            attributes.put(k, v);
            return this;
        }

        public Tag body(Object o)
        {
            if (children == null)
            {
                children = new ArrayList<Object>();
            }
            else
            {
                children.clear();
            }
            children.add(o);
            return this;
        }

        public Tag append(Object o)
        {
            if (children == null)
            {
                children = new ArrayList<Object>();
            }
            children.add(o);
            if (o instanceof Tag)
            {
                ((Tag)o).parent(this);
            }
            return this;
        }

        public Tag prepend(Object o)
        {
            if (children == null)
            {
                children = new ArrayList<Object>();
                children.add(o);
            }
            else
            {
                children.add(0, o);
            }
            if (o instanceof Tag)
            {
                ((Tag)o).parent(this);
            }
            return this;
        }

        public Tag wrap(String tag)
        {
            // make new tag
            Tag prnt = tool.tag(tag);
            // give root of new tag our parent
            prnt.root().parent(parent());
            // make new tag our parent
            parent(prnt);
            return this;
        }

        public Tag orphan()
        {
            return parent(null);
        }

        public Tag parent(Tag parent)
        {
            this.parent = parent;
            return this;
        }

        public Tag parent()
        {
            return this.parent;
        }

        public Tag root()
        {
            if (isOrphan())
            {
                return this;
            }
            return this.parent.root();
        }

        public List<Object> children()
        {
            return children;
        }

        public boolean isOrphan()
        {
            return (parent == null);
        }

        public boolean isEmpty()
        {
            return (children == null || children().isEmpty());
        }

        public boolean matches(Tag tag)
        {
            if (missed(name, tag.name) ||
                missed(id, tag.id) ||
                missed(classes, tag.classes))
            {
                return false;
            }
            //TODO: match attributes
            return true;
        }

        protected boolean missed(Object target, Object arrow)
        {
            // no arrow, no miss
            if (arrow == null)
            {
                return false;
            }
            // otherwise, the arrow must hit the target
            return !arrow.equals(target);
        }

        protected boolean missed(List<Object> targets, List<Object> arrows)
        {
            // no arrows, no miss
            if (arrows == null)
            {
                return false;
            }
            // no targets, always miss
            if (targets == null)
            {
                return true;
            }
            for (Object o : arrows)
            {
                if (!targets.contains(o))
                {
                    return true;
                }
            }
            return false;
        }


        /************* rendering methods **************/

        /**
         * Render tag
         * @param indent indentation string
         * @param s string builder
         */
        protected void render(String indent, StringBuilder s)
        {
            if (render_start(indent, s))
            {
                render_body(indent, s);
                render_end(indent, s);
            }
        }

        /**
         * Start tag rendering
         * @param indent indentation string
         * @param s string builder
         * @return whether a closing tag is needed
         */
        protected boolean render_start(String indent, StringBuilder s)
        {
            if (indent != null)
            {
                s.append(indent);
            }
            s.append('<');
            render_name(s);
            render_id(s);
            render_classes(s);
            render_attributes(s);
            if (isEmpty())
            {
                s.append("/>");
                return false;
            }
            else
            {
                s.append('>');
                return true;
            }
        }

        /**
         * Render tag name
         * @param s string builder
         */
        protected void render_name(StringBuilder s)
        {
            s.append(name == null ? "div" : name);
        }

        /**
         * render tag id
         * @param s string builder
         */
        protected void render_id(StringBuilder s)
        {
            if (id != null)
            {
                s.append(" id=\"").append(id).append('"');
            }
        }

        /**
         * render tag classes
         * @param s string builder
         */
        protected void render_classes(StringBuilder s)
        {
            if (classes != null)
            {
                s.append(" class=\"");
                for (int i=0; i < classes.size(); i++)
                {
                    s.append(classes.get(i));
                    if (i + 1 != classes.size())
                    {
                        s.append(' ');
                    }
                }
                s.append('"');
            }
        }

        /**
         * Render tag attributes
         * @param s string builder
         */
        protected void render_attributes(StringBuilder s)
        {
            if (attributes != null)
            {
                for (Map.Entry<Object,Object> entry : attributes.entrySet())
                {
                    s.append(' ').append(entry.getKey()).append("=\"");
                    if (entry.getValue() != null)
                    {
                        s.append(entry.getValue());
                    }
                    s.append('"');
                }
            }
        }

        /**
         * Render tag body
         * @param indent indentation string
         * @param s string builder
         */
        protected void render_body(String indent, StringBuilder s)
        {
            String kidIndent = indent + tool.getTab();
            for (Object o : children)
            {
                if (o instanceof Tag)
                {
                    ((Tag)o).render(kidIndent, s);
                }
                else
                {
                    s.append(kidIndent);
                    s.append(o);
                }
            }
        }

        /**
         * Render tag end
         * @param indent indentation string
         * @param s string builder
         */
        protected void render_end(String indent, StringBuilder s)
        {
            if (indent != null)
            {
                s.append(indent);
            }
            s.append("</").append(name).append('>');
        }

        /**
         * @return string representation
         */
        public String toString()
        {
            StringBuilder s = new StringBuilder();
            root().render("\n", s);
            return s.toString();
        }
    }
}
