﻿//<using>
//  nui/nui.js
//  nui/prototype.js
//  nui/lang.js
//  nui/quill/processor/processor.js
//  nui/quill/entity/*
//  nui/quill/proxy.js
//</using>

/**
 * The namespace of question processor used in netranking.cn 
 * @namespace NUI.Quill.Processor.Question
 */
NUI.Quill.Processor.Question = {
    getQuestionPrcs : function(vQuestion) {},
    Base : function(vQuestion) {},
    Choice : function(vQuestion) {},
    Matrix : function(vQuestion) {},
    Input : function(vQuestion) {},
    Rank : function(vQuestion) {},
    Sort : function(vQuestion) {},
    ConstSum : function(vQuestion) {},
    Location : function(vQuestion) {},
    MatrixInput : function(vQuestion) {}
};

/**
 * Get a question's processor
 * @param vQuestion {object}. The entity of the survey
 */
NUI.Quill.Processor.Question.getQuestionPrcs = function(vQuestion) {
    if(vQuestion == null) {
        return null;
    }
    var type = vQuestion.type,
        typeValue = null,
        qType = NUI.Quill.Enum.QuestionType;
    NUI.Util.ObjectService.searchObject(qType, function(vName) {
        if(qType[vName].id == type) {
            typeValue = qType[vName].value;
            return true;
        }
        return false;
    });
    if(typeValue == null) {
        return null;
    }
    return NUI.Quill.Processor.Question[typeValue](vQuestion);
};

/**
 * The base class of all kinds of question Processors.
 * @class NUI.Quill.Processor.Question.Base
 * @param vSecret {object} 
 *      vSecret = {
 *          entity : {object},  // NUI.Quill.Entity.*
 *      }
 */
NUI.Quill.Processor.Question.Base = (function() {
    var g_question = NUI.Quill.Entity.Question,
        g_ns = NUI.Quill.Processor.Question,
        g_lang = NUI.Lang;
    
    return function(vSecret) {
        var secret = vSecret || {};
        if(!secret.entity) {
            secret.entity = g_question["Base"]();
        }
        
        NUI.Util.ObjectService.annex(secret, {
            isModified : function() {
                return secret.entity.modified;
            },
            setModified : function() {
                secret.entity.modified = true;
            },
            resetModified : function() {
                secret.entity.modified = false;
            },
            
            /**
             * methods for the options
             */
            /**
             * Count the number of items.Add/remove/update an item.
             */
            itemLength : function(vItemList) {
                if(!vItemList) {
                    return -1;
                }
                return vItemList.length;
            },
            addItem : function(vItemList, vIndex, vItem) {
                if(!vItemList) {
                    return false;
                }
                var retval = vItemList.addAt(vIndex, vItem);
                if(retval) {
                    secret.setModified();
                }
                return retval;
            },
            removeItem : function(vItemList, vIndex) {
                if(!vItemList) {
                    return false;
                }
                var retval = vItemList.removeAt(vIndex);
                if(retval) {
                    secret.setModified();
                }
                return retval;
            },
            updateItem : function(vItemList, vIndex, vItem) {
                if(!vItemList) {
                    return false;
                }
                var retval = vItemList.update(vIndex, vItem);
                if(retval) {
                    secret.setModified();
                }
                return retval;
            },
            
            /**
             * Set other option on or off
             */
            setOtherOption : function(vOptionSet, vHasOtherOption) {
                if(vOptionSet && vOptionSet.hasOtherOption != vHasOtherOption) {
                    vOptionSet.hasOtherOption = vHasOtherOption;
                    secret.setModified();
                }
            },
            
            /**
             * set min and max
             */
            setMin : function(vOptionSet, vMin) {
                if(vOptionSet && g_lang.isNumber(vMin)) {
                    var max = vOptionSet.hasOtherOption ? 
                        (vOptionSet.options.length + 1) : vOptionSet.options.length;
                    if(vMin > max) {
                        vMin = max;
                    }
                    if(vMin > vOptionSet.constrain.max) {
                        vMin = vOptionSet.constrain.max
                    }
                    if(vMin <= 0) {
                        vMin = 0;
                    }
                    if(vMin != vOptionSet.constrain.min) {
                        vOptionSet.constrain.min = vMin;
                        secret.setModified();
                    }
                }
                return vMin;
            },
            setMax : function(vOptionSet, vMax) {
                if(vOptionSet && g_lang.isNumber(vMax)) {
                    var len = vOptionSet.options.length;
                    if(vOptionSet.hasOtherOption) {
                        len += 1;
                    }
                    if(vMax > len) {
                        vMax = len;
                    }
                    if(vMax < vOptionSet.constrain.min) {
                        vMax = vOptionSet.constrain.min
                    }
                    if(vMax <= 0) {
                        vMax = 0;
                    }
                    if(vMax != vOptionSet.constrain.max) {
                        vOptionSet.constrain.max = vMax;
                        secret.setModified();
                    }
                }
                return vMax;
            }
        });
        
        var that = {
            /**
             * Update the caption of the question.
             */
            updateCaption : function(vCaption) {
                if(g_lang.isString(vCaption)) {
                    secret.setModified();
                    secret.entity.caption = vCaption;
                    return true;
                }
                return false;
            },
            
            /**
             * Save question
             * @param vSurveyId {int}. The id of the question's owner survey
             * @param vFunc(vIsSuccess) {boolean}. The function to execute after saving the question
             */
            save : function(vSurveyId, vFunc) {
                if(!secret.isModified()) {
                    vFunc(true);
                } else {
                    NUI.Quill.Proxy.Question.saveQuestion(vSurveyId, secret.entity, function(vIsSuccess) {
                        if(vIsSuccess) {
                            secret.resetModified();
                        }
                        vFunc(vIsSuccess);
                    });
                }
            }
        };
        
        return that;
    };
})();

