/**
 * 编码/解码XML文件的相关函数。
 * @create   2004-9-29 source0
 * @author   source0 source0@hotmail.com
 * @copyright 版权所有（C） 2004  source0
 *                这一程序是自由软件，你可以遵照自由软件基金会出版的GNU通用
 *            公共许可证条款来修改和重新发布这一程序。或者用许可证的第二版，
 *            或者（根据你的选择）用任何更新的版本。
 *                发布这一程序的目的是希望它有用，但没有任何担保。甚至没有
 *            适合特定目的的隐含的担保。更详细的情况请参阅GNU通用公共许可证。
 *                你应该已经和程序一起收到一份GNU通用公共许可证的副本。如果
 *            还没有，写信给：
 *                The Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
 *                MA02139, USA
 */


/**
 * 读取指定的XML文件并调用指定的文件处理函数。
 * @param file 字符串。文件名。
 * @param parser 字符串。用于输出或者处理数据的函数名。
 * @create 2004-9-29 source0
 */
function loadXML(file, parser) {
    /* http://www.sitepoint.com/article/xml-javascript-mozilla/2 */
    var moz = (document.implementation && document.implementation.createDocument);
    var ie = (window.ActiveXObject);

    var xmlDoc;
    if (moz) {
        xmlDoc = document.implementation.createDocument("", "", null)
        xmlDoc.onload = function (){
            eval("" + parser + "(xmlDoc)");
        }
    } else if (ie) {
        xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async = false;
        xmlDoc.onreadystatechange = function () {
             // 0 Object is not initialized
             // 1 Loading object is loading data
             // 2 Loaded object has loaded data
             // 3 Data from object can be worked with
             // 4 Object completely initialized
            if (xmlDoc.readyState == 4)
            {
                eval("" + parser + "(xmlDoc)");
            }
        };
        /* 如果需要解析xml文本，这样调用
        xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async = false;
        xmlDoc.onreadystatechange = function () {...}//可以去掉此行代码，在 loadXML 方法后自行调用文本处理函数
        xmlDoc.loadXML(text);
         */

    }
    xmlDoc.load(file);
}

/**
 * 载入一个角色的数据。
 * @param xmlDoc 保存有指定角色数据的xml文档实例。
 * @return 解码后生成的角色对象。
 * @create 2004-10-06 source0
 */
