//////////////////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2014-present, Egret Technology.
//  All rights reserved.
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of the Egret nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY EGRET AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
//  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL EGRET AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA,
//  OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
//  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////////////

namespace egret.web {

    /**
     * @private
     * XML节点基类
     */
    export class XMLNode {

        /**
         * @private
         */
        public constructor(nodeType:number, parent:XML) {
            this.nodeType = nodeType;
            this.parent = parent;
        }

        /**
         * @private
         * 节点类型，1：XML，2：XMLAttribute，3：XMLText
         */
        public nodeType:number;
        /**
         * @private
         * 节点所属的父级节点
         */
        public parent:XML;
    }

    /**
     * @private
     * XML节点对象
     */
    export class XML extends XMLNode {

        /**
         * @private
         */
        public constructor(localName:string, parent:XML, prefix:string, namespace:string, name:string) {
            super(1, parent);
            this.localName = localName;
            this.prefix = prefix;
            this.namespace = namespace;
            this.name = name;
        }

        /**
         * @private
         * 当前节点上的属性列表
         */
        public attributes:{[key:string]:string} = {};
        /**
         * @private
         * 当前节点的子节点列表
         */
        public children:XMLNode[] = [];
        /**
         * @private
         * 节点完整名称。例如节点 <s:Button/> 的 name 为：s:Button
         */
        public name:string;
        /**
         * @private
         * 节点的命名空间前缀。例如节点 <s:Button/> 的 prefix 为：s
         */
        public prefix:string;
        /**
         * @private
         * 节点的本地名称。例如节点 <s:Button/> 的 localName 为：Button
         */
        public localName:string;
        /**
         * @private
         * 节点的命名空间地址。例如节点 <s:Skin xmlns:s="http://ns.egret.com/eui"/> 的 namespace 为： http://ns.egret.com/eui
         */
        public namespace:string;
    }

    /**
     * @private
     * XML文本节点
     */
    export class XMLText extends XMLNode {
        /**
         * @private
         */
        public  constructor(text:string, parent:XML) {
            super(3, parent);
            this.text = text;
        }

        /**
         * @private
         * 文本内容
         */
        public text:string;
    }

    /**
     * @private
     * 解析字符串为XML对象
     * @param text 要解析的字符串
     */
    function parse(text:string):XML {
        let xmlDocStr = egret_native.xmlStr2JsonStr(text);
        //替换换行符
        xmlDocStr = xmlDocStr.replace(/\n/g,"\\n");
        let xmlDoc = JSON.parse(xmlDocStr);
        return parseNode(xmlDoc, null);
    }

    /**
     * @private
     * 解析一个节点
     */
    function parseNode(node, parent:XML):XML {
        if(node.localName=="parsererror"){
            throw new Error(node.textContent);
        }
        let xml = new XML(node.localName, parent, node.prefix, node.namespace, node.name);
        let nodeAttributes = node.attributes;
        let attributes = xml.attributes;
        for (let key in nodeAttributes) {
            attributes[key] = xml["$" + key] = nodeAttributes[key];
        }
        let childNodes = node.children;
        let length = childNodes.length;
        let children = xml.children;
        for (let i = 0; i < length; i++) {
            let childNode = childNodes[i];
            let nodeType = childNode.nodeType;
            let childXML:any = null;
            if (nodeType == 1) {
                childXML = parseNode(childNode, xml);
            }
            else if (nodeType == 3) {
                let text = childNode.text.trim();
                if (text) {
                    childXML = new XMLText(text, xml);
                }
            }
            if (childXML) {
                children.push(childXML);
            }
        }
        return xml;
    }

    egret.XML = {parse: parse};
}