/**
 * The class of choice question Processor.
 * @class NUI.Quill.Processor.Question.Choice
 * @param vEntity {object}. The entity of the choice question
 */
NUI.Quill.Processor.Question.Choice = (function() {
    var g_lang = NUI.Lang,
        g_ns = NUI.Quill.Processor.Question,
        g_type = NUI.Quill.Enum.QuestionType;
    
    return function(vEntity) {
        if(vEntity == null || !(g_type.CHOICE.id == vEntity.type)) {
            return null;
        }
            
        var secret = {
            entity : vEntity
        };
        var that = new g_ns.Base(secret),
            entity = secret.entity;
            
        NUI.Util.ObjectService.annex(that, {
            /**
             * Count the number of options. Add/remove/update an option.
             */
            optionLength : function() {
                return secret.itemLength(entity.optSet.options);
            },
            addOption : function(vIndex, vOption) {
                return secret.addItem(entity.optSet.options, vIndex, vOption);
            },
            removeOption : function(vIndex) {
                return secret.removeItem(entity.optSet.options, vIndex);
            },
            updateOption : function(vIndex, vOption) {
                return secret.updateItem(entity.optSet.options, vIndex, vOption);
            },
            
            /**
             * set other option
             */
            setOtherOption : function(vHasOtherOption) {
                return secret.setOtherOption(entity.optSet, vHasOtherOption);
            },
            
            /**
             * Set the min and max number of choices that users can choice
             */
            setMin : function(vMin) {
                return secret.setMin(entity.optSet, vMin);
            },
            setMax : function(vMax) {
                return secret.setMax(entity.optSet, vMax);
            },
            
            /**
             * Set style
             */
            setColumn : function(vColumn) {
                if(g_lang.isNumber(vColumn) && entity.style.column != vColumn) {
                    entity.style.column = vColumn;
                    secret.setModified();
                }
            },
            
            /**
             * Set random
             */
            setRandom : function(vIsRandom) {
                if(g_lang.isBoolean(vIsRandom) && entity.style.isRandom != vIsRandom) {
                    entity.style.isRandom = vIsRandom;
                    secret.setModified();
                }
            }
        });
        return that;
    };
})();

/**
 * The class of Matrix question Processor.
 * @class NUI.Quill.Processor.Question.Matrix
 * @param vEntity {object}. The entity of the matrix question
 */
