/************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
 * 
 * Copyright 2008, 2010 Oracle and/or its affiliates. All rights reserved.
 * 
 * Use is subject to license terms.
 * 
 * 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. You can also
 * obtain a copy of the License at http://odftoolkit.org/docs/license.txt
 * 
 * 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.odftoolkit.odfdom.dom.element;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Map.Entry;

import org.odftoolkit.odfdom.pkg.OdfAttribute;
import org.odftoolkit.odfdom.pkg.OdfContainerElementBase;
import org.odftoolkit.odfdom.pkg.OdfElement;
import org.odftoolkit.odfdom.pkg.OdfFileDom;
import org.odftoolkit.odfdom.pkg.OdfName;
import org.odftoolkit.odfdom.dom.OdfDocumentNamespace;
import org.odftoolkit.odfdom.dom.element.style.StyleChartPropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleDrawingPagePropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleGraphicPropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleHeaderFooterPropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleListLevelPropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StylePageLayoutPropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleParagraphPropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleRubyPropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleSectionPropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleTableCellPropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleTableColumnPropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleTablePropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleTableRowPropertiesElement;
import org.odftoolkit.odfdom.dom.element.style.StyleTextPropertiesElement;
import org.odftoolkit.odfdom.dom.style.OdfStyleFamily;
import org.odftoolkit.odfdom.dom.style.OdfStylePropertySet;
import org.odftoolkit.odfdom.dom.style.props.OdfStylePropertiesSet;
import org.odftoolkit.odfdom.dom.style.props.OdfStyleProperty;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * 
 */
abstract public class OdfStyleBase extends OdfContainerElementBase implements OdfStylePropertySet, Comparable {

    /**
     *
     */
    private static final long serialVersionUID = 8271282184913774000L;
    private HashMap<OdfStylePropertiesSet, OdfStylePropertiesBase> mPropertySetElementMap;
    private ArrayList<OdfStylableElement> mStyleUser;
    static HashMap<OdfName, OdfStylePropertiesSet> mStylePropertiesElementToSetMap;


    static {
        mStylePropertiesElementToSetMap = new HashMap<OdfName, OdfStylePropertiesSet>();
        mStylePropertiesElementToSetMap.put(StyleChartPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.ChartProperties);
        mStylePropertiesElementToSetMap.put(StyleDrawingPagePropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.DrawingPageProperties);
        mStylePropertiesElementToSetMap.put(StyleGraphicPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.GraphicProperties);
        mStylePropertiesElementToSetMap.put(StyleHeaderFooterPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.HeaderFooterProperties);
        mStylePropertiesElementToSetMap.put(StyleListLevelPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.ListLevelProperties);
        mStylePropertiesElementToSetMap.put(StylePageLayoutPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.PageLayoutProperties);
        mStylePropertiesElementToSetMap.put(StyleParagraphPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.ParagraphProperties);
        mStylePropertiesElementToSetMap.put(StyleRubyPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.RubyProperties);
        mStylePropertiesElementToSetMap.put(StyleSectionPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.SectionProperties);
        mStylePropertiesElementToSetMap.put(StyleTableCellPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.TableCellProperties);
        mStylePropertiesElementToSetMap.put(StyleTableColumnPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.TableColumnProperties);
        mStylePropertiesElementToSetMap.put(StyleTablePropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.TableProperties);
        mStylePropertiesElementToSetMap.put(StyleTableRowPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.TableRowProperties);
        mStylePropertiesElementToSetMap.put(StyleTextPropertiesElement.ELEMENT_NAME, OdfStylePropertiesSet.TextProperties);
    }

    /** Creates a new instance of OdfElement */
    public OdfStyleBase(OdfFileDom ownerDocument,
            String namespaceURI,
            String qualifiedName) throws DOMException {
        super(ownerDocument, namespaceURI, qualifiedName);
    }

    /** Creates a new instance of OdfElement */
    public OdfStyleBase(OdfFileDom ownerDocument,
            OdfName aName) throws DOMException {
        super(ownerDocument, aName.getUri(), aName.getQName());
    }

    public void addStyleUser(OdfStylableElement user) {
        if (mStyleUser == null) {
            mStyleUser = new ArrayList<OdfStylableElement>();
        }
        mStyleUser.add(user);
    }