function decodeRole(xmlDoc){
    var roleDoc = xmlDoc.getElementsByTagName("role")[0];
    var role = new CRole(roleDoc.getAttribute("id"), roleDoc.getAttribute("name"), new Array());
    var classes = roleDoc.getElementsByTagName("class");
    for(var i = 0; i < classes.length; i++) {
        role.talentClasses[i] = decodeTalentClass(classes[i]);
    }
    for(var i = 0; i < classes.length; i++) {
        /* 将天赋图标放入图片池中。 */
        var tvs = role.talentClasses[i].getTalentViews();
        var image = null;
        for ( var key in tvs ){
            image = new Image(40, 40);
            image.src = role.talentClasses[i].path + "/" + tvs[key].icon;
            IMAGE_POOL[role.talentClasses[i].path + "/" + tvs[key].icon] = image;
        }
    }

    return role;

    /**
     * 载入一个天赋类。
     * @param classDoc class标签的对象。
     * @return 天赋类的实例。
     */
    function decodeTalentClass(classDoc){
        var talentClass = new CTalentClass(
            classDoc.getAttribute("id"),
            classDoc.getAttribute("name"),
            classDoc.getAttribute("path"),
            classDoc.getAttribute("image"));
        var talents = classDoc.getElementsByTagName("talent");
        var icon = null;
        var column = 0;
        for( var i = 0; i < talents.length; i++ ){
            column = talents[i].getAttribute("column");
            icon = talents[i].getAttribute("icon");
            talentClass.add(decodeTalentModel(talents[i]), icon, column);
        }
        return talentClass;
    }
    /**
     * 载入一个天赋数据。
     * @param talentDoc talent标签的对象。
     * @return 天赋实例。
     */
    function decodeTalentModel(talentDoc){
        var isImprove = talentDoc.getElementsByTagName("improve").length > 0;

        var talentType = TALENT_TYPE_IMPROVE;
        var effect = null;
        if ( isImprove)
        {/* 读出强化数据。 */
            effect = decodeTalentImprove(talentDoc);
        }
        else
        {/* 读出技能数据。 */
            talentType = TALENT_TYPE_SKILL;
            effect = decodeTalentSkill(talentDoc);

        }
        /* 读出天赋的需求数据。 */
        var requirements = decodeTalentRequirements(talentDoc);

        return new CTalentModel(talentDoc.getAttribute("id"), talentDoc.getAttribute("name"), talentDoc.getAttribute("tier"), talentType, effect, requirements);
    }

    /**
     * 载入一个强化型天赋的强化效果数据。
     * @param talentDoc talent标签的对象。
     * @return 天赋强化效果实例。
     */
    function decodeTalentImprove(talentDoc){
        var xmlDoc = talentDoc.getElementsByTagName("improve")[0];
        var desc = xmlDoc.getAttribute("description");
        var maxRank = xmlDoc.getAttribute("maxRank");
        return new CTalentImprove(desc, maxRank, decodeTalentImproveEffects(xmlDoc));
    }

    /**
     * 载入一个强化型天赋的所有效果数据。
     * @param talentDoc talent标签的对象。
     * @return 天赋的技能实例。
     */
    function decodeTalentImproveEffects(effectsDoc){
        var xmlEffects = effectsDoc.getElementsByTagName("effects");
        var result = new Array();
        if ( xmlEffects.length <= 0 ){
            return result;
        }
        var effects = xmlEffects[0].getElementsByTagName("effect");
        for ( var i = 0; i < effects.length ; i++ ){
            result[result.length] = new CTalentImproveEffect(
                effects[i].getAttribute("id"),
                effects[i].getAttribute("unit"),
                effects[i].getAttribute("initValue"),
                effects[i].getAttribute("increment")
            );
        }
        return result;
    }

    /**
     * 载入一个技能型天赋的技能数据。
     * @param talentDoc talent标签的对象。
     * @return 天赋的技能实例。
     */
    function decodeTalentSkill(talentDoc){
        var xmlDoc = talentDoc.getElementsByTagName("skill")[0];
        var desc = xmlDoc.getAttribute("description");
        var consume = xmlDoc.getAttribute("consume");
        var consumeType = xmlDoc.getAttribute("consumeType");
        var castTime = xmlDoc.getAttribute("castTime");
        var cooldown = xmlDoc.getAttribute("cooldown");
        var maxRange = xmlDoc.getAttribute("maxRange");
        var minRange = xmlDoc.getAttribute("minRange");
        var remark = xmlDoc.getAttribute("remark");
        return new CTalentSkill(desc, consume, consumeType, castTime, cooldown, maxRange, minRange, remark);

    }

    /**
     * 载入天赋的需求信息。
     * @param talent标签的对象。
     * @return 天赋需求实例的数组。如果没有需求，返回空数组。
     */
    function decodeTalentRequirements(talentDoc){
        var requirements = talentDoc.getElementsByTagName("requirements");
        var result = new Array();
        if ( requirements.length > 0 ){
            var reqs = requirements[0].getElementsByTagName("requirement");
            for ( var r = 0; r < reqs.length ; r++ ){
                var req = new CTalentRequirement(reqs[r].getAttribute("id"), reqs[r].getAttribute("rank"));
                result[result.length] = req;
            }
        }
        return result;
    }
}

/**
 * 编码一个角色的数据。
 * @param role 需要进行编码的角色对象。
 * @create 2004-10-06 source0
 */