NUI.Quill.Processor.Question.Matrix = (function() {
    var g_lang = NUI.Lang,
        g_ns = NUI.Quill.Processor.Question,
        g_type = NUI.Quill.Enum.QuestionType;
    
    return function(vEntity) {
        if(vEntity == null || !(g_type.MATRIX.id == vEntity.type)) {
            return null;
        }
            
        var secret = {
            entity : vEntity
        };
        var that = new g_ns.Base(secret),
            entity = secret.entity;
            
        NUI.Util.ObjectService.annex(that, {
            /**
             * Add/remove/update row or col option
             */
            addRowOption : function(vIndex, vOption) {
                return secret.addItem(entity.rows.options, vIndex, vOption);
            },
            removeRowOption : function(vIndex) {
                return secret.removeItem(entity.rows.options, vIndex);
            },
            updateRowOption : function(vIndex, vOption) {
                return secret.updateItem(entity.rows.options, vIndex, vOption);
            },
            addColOption : function(vIndex, vOption) {
                return secret.addItem(entity.cols.options, vIndex, vOption);
            },
            removeColOption : function(vIndex) {
                return secret.removeItem(entity.cols.options, vIndex);
            },
            updateColOption : function(vIndex, vOption) {
                return secret.updateItem(entity.cols.options, vIndex, vOption);
            },
            
            /**
             * Add/remove other option
             */
            setRowOtherOption : function(vHasOtherOption) {
                return secret.setOtherOption(entity.rows, vHasOtherOption);
            },
            setColOtherOption : function(vHasOtherOption) {
                return secret.setOtherOption(entity.cols, vHasOtherOption);
            },
            
            /**
             * The following is Quill version 3.0. If you want the version 2.0, uncomment the comments.
             * Set the min and max count of choices that users can choose
             * Attention : Quill 2.0's entity.rows :
             *    options : matrix's rows title
             *    hasOtherOption : indicate whether matrix has an "other" option or not
             *    constrain : limition of every row (in fact, we limit the legal count of chosen option of col)
             * Quill 3.0 change the constrain:
             *    constrain : limition of every col. As a matter of fact, 
             *                we limit the legal count of chosen option of row. 
             */
            setRowMin : function(vMin) {
                return secret.setMin(entity.rows, vMin);
//                if(g_lang.isNumber(vMin)) {
//                    var max = entity.cols.hasOtherOption ? 
//                        (entity.cols.options.length + 1) : entity.cols.options.length;
//                    if(vMin > max) {
//                        vMin = max;
//                    }
//                    if(vMin <= 0) {
//                        vMin = 0;
//                    }
//                    if(vMin != entity.rows.constrain.min) {
//                        entity.rows.constrain.min = vMin;
//                        secret.setModified();
//                    }
//                }
//                return vMin;
            },
            setRowMax : function(vMax) {
                return secret.setMax(entity.rows, vMax);
//                if(g_lang.isNumber(vMax)) {
//                    var len = entity.cols.options.length;
//                    if(entity.cols.hasOtherOption) {
//                        len += 1;
//                    }
//                    if(vMax > len) {
//                        vMax = len;
//                    }
//                    if(vMax <= 0) {
//                        vMax = 0;
//                    }
//                    if(vMax != entity.rows.constrain.max) {
//                        entity.rows.constrain.max = vMax;
//                        secret.setModified();
//                    }
//                }
//                return vMax;
            },
            setColMin : function(vMin) {
                return secret.setMin(entity.cols, vMin);
            },
            setColMax : function(vMax) {
                return secret.setMax(entity.cols, vMax);
            }
        });
        return that;
    };
})();

/**
 * The class of Input question Processor.
 * @class NUI.Quill.Processor.Question.Input
 * @param vEntity {object}. The entity of the Input question
 */