    /**
     * get a map containing all properties of this style and their values.
     * @return map of properties. 
     */
    public Map<OdfStyleProperty, String> getStyleProperties() {
        TreeMap<OdfStyleProperty, String> result = new TreeMap<OdfStyleProperty, String>();
        OdfStyleFamily family = getFamily();
        if (family != null) {
            for (OdfStyleProperty property : family.getProperties()) {
                if (hasProperty(property)) {
                    result.put(property, getProperty(property));
                }
            }
        }
        return result;
    }

    /**
     * get a map containing all properties of this style and their values.
     * The map will also include any properties set by parent styles
     * @return  a map of all the properties.
     */
    public Map<OdfStyleProperty, String> getStylePropertiesDeep() {
        TreeMap<OdfStyleProperty, String> result = new TreeMap<OdfStyleProperty, String>();
        OdfStyleBase style = this;
        while (style != null) {
            OdfStyleFamily family = style.getFamily();
            if (family != null) {
                for (OdfStyleProperty property : family.getProperties()) {
                    if (!result.containsKey(property) && style.hasProperty(property)) {
                        result.put(property, style.getProperty(property));
                    }
                }
            }

            style = style.getParentStyle();
        }
        return result;
    }

    public void removeStyleUser(OdfStylableElement user) {
        if (mStyleUser != null) {
            mStyleUser.remove(user);
        }
    }

    public int getStyleUserCount() {
        return mStyleUser == null ? 0 : mStyleUser.size();
    }

    /** Returns an iterator for all <code>OdfStylableElement</code> elements
     * using this style.
     *
     * @return an iterator for all <code>OdfStylableElement</code> elements
     * using this style
     */
    public Iterable<OdfStylableElement> getStyleUsers() {
        if (mStyleUser != null) {
            return mStyleUser;
        }
        return new ArrayList<OdfStylableElement>();
    }

    public String getFamilyName() {
        return getFamily().getName();
    }


    /**
     * 
     * @param set
     * @return the style:*-properties element for the given set. Returns null if
     *         such element does not exist yet.
     */
    public OdfStylePropertiesBase getPropertiesElement(OdfStylePropertiesSet set) {
        if (mPropertySetElementMap != null) {
            return mPropertySetElementMap.get(set);
        }

        return null;
    }

    /**
     * 
     * @param set
     * @return the style:*-properties element for the given set. If such element
     *         does not yet exist, it is created.
     */
    public OdfStylePropertiesBase getOrCreatePropertiesElement(OdfStylePropertiesSet set) {
        OdfStylePropertiesBase properties = null;

        if (mPropertySetElementMap != null) {
            properties = mPropertySetElementMap.get(set);
        }

        if (properties == null) {
            for (Entry<OdfName, OdfStylePropertiesSet> entry : mStylePropertiesElementToSetMap.entrySet()) {
                if (entry.getValue().equals(set)) {
                    properties = (OdfStylePropertiesBase) ((OdfFileDom) this.ownerDocument).createElementNS(entry.getKey());
                    if (getFirstChild() == null) {
                        appendChild(properties);
                    } else {
                        // make sure the properties elements are in the correct order
                        Node beforeNode = null;
                        if (set.equals(OdfStylePropertiesSet.GraphicProperties)) {
                            beforeNode = OdfElement.findFirstChildNode(StyleParagraphPropertiesElement.class, this);
                            if (beforeNode == null) {
                                beforeNode = OdfElement.findFirstChildNode(StyleTextPropertiesElement.class, this);
                            }
                        } else if (set.equals(OdfStylePropertiesSet.ParagraphProperties)) {
                            beforeNode = OdfElement.findFirstChildNode(StyleTextPropertiesElement.class, this);
                        } else if (!set.equals(OdfStylePropertiesSet.TextProperties)) {
                            beforeNode = getFirstChild();
                        }

                        if (beforeNode == null) {
                            beforeNode = getFirstChild();
                            // find first non properties node
                            while (beforeNode != null) {
                                if (beforeNode.getNodeType() == Node.ELEMENT_NODE) {
                                    if (!(beforeNode instanceof OdfStylePropertiesBase)) {
                                        break;
                                    }
                                }
                                beforeNode = beforeNode.getNextSibling();
                            }
                        }

                        insertBefore(properties, beforeNode);
                    }
                    break;
                }
            }
        }

        return properties;
    }

    /**
     * 
     * @return a property value.
     */
    public String getProperty(OdfStyleProperty prop) {
        String value = null;

        OdfStylePropertiesBase properties = getPropertiesElement(prop.getPropertySet());
        if (properties != null) {
            if (properties.hasAttributeNS(prop.getName().getUri(), prop.getName().getLocalName())) {
                return properties.getOdfAttribute(prop.getName()).getValue();
            }
        }

        OdfStyleBase parent = getParentStyle();
        if (parent != null) {
            return parent.getProperty(prop);
        }

        return value;
    }

