/**
 * @fileoverview HKMA FlashMenu 核心文件。
 */

/**
 * HKMA MagicHighlight 通用高亮组件。
 * @class 可定制式高亮组件，自由点亮单个或多个HTML元素。<br/>
 * <i><a href="http://source.dev.hkma.org.gz/common/util/magicHighlight/doc/magicHighlight.htm">
 * 相关代码示例及功能演示。
 * </a></i>
 * @constructor
 * @param {String} effectDie 效果消逝(事件名)
 * @param {String} effectHold 效果保持(事件名)
 * @param {int} holdLimit 保持限制
 */
HKMA.MagicHighlight = function (effectDie,effectHold,holdLimit)
{
    /**
     * 存储旧目标原有外观
     * @type Any
     */
    this.memory = null;
    
    /**
     * 当前高亮的目标
     * @type Object
     */
    this.target = undefined;
    
    /**
     * 存储旧目标
     * @type Object
     */
    this.jump = undefined;
    
    /**
     * 效果消逝(事件名)
     * @type String
     */
    this.effectDie = effectDie;
    
    /**
     * 效果保持(事件名)
     * @type String
     */
    this.effectHold = effectHold;
    
    /**
     * 保持限制
     * @type int
     */
    this.holdLimit = holdLimit;
    
    /**
     * 保持配额
     * @type int
     */
    this.holdQuota = holdLimit;
    
    /**
     * MagicHighlight 内部唯一标识
     * @type String
     */
    this.id = HKMA.MagicHighlight.makeID("magicHighlight",HKMA.MagicHighlight._ids);
};

/**
 * MagicHighlight 设置。
 * @param {Array} params MagicHighlight 设置项
 * @type Object
 * @return MagicHighlight 对象
 */
HKMA.MagicHighlight.setup = function (params)
{
    paramsList = ["id"];
    
    function param_default(pname, value)
    {
        if (typeof params[pname] == "undefined")
        {
            params[pname] = value;
        }
        paramsList.push(pname);
    };
    
    // 接收事件名指定高亮效果何时消逝。
    
    param_default("effectDie","never");
    
    // 接收事件名指定高亮效果何时保持。
    
    param_default("effectHold","never");
    
    // 接收数字指定高亮效果保持的配额。
    
    param_default("holdLimit","never");
    
    var magicHighlight = new HKMA.MagicHighlight(params.effectDie,params.effectHold,params.holdLimit);

    return magicHighlight;
};

/**
 * 容纳每个新建高亮组件编号。
 */
HKMA.MagicHighlight._ids = {};

/**
 * 构成新高亮组件编号。
 * @param {String} code 代号
 * @param {int} id 编号，如果这个参数不存在则为自增量。
 * @type String
 * @return 菜单编号
 */
HKMA.MagicHighlight.makeID = function(code, carrier)
{
    if (typeof carrier[code] == "undefined")
    {
        carrier[code] = 0;
    }
        
    id = ++carrier[code];
    
    return code + id;
};

/**
 * 辨别改变类型。
 * @param {Object} changeObj 待改变对象。
 * @type String
 * @return 改变类型
 */
HKMA.MagicHighlight.changeType = function(changeObj)
{
    var changeType = "unknown";
    
    if(changeObj.tagName == "IMG")
    {
        changeType = "src";
    }
    else
    {
        changeType = "className";
    }
    
    return changeType;
};

/**
 * 标记对象的外观。
 * @param {Object} tagTarget 待标记对象。
 */
HKMA.MagicHighlight.markFace = function (tagTarget)
{
    var backupValue = null;
    var changeType = HKMA.MagicHighlight.changeType(tagTarget);
    
    // 改变类型为样式表或属性设置形式。
    
    if(changeType == "className")
    {
        // 属性优先级 1
        
        backupValue = tagTarget.getAttribute("style").background;
        
        if("" != backupValue)
        {
            tagTarget.setAttribute("backupType","background");
            tagTarget.setAttribute("backupValue",backupValue);
            tagTarget.getAttribute("style").background = "";
            return;
        }
        
        // 属性优先级 2
        
        backupValue = tagTarget.getAttribute("style").backgroundColor;
        
        if("" != backupValue)
        {
            tagTarget.setAttribute("backupType","bgColor");
            tagTarget.setAttribute("backupValue",backupValue);
            tagTarget.getAttribute("style").backgroundColor = "";
            return;
        }
        
        // 属性优先级 3
        
        backupValue = tagTarget.getAttribute("className");
        
        if("" != backupValue)
        {
            tagTarget.setAttribute("backupType","className");
            tagTarget.setAttribute("backupValue",backupValue);
            tagTarget.removeAttribute("className");
            return;
        }
        
        // 属性优先级 4
        
        backupValue = tagTarget.getAttribute("background");
        
        if(null != backupValue)
        {
            tagTarget.setAttribute("backupType","background");
            tagTarget.setAttribute("backupValue",backupValue);
            tagTarget.removeAttribute("background");
            return;
        }
        
        // 属性优先级 5
        
        backupValue = tagTarget.getAttribute("bgColor");
        
        if("" != backupValue)
        {
            tagTarget.setAttribute("backupType","bgColor");
            tagTarget.setAttribute("backupValue",backupValue);
            tagTarget.removeAttribute("bgcolor");
            return;
        }
    }
    
    // 改变类型为路径形式。
    
    if(changeType == "src")
    {
        backupValue = tagTarget.getAttribute("src");
        
        if("" != backupValue)
        {
            tagTarget.setAttribute("backupType","src");
            tagTarget.setAttribute("backupValue",backupValue);
            tagTarget.removeAttribute("src");
            return;
        }
    }
};