NUI.Quill.Processor.Question.Input = (function() {
    var g_lang = NUI.Lang,
        g_ns = NUI.Quill.Processor.Question,
        g_type = NUI.Quill.Enum.QuestionType,
        g_optType = NUI.Quill.Enum.InputOptionType;
        
    return function(vEntity) {
        if(vEntity == null || !(g_type.INPUT.id == vEntity.type)) {
            return null;
        }
            
        var secret = {
            entity : vEntity
        };
        var m_type = NUI.Widget.Input.TextInputType,
            that = new g_ns.Base(secret),
            entity = secret.entity;
            
        /**
         * Get position in the options
         */
        function _getPosition(vType, vIndex) {
            if(!NUI.Util.ObjectService.hasValue(g_optType, vType)) {
                return -1;
            }
            var mask = secret.entity.optTypeMask,
                len = mask.length,
                count = -1,
                retval = 0;
            for(; retval<len; retval++) {
                if(mask[retval] == vType) {
                    count ++;
                    if(count == vIndex) {
                        break;
                    }
                }
            }
            if(count != vIndex) {
                return -1;
            } else {
                return retval;
            }
        }
        
        /**
         * Check the type of the item
         */
        function _isText(vMaskIndex) {
            return (secret.entity.optTypeMask[vMaskIndex] == g_optType.TEXT);
        }
        function _isInput(vMaskIndex) {
            return (secret.entity.optTypeMask[vMaskIndex] == g_optType.INPUT);
        }
        
        /**
         * Get the items of some type
         */
        function _getItems(vType) { 
            var retval = null;
            switch(vType) {
                case g_optType.TEXT:
                    retval = secret.entity.texts; 
                    break;
                case g_optType.INPUT:
                    retval = secret.entity.inputs; 
                    break;
            }
            return retval;
        }
        
        /**
         * Adjust the options and combine the neighbored Text-options
         */
        function _adjustOptions() {
            var mask = secret.entity.optTypeMask,
                texts = secret.entity.texts,
                inputs = secret.entity.inputs;
            var mIdx = 0, tIdx = 0, iIdx = 0;
            while(mIdx < mask.length) {
                if(_isText(mIdx)){
                    var mNext = mIdx + 1,
                        tNext = tIdx + 1;
                    if(tNext < texts.length && mNext < mask.length && _isText(mNext)) {
                        texts[tIdx] += texts[tNext];
                        texts.removeAt(tNext);
                        mask.removeAt(mNext);
                    } else {
                        mIdx ++;
                        tIdx ++;
                    }
                } else if(_isInput(mIdx)) {
                    mIdx ++;
                    iIdx ++;
                }
            }
        }
        
        NUI.Util.ObjectService.annex(that, {
            optionLength : function() {
                var mask = secret.entity.optTypeMask;
                if(!mask) {
                    return -1;
                }
                return mask.length;
            },
            isText : function(vMaskIndex) {
                return _isText(vMaskIndex);
            },
            isInput : function(vMaskIndex) {
                return _isInput(vMaskIndex);
            },
            
            /**
             * Add/remove/update an option
             */
            addOption : function(vType, vOption) {
                if(!NUI.Util.ObjectService.hasValue(g_optType, vType)) {
                    return false;
                }
                var items = _getItems(vType);
                if(!items) {
                    return false;
                }
                items[items.length] = vOption;
                var mask = secret.entity.optTypeMask;
                mask[mask.length] = vType;
                _adjustOptions();
                secret.setModified();
                return true;
            },
            removeOption : function(vType, vIndex) {
                var items = _getItems(vType),
                    pos = _getPosition(vType, vIndex);
                if(!items || pos < 0) {
                    return false;
                }
                items.removeAt(vIndex);
                secret.entity.optTypeMask.removeAt(pos);
                _adjustOptions();
                secret.setModified();
                return true;
            },
            updateOption : function(vType, vIndex, vNewOption) {
                var items = _getItems(vType);
                if(!items) {
                    return false;
                }
                secret.setModified();
                return items.update(vIndex, vNewOption);
            },
            
            /**
             * Set min and max adn type of input
             */
            setMin : function(vIndex, vMin) {
                var inputs = secret.entity.inputs;
                if(!inputs.isIndexLegal(vIndex) || !g_lang.isNumber(vMin)) {
                    return;
                }
                inputs[vIndex].min = vMin;
                secret.setModified();
            },
            setMax : function(vIndex, vMax) {
                var inputs = secret.entity.inputs;
                if(!inputs.isIndexLegal(vIndex) || !g_lang.isNumber(vMax)) {
                    return;
                }
                inputs[vIndex].max = vMax;
                secret.setModified();
            },
            setType : function(vIndex, vInputTypeId) {
                var inputs = secret.entity.inputs;
                if(!inputs.isIndexLegal(vIndex)) {
                    return;
                }
                var hasType = false;
                NUI.Util.ObjectService.searchObject(m_type, function(vName) {
                    hasType = (m_type[vName].id == vInputTypeId);
                    return hasType;
                });
                if(!hasType) {
                    return;
                }
                inputs[vIndex].type = vInputTypeId;
                secret.setModified();
            }
        });
        return that;
    };
})();

/**
 * The class of Rank question Processor.
 * @class NUI.Quill.Processor.Question.Rank
 * @param vEntity {object}. The entity of the Rank question
 */