    public boolean hasProperty(OdfStyleProperty prop) {
        if (mPropertySetElementMap != null) {
            OdfStylePropertiesBase properties = mPropertySetElementMap.get(prop.getPropertySet());
            if (properties != null) {
                return properties.hasAttributeNS(prop.getName().getUri(), prop.getName().getLocalName());
            }
        }
        return false;
    }

    @Override
    protected void onOdfNodeInserted(OdfElement node, Node refChild) {
        if (node instanceof OdfStylePropertiesBase) {
            OdfStylePropertiesSet set = mStylePropertiesElementToSetMap.get(node.getOdfName());
            if (set != null) {
                if (mPropertySetElementMap == null) {
                    mPropertySetElementMap = new HashMap<OdfStylePropertiesSet, OdfStylePropertiesBase>();
                }
                mPropertySetElementMap.put(set, (OdfStylePropertiesBase) node);
            }
        }
    }

    @Override
    protected void onOdfNodeRemoved(OdfElement node) {
        if (mPropertySetElementMap != null) {
            if (node instanceof OdfStylePropertiesBase) {
                OdfStylePropertiesSet set = mStylePropertiesElementToSetMap.get(node.getOdfName());
                if (set != null) {
                    mPropertySetElementMap.remove(set);
                }
            }
        }
    }

    public Map<OdfStyleProperty, String> getProperties(Set<OdfStyleProperty> properties) {
        HashMap<OdfStyleProperty, String> map = new HashMap<OdfStyleProperty, String>();
        for (OdfStyleProperty property : properties) {
            map.put(property, getProperty(property));
        }

        return map;
    }

    public Set<OdfStyleProperty> getStrictProperties() {
        return getFamily().getProperties();
    }

    public void removeProperty(OdfStyleProperty property) {
        if (mPropertySetElementMap != null) {
            OdfStylePropertiesBase properties = mPropertySetElementMap.get(property.getPropertySet());
            if (properties != null) {
                properties.removeAttributeNS(property.getName().getUri(), property.getName().getLocalName());
            }
        }
    }

    public void setProperties(Map<OdfStyleProperty, String> properties) {
        for (Map.Entry<OdfStyleProperty, String> entry : properties.entrySet()) {
            setProperty(entry.getKey(), entry.getValue());
        }
    }

    public void setProperty(OdfStyleProperty property, String value) {
        OdfStylePropertiesBase properties = getOrCreatePropertiesElement(property.getPropertySet());
        if (properties != null) {
        	OdfAttribute propertyAttr = ((OdfFileDom) this.ownerDocument).createAttributeNS(property.getName());
            properties.setOdfAttribute(propertyAttr);
            propertyAttr.setValue(value);
        }
    }

    /** compare one style to another one.
     *  This implements a total order on style objects.
     *
     * @param obj - the reference object with which to compare2.
     * @return 0 if this object is the same as the obj argument; -1 if this
     * object is less than the obj argument; 1 if this object is greater than
     * the obj argument
     */
    public int compareTo(Object obj) {
        if (this == obj) {
            return 0;
        }

        if (!(obj instanceof OdfStyleBase)) {
            if (obj == null) {
                throw new ClassCastException("The object to be compared is null!");
            } else {
                throw new ClassCastException("The object to be compared is not a style!");
            }
        }
        OdfStyleBase compare = (OdfStyleBase) obj;

        int c = compareNodes(this, compare);
        return c;
    }