/**
 * 高亮单个标记的效果。
 * @param {String} face 如待改变对象被辨别为图片则 face 被理解为路径，其它情况则为样式名。
 * @param {function} holdGoOn 保持高亮后执行的函数接口(可选)。
 */
HKMA.MagicHighlight.prototype.onTag = function (face,holdGoOn)
{

    this.kindle(face,event.srcElement,holdGoOn);
};

/**
 * 点亮多个标记的效果。
 * @param {String} face 如待改变对象被辨别为图片则 face 被理解为路径，其它情况则为样式名。
 * @param {Object} tagTarget 期望点亮的父对象。
 * @param {function} holdGoOn 保持高亮后执行的函数接口。
 */
HKMA.MagicHighlight.prototype.onTags = function (face,tagTarget,holdGoOn)
{
    var newTarget = event.srcElement;
    
    while(newTarget.tagName != tagTarget)
    {
        newTarget = newTarget.parentElement;
    }
    
    this.kindle(face,newTarget,holdGoOn);
};

/**
 * 激活高亮效果。
 * @param {String} face 如待改变对象被辨别为图片则 face 被理解为路径，其它情况则为样式名。
 * @param {Object} newTarget 待改变对象。
 * @param {function} holdGoOn 保持高亮后执行的函数接口(可选)。
 */
HKMA.MagicHighlight.prototype.kindle = function (face,newTarget,holdGoOn)
{
    var changeType = HKMA.MagicHighlight.changeType(newTarget);
    
    /* 此 this.target 指的是旧目标,打开注释: 在转移目标的时候即恢复旧目标原便有样式。
    
    if (typeof this.target != "undefined")
    {
        //this.target.setAttribute(changeType,this.memory);
    }
    
    */

    this.memory = newTarget.getAttribute(changeType);
    this.target = newTarget;
    
    if(null == newTarget.getAttribute("backupType") && null == newTarget.getAttribute("backupValue"))
    {
        HKMA.MagicHighlight.markFace(newTarget);
    }

    newTarget.setAttribute(changeType,face);
    
    var backupType = newTarget.getAttribute("backupType");
    var backupValue = newTarget.getAttribute("backupValue");
    
    _this = this; // _this 在匿名函数中能被使用。
    
    if(this.effectDie != "never")
    {
        var effectDieFunction = function anonymous()
        {
           // 如果记忆可用则使用记忆中的外观，否则使用备份中的外观。
           
           if("" != _this.memory)
           {
               if(newTarget.getAttribute(changeType) != _this.memory)
                {
                    newTarget.setAttribute(changeType ,_this.memory);
                }
           }
           else
           {
                newTarget.removeAttribute(changeType);
                newTarget.setAttribute(backupType, backupValue);
           }
        };
        
        newTarget.setAttribute(this.effectDie, effectDieFunction);
    }

    if(this.effectHold != "never")
    {
        var effectHoldFunction = function anonymous()
        {
            if(_this.effectDie != "never")
            {
                if(newTarget.getAttribute(changeType) == _this.memory)
                {
                    newTarget.setAttribute(_this.effectDie, "");
                    newTarget.removeAttribute(changeType);
                    newTarget.setAttribute(backupType,backupValue);
                    
                    if (typeof holdGoOn != "undefined")
                    {
                        if(typeof holdGoOn == "function")
                        {
                            holdGoOn();
                        }
                        else
                        {
                            eval(holdGoOn);
                        }
                    }

                    // 当配额为1时计数器继续运作，当然计数器的使用已无意义。

                    if(_this.holdLimit < _this.holdQuota + 1 || _this.holdQuota == 1)
                    {
                        ++_this.holdLimit;
                    }
                }
                else
                {
                    // 当限制为1时，将旧目标（_this.jump）恢复原貌。
                    
                    if(_this.holdQuota == 1)
                    {
                        if(typeof _this.jump != "undefined")
                        {
                            if(_this.jump != newTarget)
                            {
                                var jumpBackupType = _this.jump.getAttribute("backupType");
                                var jumpBackupValue = _this.jump.getAttribute("backupValue");

                                _this.jump.setAttribute(_this.effectDie, "");
                                _this.jump.removeAttribute(changeType);
                                _this.jump.setAttribute(jumpBackupType,jumpBackupValue);
                                _this.jump = newTarget;
                            }
                        }
                        else
                        {
                            _this.jump = newTarget;
                        }

                    }

                    // 当 holdLimit = "never" 时, NaN 不予理会，
                    // 并且当配额为1时并不需进行点选的限制。

                    if(_this.holdLimit != 0 || _this.holdQuota == 1)
                    {
                        newTarget.setAttribute(_this.effectDie, "");

                        --_this.holdLimit;

                        if (typeof holdGoOn != "undefined")
                        {
                            if(typeof holdGoOn == "function")
                            {
                                holdGoOn();
                            }
                            else
                            {
                                eval(holdGoOn);
                            }
                        }
                    }
                }
            }
            
            newTarget.setAttribute(_this.effectHold, ""); // 注销
        };

        // 本该优先使用 attachEvent 和 detachEvent 的方式,
        // 但会导致事件的叠加,并使到计数器失误。

        newTarget.setAttribute(this.effectHold, effectHoldFunction);
    }
};