NUI.Quill.Processor.Question.Rank = (function() {
    var g_lang = NUI.Lang,
        g_ns = NUI.Quill.Processor.Question,
        g_type = NUI.Quill.Enum.QuestionType;
    
    return function(vEntity) {
        if(vEntity == null || !(g_type.RANK.id == vEntity.type)) {
            return null;
        }
            
        var secret = {
            entity : vEntity
        };
        var that = new g_ns.Base(secret),
            entity = secret.entity;
        
        NUI.Util.ObjectService.annex(that, {
            /**
             * Count the number of options.Add/remove/update an option.
             */
            optionLength : function() {
                return secret.itemLength(entity.options);
            },
            addOption : function(vIndex, vOption) {
                return secret.addItem(entity.options, vIndex, vOption);
            },
            removeOption : function(vIndex) {
                return secret.removeItem(entity.options, vIndex);
            },
            updateOption : function(vIndex, vOption) {
                return secret.updateItem(entity.options, vIndex, vOption);
            },
            
            /**
             * Update option value/type/iconcount
             */
            updateOptionValue : function(vIndex, vValue) {
                if(!g_lang.isString(vValue)) {
                    return false;
                }
                var opts = secret.entity.options;
                if(!opts || !opts.isIndexLegal(vIndex)) {
                    return false;
                }
                var opt = opts[vIndex];
                if(opt == null) {
                    return false;
                }
                opt.value = vValue;
                secret.setModified();
                return true;
            },
            updateOptionType: function(vIndex, vType) {
                if(!NUI.Util.ObjectService.hasValue(NUI.Widget.Input.RankBarType, vType)) {
                    return false;
                }
                var opts = secret.entity.options;
                if(!opts || !opts.isIndexLegal(vIndex)) {
                    return false;
                }
                var opt = opts[vIndex];
                if(opt == null) {
                    return false;
                }
                opt.type = vType;
                secret.setModified();
                return true;
            },
            updateOptionCount : function(vIndex, vCount) {
                if(!g_lang.isNumber(vCount) || !(vCount > 0)) {
                    return false;
                }
                var opts = secret.entity.options;
                if(!opts || !opts.isIndexLegal(vIndex)) {
                    return false;
                }
                var opt = opts[vIndex];
                if(opt == null) {
                    return false;
                }
                opt.count = vCount;
                secret.setModified();
                return true;
            }
        });
        return that;
    };
})();

/**
 * The class of Sort question Processor.
 * @class NUI.Quill.Processor.Question.Sort
 * @param vEntity {object}. The entity of the Sort question
 */
NUI.Quill.Processor.Question.Sort = (function() {
    var g_lang = NUI.Lang,
        g_ns = NUI.Quill.Processor.Question,
        g_type = NUI.Quill.Enum.QuestionType;
    
    return function(vEntity) {
        if(vEntity == null || !(g_type.SORT.id == vEntity.type)) {
            return null;
        }
            
        var secret = {
            entity : vEntity
        };
        var that = new g_ns.Base(secret),
            entity = secret.entity;
            
        NUI.Util.ObjectService.annex(that, {
            /**
             * Count the number of options.Add/remove/update an option.
             */
            optionLength : function() {
                return secret.itemLength(entity.options);
            },
            addOption : function(vIndex, vOption) {
                return secret.addItem(entity.options, vIndex, vOption);
            },
            removeOption : function(vIndex) {
                return secret.removeItem(entity.options, vIndex);
            },
            updateOption : function(vIndex, vOption) {
                return secret.updateItem(entity.options, vIndex, vOption);
            },
            
            /**
             * Set the column number
             */
            setColumn : function(vColumn) {
                if(!g_lang.isNumber(vColumn) || vColumn <= 0) {
                    return false;
                }
                secret.entity.style.column = vColumn;
                secret.setModified();
                return true;
            }
        });
        return that;
    };
})();

/**
 * The class of ConstSum question Processor.
 * @class NUI.Quill.Processor.Question.ConstSum
 * @param vEntity {object}. The entity of the ConstSum question
 */