    // Currently this function does not consider the order of child nodes, e.g.,
    //
    //		<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard">
    //			<style:paragraph-properties>
    //				<style:tab-stops>
    //					<style:tab-stop style:position="4.344cm"/>
    //				</style:tab-stops>
    //				<style:background-image xlink:href="Pictures/1.jpg" xlink:type="simple" xlink:actuate="onLoad"/>
    //			</style:paragraph-properties>
    //		</style:style>
    //
    //  and
    //
    //		<style:style style:name="P2" style:family="paragraph" style:parent-style-name="Standard">
    //			<style:paragraph-properties>
    //				<style:background-image xlink:href="Pictures/1.jpg" xlink:type="simple" xlink:actuate="onLoad"/>
    //				<style:tab-stops>
    //					<style:tab-stop style:position="4.344cm"/>
    //				</style:tab-stops>
    //			</style:paragraph-properties>
    //		</style:style>
    //
    //  are regarded non-equal
    //
    static private int compareNodes(Node compare1, Node compare2) {
        // Only styles can be equal, that are from the same element
        // (e.g. style:style and text:list-level-style-bullet are never equal)
        int c = 0;
        // if the local name is unequal (e.g. style vs. list-level-style-bullet)
        // the String compareTo will give me the order
        if ((c = compare1.getLocalName().compareTo(compare2.getLocalName())) != 0) {
            return c;
        }

        // if the namespaceURI is unequal (e.g. style vs. text)
        // the String compareTo will give me the order
        if ((c = compare1.getNamespaceURI().compareTo(compare2.getNamespaceURI())) != 0) {
            return c;
        }

        // compare number of attributes
        int attr_count1 = compare1.getAttributes() != null ? compare1.getAttributes().getLength() : 0;
        int attr_count2 = compare2.getAttributes() != null ? compare2.getAttributes().getLength() : 0;

        // attributes with default values do not exist in the ODFDOM XML model
        if (attr_count1 != attr_count2) {
            return attr_count1 < attr_count2 ? -1 : 1;
        }

        // sort attributes by namespace:localname, omit style name
        SortedMap<String, String> attr1 = getSortedAttributes(compare1);
        SortedMap<String, String> attr2 = getSortedAttributes(compare2);

        // compare2 attribute names and values
        Iterator<String> keySet1Iter = attr1.keySet().iterator();
        Iterator<String> keySet2Iter = attr2.keySet().iterator();

        while (keySet1Iter.hasNext()) {
            String key1 = keySet1Iter.next();
            String key2 = keySet2Iter.next();

            if ((c = key1.compareTo(key2)) != 0) {
                return c;
            }

            String attrValue1 = attr1.get(key1);
            String attrValue2 = attr2.get(key1);
            
            if ((c = attrValue1.compareTo(attrValue2)) != 0) {
                return c;
            }
        }

        // now number of child elements
        ArrayList<Node> nodes1 = getNonEmptyChildNodes(compare1);
        ArrayList<Node> nodes2 = getNonEmptyChildNodes(compare2);

        if (nodes1.size() != nodes2.size()) {
            return nodes1.size() < nodes2.size() ? -1 : 1;
        }

        // now compare child elements
        Iterator<Node> iter1 = nodes1.iterator();
        Iterator<Node> iter2 = nodes2.iterator();

        while (iter1.hasNext()) {
            Node child1 = iter1.next();
            Node child2 = iter2.next();
            if ((c = compareNodes(child1, child2)) != 0) {
                return c;
            }
        }

        return 0;
    }

    // helper function for compareTo.
    // sorts attributes by namespace:localname
    private static SortedMap<String, String> getSortedAttributes(Node node) {
        SortedMap<String, String> ret = new TreeMap<String, String>();
        NamedNodeMap attrs = node.getAttributes();
        for (int i = 0; i < attrs.getLength(); i++) {
            Node cur = attrs.item(i);
            String namespace = cur.getNamespaceURI();
            String local = cur.getLocalName();
            // styles can be still the same, even if they have different names
            if (local.equals("name") && namespace.equals(OdfDocumentNamespace.STYLE.getUri())) {
                continue;
            }
            ret.put(namespace + ":" + local, ((Attr) cur).getValue());
        }
        return ret;
    }

    // helper function for compareTo.
    // all except "empty" text nodes will be returned
    private static ArrayList<Node> getNonEmptyChildNodes(Node node) {
        ArrayList<Node> ret = new ArrayList<Node>();
        NodeList childs = node.getChildNodes();
        for (int i = 0; i < childs.getLength(); i++) {
            Node cur = childs.item(i);
            if (cur.getNodeType() == Node.TEXT_NODE) {
                if (cur.getNodeValue().trim().length() == 0) {
                    continue; // skip whitespace text nodes
                }
            }
            ret.add(cur);
        }
        return ret;
    }

    /** Indicates if some other object is equal to this one.
     *  The attribute style:name is ignored during compare2.
     *
     * @param obj - the reference object with which to compare2.
     * @return true if this object is the same as the obj argument; false otherwise.
     */
	@Override
	public boolean equals(Object obj) {
        return obj != null ? compareTo(obj) == 0 : false;
	}

    @Override
    public int hashCode() {
        return 59 * 7 + (this.mPropertySetElementMap != null ? this.mPropertySetElementMap.hashCode() : 0);
    }
    
    public OdfStyleFamily getFamily() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public OdfStyleBase getParentStyle() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
