/*
 * 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.
 */

package freemarker.template.utility;

import java.util.HashMap;
import java.util.List;

import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

import freemarker.ext.dom.NodeModel;
import freemarker.template.SimpleHash;
import freemarker.template.SimpleScalar;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateHashModel;
import freemarker.template.TemplateMethodModel;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateSequenceModel;
import freemarker.template._TemplateAPI;

/**
 * A convenient wrapper class for wrapping a Node in the W3C DOM API.
 *
 * @deprecated Use {@link NodeModel} instead
 */
@Deprecated
public class DOMNodeModel implements TemplateHashModel {

    static private HashMap equivalenceTable = new HashMap();
    static {
        equivalenceTable.put("*", "children");
        equivalenceTable.put("@*", "attributes");
    }

    private Node node;
    private HashMap cache = new HashMap();

    public DOMNodeModel(Node node) {
        this.node = node;
    }

    public TemplateModel get(String key) throws TemplateModelException {
        TemplateModel result = null;
        if (equivalenceTable.containsKey(key)) {
            key = (String) equivalenceTable.get(key);
        }
        if (cache.containsKey(key)) {
            result = (TemplateModel) cache.get(key);
        }
        if (result == null) {
            if ("attributes".equals(key)) {
                NamedNodeMap attributes = node.getAttributes();
                if (attributes != null) {
                    SimpleHash hash = new SimpleHash(_TemplateAPI.SAFE_OBJECT_WRAPPER);
                    for (int i = 0; i < attributes.getLength(); i++) {
                        Attr att = (Attr) attributes.item(i);
                        hash.put(att.getName(), att.getValue());
                    }
                    result = hash;
                }
            } else if (key.charAt(0) == '@') {
                if (node instanceof Element) {
                    String attValue = ((Element) node).getAttribute(key.substring(1));
                    result = new SimpleScalar(attValue);
                } else {
                    throw new TemplateModelException("Trying to get an attribute value for a non-element node");
                }
            } else if ("is_element".equals(key)) {
                result = (node instanceof Element) ?
                    TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
            } else if ("is_text".equals(key)) {
                result = (node instanceof Text) ?
                    TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
            } else if ("name".equals(key)) {
                result = new SimpleScalar(node.getNodeName());
            } else if ("children".equals(key)) {
                result = new NodeListTM(node.getChildNodes());
            } else if ("parent".equals(key)) {
                Node parent = node.getParentNode();
                result = (parent == null) ? null : new DOMNodeModel(parent);
            } else if ("ancestorByName".equals(key)) {
                result = new AncestorByName();
            } else if ("nextSibling".equals(key)) {
                Node next = node.getNextSibling();
                result = (next == null) ? null : new DOMNodeModel(next);
            } else if ("previousSibling".equals(key)) {
                Node previous = node.getPreviousSibling();
                result = (previous == null) ? null : new DOMNodeModel(previous);
            } else if ("nextSiblingElement".equals(key)) {
                Node next = nextSiblingElement(node);
                result = (next == null) ? null : new DOMNodeModel(next);
            } else if ("previousSiblingElement".equals(key)) {
                Node previous = previousSiblingElement(node);
                result = (previous == null) ? null : new DOMNodeModel(previous);
            } else if ("nextElement".equals(key)) {
                Node next = nextElement(node);
                result = (next == null) ? null : new DOMNodeModel(next);
            } else if ("previousElement".equals(key)) {
                Node previous = previousElement(node);
                result = (previous == null) ? null : new DOMNodeModel(previous);
            } else if ("text".equals(key)) {
                result = new SimpleScalar(getText(node));
            }
            cache.put(key, result);
        }
        return result;
    }

    public boolean isEmpty() {
        return false;
    }

    static private String getText(Node node) {
        String result = "";
        if (node instanceof Text) {
            result = ((Text) node).getData();
        } else if (node instanceof Element) {
            NodeList children = node.getChildNodes();
            for (int i = 0; i < children.getLength(); i++) {
                result += getText(children.item(i));
            }
        }
        return result;
    }

    static private Element nextSiblingElement(Node node) {
        Node next = node;
        while (next != null) {
            next = next.getNextSibling();
            if (next instanceof Element) {
                return (Element) next;
            }
        }
        return null;
    }

    static private Element previousSiblingElement(Node node) {
        Node previous = node;
        while (previous != null) {
            previous = previous.getPreviousSibling();
            if (previous instanceof Element) {
                return (Element) previous;
            }
        }
        return null;
    }

    static private Element nextElement(Node node) {
        if (node.hasChildNodes()) {
            NodeList children = node.getChildNodes();
            for (int i = 0; i < children.getLength(); i++) {
                Node child = children.item(i);
                if (child instanceof Element) {
                    return (Element) child;
                }
            }
        }
        Element nextSiblingElement = nextSiblingElement(node);
        if (nextSiblingElement != null) {
            return nextSiblingElement;
        }
        Node parent = node.getParentNode();
        while (parent instanceof Element) {
            Element next = nextSiblingElement(parent);
            if (next != null) {
                return next;
            }
            parent = parent.getParentNode();
        }
        return null;
    }

    static private Element previousElement(Node node) {
        Element result = previousSiblingElement(node);
        if (result != null) {
            return result;
        }
        Node parent = node.getParentNode();
        if (parent instanceof Element) {
            return (Element) parent;
        }
        return null;
    }

    void setParent(DOMNodeModel parent) {
        if (parent != null) {
            cache.put("parent", parent);
        }
    }

    String getNodeName() {
        return node.getNodeName();
    }


    class AncestorByName implements TemplateMethodModel {
        public Object exec(List arguments) throws TemplateModelException {
            if (arguments.size() != 1) {
                throw new TemplateModelException("Expecting exactly one string argument here");
            }
            String nodeName = (String) arguments.get(0);
            DOMNodeModel ancestor = (DOMNodeModel) DOMNodeModel.this.get("parent");
            while (ancestor != null) {
                if (nodeName.equals(ancestor.getNodeName())) {
                    return ancestor;
                }
                ancestor = (DOMNodeModel) ancestor.get("parent");
            }
            return null;
        }
    }


    class NodeListTM implements TemplateSequenceModel, TemplateMethodModel {

        private NodeList nodeList;
        private TemplateModel[] nodes;

        NodeListTM(NodeList nodeList) {
            this.nodeList = nodeList;
            nodes = new TemplateModel[nodeList.getLength()];
        }

        public TemplateModel get(int index) {
            DOMNodeModel result = (DOMNodeModel) nodes[index];
            if (result == null) {
                result = new DOMNodeModel(nodeList.item(index));
                nodes[index] = result;
                result.setParent(DOMNodeModel.this);
            }
            return result;
        }

        public int size() {
            return nodes.length;
        }

        public Object exec(List arguments) throws TemplateModelException {
            if (arguments.size() != 1) {
                throw new TemplateModelException("Expecting exactly one string argument here");
            }
            if (!(node instanceof Element)) {
                throw new TemplateModelException("Expecting element here.");
            }
            Element elem = (Element) node;
            return new NodeListTM(elem.getElementsByTagName((String) arguments.get(0)));
        }
    }
}