NUI.Quill.Processor.Question.ConstSum = (function() {
    var g_lang = NUI.Lang,
        g_ns = NUI.Quill.Processor.Question,
        g_type = NUI.Quill.Enum.QuestionType;
    
    return function(vEntity) {
        if(vEntity == null || !(g_type.CONSTSUM.id == vEntity.type)) {
            return null;
        }
            
        var secret = {
            entity : vEntity
        };
        var that = new g_ns.Base(secret),
            entity = secret.entity,
            m_color = NUI.Widget.Input.ConstBarType,
            m_arrange = NUI.Widget.Input.ArrangeType;
        
        NUI.Util.ObjectService.annex(that, {
            /**
             * Count the number of options.Add/remove/update an option.
             */
            optionLength : function() {
                return secret.itemLength(entity.options);
            },
            addOption : function(vIndex, vOption) {
                return secret.addItem(entity.options, vIndex, vOption);
            },
            removeOption : function(vIndex) {
                return secret.removeItem(entity.options, vIndex);
            },
            updateOption : function(vIndex, vOption) {
                return secret.updateItem(entity.options, vIndex, vOption);
            },
            
            /**
             * Set the color of the bar
             */
            setColor : function(vColor) {
                if(!NUI.Util.ObjectService.hasValue(m_color, vColor)) {
                    return false;
                }
                secret.entity.color = vColor;
                secret.setModified();
                return true;
            },
            
            /**
             * Set the arrange of the bar
             */
            setArrange : function(vArrange) {
                if(!NUI.Util.ObjectService.hasValue(m_arrange, vArrange)) {
                    return false;
                }
                secret.entity.arrange = vArrange;
                secret.setModified();
                return true;
            }
        });
        return that;
    };
})();

/**
 * The class of location question Processor.
 * @class NUI.Quill.Processor.Question.Location
 * @param vEntity {object}. The entity of the location question
 */
NUI.Quill.Processor.Question.Location = (function() {
    var g_lang = NUI.Lang,
        g_ns = NUI.Quill.Processor.Question,
        g_type = NUI.Quill.Enum.QuestionType;
    
    return function(vEntity) {
        if(vEntity == null || !(g_type.LOCATION.id == vEntity.type)) {
            return null;
        }
            
        var secret = {
            entity : vEntity
        };
        var that = new g_ns.Base(secret),
            entity = secret.entity;
            
        NUI.Util.ObjectService.annex(that, {
            /**
             * Set the min and max number of choices that users can choice
             */
            setMin : function(vMin) {
                if(g_lang.isNumber(vMin)) {
                    if(vMin <= 1) {
                        vMin = 1;
                    }
                    if(vMin >= entity.constrain.max) {
                        vMin = entity.constrain.max;
                    }
                    if(vMin != entity.constrain.min) {
                        entity.constrain.min = vMin;
                        secret.setModified();
                    }
                }
                return vMin;
            },
            setMax : function(vMax) {
                if(g_lang.isNumber(vMax)) {
                    if(vMax <= 1) {
                        vMax = 1;
                    }
                    if(vMax <= entity.constrain.min) {
                        vMax = entity.constrain.min;
                    }
                    if(vMax != entity.constrain.max) {
                        entity.constrain.max = vMax;
                        secret.setModified();
                    }
                }
                return vMax;
            }
        });
        return that;
    };
})();

/**
 * The class of MatrixInput question Processor.
 * @class NUI.Quill.Processor.Question.MatrixInput
 * @param vEntity {object}. The entity of the matrix question
 */
NUI.Quill.Processor.Question.MatrixInput = (function() {
    var g_lang = NUI.Lang,
        g_ns = NUI.Quill.Processor.Question,
        g_type = NUI.Quill.Enum.QuestionType;
    
    return function(vEntity) {
        if(vEntity == null || !(g_type.MATRIXINPUT.id == vEntity.type)) {
            return null;
        }
            
        var secret = {
            entity : vEntity
        };
        var that = new g_ns.Base(secret),
            entity = secret.entity;
            
        NUI.Util.ObjectService.annex(that, {
            /**
             * Add/remove/update row or col option
             */
            addRowOption : function(vIndex, vOption) {
                return secret.addItem(entity.rows.options, vIndex, vOption);
            },
            removeRowOption : function(vIndex) {
                return secret.removeItem(entity.rows.options, vIndex);
            },
            updateRowOption : function(vIndex, vOption) {
                return secret.updateItem(entity.rows.options, vIndex, vOption);
            },
            addColOption : function(vIndex, vOption) {
                return secret.addItem(entity.cols.options, vIndex, vOption);
            },
            removeColOption : function(vIndex) {
                return secret.removeItem(entity.cols.options, vIndex);
            },
            updateColOption : function(vIndex, vOption) {
                return secret.updateItem(entity.cols.options, vIndex, vOption);
            },
            
            /**
             * Add/remove other option
             */
            setRowOtherOption : function(vHasOtherOption) {
                return secret.setOtherOption(entity.rows, vHasOtherOption);
            },
            setColOtherOption : function(vHasOtherOption) {
                return secret.setOtherOption(entity.cols, vHasOtherOption);
            }
        });
        return that;
    };
})();