function encodeRole(role){
    var attrs = null;
    var degree = 0;
    var indents = new Array('');
    var rt = new String();

    rt += '<' + '?xml version="1.0" encoding="GBK"?' + '>\n';
    start('role id="' + role.id + '" name="' + role.name + '"');

    for ( var key in role.talentClasses ){
        encodeTalentClass(role.talentClasses[key]);
    }

    end('role');

    return rt;

    function getIndent(degree){
        while ( degree >= indents.length ){
            indents[indents.length] = indents[indents.length - 1] + '  ';
        }
        return indents[degree];
    }
    function start(s){
        rt += getIndent(degree) + '<' + s + '>\n';
        degree ++;
    }
    function end(s){
        degree--;
        rt += getIndent(degree) + '<' + '/' + s + '>\n';
    }

    function encodeTalentClass(talentClass){
        start('class id="' + encodeTag(talentClass.id) + '"'
            + ' name="' + encodeTag(talentClass.name) + '"'
            + ' path="' + encodeTag(talentClass.path) + '"'
            + ' image="' + encodeTag(talentClass.image) + '"');

        var tvsArray = new Array();
        var tvs = talentClass.getTalentViews();
        for( var key in tvs ){
            tvsArray[tvs[key].model.tier + "_" + tvs[key].column] = tvs[key];
        }

        for ( var t = 0; t < MAX_TIER; t++ ){
            for ( var c = 0; c < MAX_COLUMN; c++ ){
                if ( null != tvsArray[t + "_" + c] ){
                    encodeTalent(tvsArray[t + "_" + c]);
                }
            }
        }
        end('class');
    }
    function encodeTalent(talentView){
        var model = talentView.model;
        start('talent id="' + encodeTag(model.id) + '"'
            + ' name="' + encodeTag(model.name) + '"'
            + ' tier="' + model.tier + '"'
            + ' column="' + talentView.column + '"'
            + ' icon="' + encodeTag(talentView.icon) + '"');

        if ( model.type == TALENT_TYPE_IMPROVE )
        {/* 强化数据。 */
            encodeTalentImprove(model.data);
        }
        else
        {/* 技能数据。 */
            encodeTalentSkill(model.data);

        }
        /* 读出天赋的需求数据。 */
        encodeTalentRequirements(model.requirements);

        end('talent');
    }
    function encodeTalentImprove(improve){
        attrs = new String();
        attrs += ' description="' + encodeTag(improve.description) + '"';
        attrs += ' maxRank="' + improve.maxRank + '"';
        start('improve' + attrs);

        start('effects');
        for ( var key in improve.effects ){
            encodeTalentImproveEffects(improve.effects[key]);
        }
        end('effects');
        end('improve');
    }
    function encodeTalentImproveEffects(effect){
        attrs = new String();
        attrs += ' id="' + encodeTag(effect.id) + '"';
        if ( null != effect.unit ){
            attrs += ' unit="' + encodeTag(effect.unit) + '"';
        }
        if ( null != effect.initValue ){
            attrs += ' initValue="' + effect.initValue + '"';
        }
        if ( effect.increment > 0 ){
            attrs += ' increment="' + effect.increment + '"';
        }
        start('effect' + attrs);
        end('effect');
    }
    function encodeTalentSkill(skill){
        attrs = new String();
        attrs += ' description="' + encodeTag(skill.description) + '"';
        attrs += ' consumeType="' + skill.consumeType + '"';
        if ( skill.consume > 0 ){
           attrs += ' consume="' + skill.consume + '"';
        }
        if ( skill.castTime > 0 ){
            attrs += ' castTime="' + skill.castTime + '"';
        }
        if ( skill.cooldown > 0 ){
            attrs += ' cooldown="' + skill.cooldown + '"';
        }
        if ( skill.maxRange > 0 ){
            attrs += ' maxRange="' + skill.maxRange + '"';
        }
        if ( skill.minRange > 0 ){
            attrs += ' minRange="' + skill.minRange + '"';
        }
        if ( null != skill.remark ){
            attrs += ' remark="' + encodeTag(skill.remark) + '"';
        }

        start('skill' + attrs);
        end('skill');
    }
    function encodeTalentRequirements(requirements){
        if (( null == requirements ) || ( 0 >= requirements.length )){
            return;
        }
        start('requirements');
        for ( var key in requirements ){
            requirements[key];
            start('requirement id="' + requirements[key].talent + '" rank="' + requirements[key].rank + '"');
            end('requirement');

        }
        end('requirements');
    }
}
