/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
 *
 * 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 com.android.ide.eclipse.adt.internal.editors.layout;

import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
import com.android.layoutlib.api.IXmlPullParser;

import org.w3c.dom.Node;
import org.xmlpull.v1.XmlPullParserException;

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

/**
 * {@link IXmlPullParser} implementation on top of {@link UiElementNode}.
 * <p/>It's designed to work on layout files, and will most likely not work on other resource
 * files.
 */
public final class UiElementPullParser extends BasePullParser {
    
    private final ArrayList<UiElementNode> mNodeStack = new ArrayList<UiElementNode>();
    private UiElementNode mRoot;
    
    public UiElementPullParser(UiElementNode top) {
        super();
        mRoot = top;
        push(mRoot);
    }
    
    private UiElementNode getCurrentNode() {
        if (mNodeStack.size() > 0) {
            return mNodeStack.get(mNodeStack.size()-1);
        }
        
        return null;
    }
    
    private Node getAttribute(int i) {
        if (mParsingState != START_TAG) {
            throw new IndexOutOfBoundsException();
        }

        // get the current uiNode
        UiElementNode uiNode = getCurrentNode();
        
        // get its xml node
        Node xmlNode = uiNode.getXmlNode();

        if (xmlNode != null) {
            return xmlNode.getAttributes().item(i);
        }

        return null;
    }
    
    private void push(UiElementNode node) {
        mNodeStack.add(node);
    }
    
    private UiElementNode pop() {
        return mNodeStack.remove(mNodeStack.size()-1);
    }

    // ------------- IXmlPullParser --------

    /**
     * {@inheritDoc}
     * 
     * This implementation returns the underlying DOM node.
     */
    public Object getViewKey() {
        return getCurrentNode();
    }

    // ------------- XmlPullParser --------

    public String getPositionDescription() {
        return "XML DOM element depth:" + mNodeStack.size();
    }

    public int getAttributeCount() {
        UiElementNode node = getCurrentNode();
        if (node != null) {
            return node.getUiAttributes().size();
        }

        return 0;
    }

    public String getAttributeName(int i) {
        Node attribute = getAttribute(i);
        if (attribute != null) {
            return attribute.getLocalName();
        }

        return null;
    }

    public String getAttributeNamespace(int i) {
        Node attribute = getAttribute(i);
        if (attribute != null) {
            return attribute.getNamespaceURI();
        }
        return ""; //$NON-NLS-1$
    }

    public String getAttributePrefix(int i) {
        Node attribute = getAttribute(i);
        if (attribute != null) {
            return attribute.getPrefix();
        }
        return null;
    }

    public String getAttributeValue(int i) {
        Node attribute = getAttribute(i);
        if (attribute != null) {
            return attribute.getNodeValue();
        }
        
        return null;
    }

    public String getAttributeValue(String namespace, String localName) {
        // get the current uiNode
        UiElementNode uiNode = getCurrentNode();
        
        // get its xml node
        Node xmlNode = uiNode.getXmlNode();
        
        if (xmlNode != null) {
            Node attribute = xmlNode.getAttributes().getNamedItemNS(namespace, localName);
            if (attribute != null) {
                return attribute.getNodeValue();
            }
        }

        return null;
    }

    public int getDepth() {
        return mNodeStack.size();
    }

    public String getName() {
        if (mParsingState == START_TAG || mParsingState == END_TAG) {
            return getCurrentNode().getDescriptor().getXmlLocalName();
        }

        return null;
    }

    public String getNamespace() {
        if (mParsingState == START_TAG || mParsingState == END_TAG) {
            return getCurrentNode().getDescriptor().getNamespace();
        }

        return null;
    }

    public String getPrefix() {
        if (mParsingState == START_TAG || mParsingState == END_TAG) {
            // FIXME will NEVER work
            if (getCurrentNode().getDescriptor().getXmlLocalName().startsWith("android:")) { //$NON-NLS-1$
                return "android"; //$NON-NLS-1$
            }
        }

        return null;
    }

    public boolean isEmptyElementTag() throws XmlPullParserException {
        if (mParsingState == START_TAG) {
            return getCurrentNode().getUiChildren().size() == 0;
        }
        
        throw new XmlPullParserException("Call to isEmptyElementTag while not in START_TAG",
                this, null);
    }
    
    @Override
    public void onNextFromStartDocument() {
        onNextFromStartTag();
    }
    
    @Override
    public void onNextFromStartTag() {
        // get the current node, and look for text or children (children first)
        UiElementNode node = getCurrentNode();
        List<UiElementNode> children = node.getUiChildren();
        if (children.size() > 0) {
            // move to the new child, and don't change the state.
            push(children.get(0));
            
            // in case the current state is CURRENT_DOC, we set the proper state.
            mParsingState = START_TAG;
        } else {
            if (mParsingState == START_DOCUMENT) {
                // this handles the case where there's no node.
                mParsingState = END_DOCUMENT;
            } else {
                mParsingState = END_TAG;
            }
        }
    }
    
    @Override
    public void onNextFromEndTag() {
        // look for a sibling. if no sibling, go back to the parent
        UiElementNode node = getCurrentNode();
        node = node.getUiNextSibling();
        if (node != null) {
            // to go to the sibling, we need to remove the current node,
            pop();
            // and add its sibling.
            push(node);
            mParsingState = START_TAG;
        } else {
            // move back to the parent
            pop();
            
            // we have only one element left (mRoot), then we're done with the document.
            if (mNodeStack.size() == 1) {
                mParsingState = END_DOCUMENT;
            } else {
                mParsingState = END_TAG;
            }
        }
    }
}
