﻿//<using>
//  nui/nui.js
//  nui/prototype.js
//  nui/util.js
//  nui/widget.js
//  nui/quill/entity/*
//  nui/quill/processor/*
//  nui/quill/render/*
//  nui/quill/filler/filler.js
//</using>

/**
 * The question filler used in Quill
 * Copyright 2007, NetRanking.cn
 *
 * @namespace NUI.Quill.Designer.Filler
 */
NUI.Quill.Filler.Question = {
    getQuestionFiller : function(vQuestion, vAnswer) {},
    Base : function(vSecret) {},
    Choice : function(vQuestion, vAnswer) {},
    Matrix : function(vQuestion, vAnswer) {},
    Input : function(vQuestion, vAnswer) {},
    Rank : function(vQuestion, vAnswer) {},
    Sort : function(vQuestion, vAnswer) {},
    ConstSum : function(vQuestion, vAnswer) {},
    Location : function(vQuestion, vAnswer) {},
    MatrixInput : function(vQuestion, vAnswer) {}
};

/**
 * Get the filler of a question
 */
NUI.Quill.Filler.Question.getQuestionFiller = function(vQuestion, vAnswer) {
    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.Filler.Question[typeValue](vQuestion, vAnswer);
};

/**
 * The base class of all kinds of question Filler.
 * @class NUI.Quill.Filler.Question.Base
 * @param vSecret {object}
 *      vSecret = {
 *          id : {string},
 *          question : {object},  // NUI.Quill.Entity.Question.*
 *      }
 */
NUI.Quill.Filler.Question.Base = (function() {
    var g_widget = NUI.Widget,
        g_enum = NUI.Quill.Enum,
        g_entity = NUI.Quill.Entity,
        g_render = NUI.Quill.Render.Question,
        g_prcs = NUI.Quill.Processor.Answer,
        g_dom = NUI.Util.DomService;
        
    return function(vSecret) {
        var m_secret = vSecret || {},
            m_question = m_secret.question || g_entity.Question["Base"]();
            
        NUI.Util.ObjectService.annex(m_secret, {
            question : m_question,
            render : g_render.getQuestionRender(m_question, m_secret.answer, m_secret.attribute),
            prcs : g_prcs.getAnswerPrcs(m_question, m_secret.answer)
        });
        
        var that = g_widget.Base(m_secret),
            m_id = m_secret.id;
        
        /**
         * Structure : 
         *  m_node
         */
        var m_node = (function() {
                var retval = g_dom.createNode("div");
                m_secret.render.attachTo(retval);
                return retval;
            })();
        
        NUI.Util.ObjectService.annex(that, {
            nodeEntity : m_node,
            
            check : function() {
                return m_secret.prcs.check();
            },
            
            /**
             * Save question
             * @param vSurveyId {int}
             * @param vFunc(vIsSuccess) {function}. The function to execute after saving the answer
             */
            save : function(vSurveyId, vFunc) {
                m_secret.prcs.save(vSurveyId, vFunc);
            },
            
            getAnswer : function() {
                if(m_secret.prcs == null) {
                    return null;
                }
                return m_secret.prcs.getAnswer();
            }
        });
        
        return that;
    };
})();

/**
 * Choice question
 * @class NUI.Quill.Filler.Question.Choice
 * @param vQuestion {object}. NUI.Quill.Entity.Question.*
 * @param vAnswer {object}. NUI.Quill.Entity.Answer.*
 */
NUI.Quill.Filler.Question.Choice = (function(){
    var g_enum = NUI.Quill.Enum,
        g_ns = NUI.Quill.Filler.Question;
    
    return function(vQuestion, vAnswer) {
        if(vQuestion == null || !(g_enum.QuestionType.CHOICE.id == vQuestion.type)) {
            return null;
        }
            
        var m_secret = {
            answer : vAnswer,
            question : vQuestion,
            attribute : {
                openRandom : true
            }
        };
        var that = new g_ns.Base(m_secret),
            m_render = m_secret.render,
            m_prcs = m_secret.prcs;
            
        // set init answer
        if(vAnswer != null && g_enum.QuestionType.CHOICE.id == vAnswer.type) {
            m_prcs.setAnswer(vAnswer.answers);
            m_prcs.setOther(vAnswer.other);
        }
        
        m_render.setOptEventHandler(function(vOptIndexes, vOtherValue) {
            m_prcs.setAnswer(vOptIndexes);
            m_prcs.setOther(vOtherValue);
        });
            
        NUI.Util.ObjectService.annex(that, {});
        return that;
    };
})();

/**
 * Matrix question
 * @class NUI.Quill.Filler.Question.Matrix
 * @param vQuestion {object}, NUI.Quill.Entity.Question.*
 * @param vAnswer {object}. NUI.Quill.Entity.Answer.*
 */
NUI.Quill.Filler.Question.Matrix = (function(){
    var g_enum = NUI.Quill.Enum,
        g_ns = NUI.Quill.Filler.Question;
    
    return function(vQuestion, vAnswer) {
        if(vQuestion == null || !(g_enum.QuestionType.MATRIX.id == vQuestion.type)) {
            return null;
        }
            
        var m_secret = {
            answer : vAnswer,
            question : vQuestion
        };
        var that = new g_ns.Base(m_secret),
            m_render = m_secret.render,
            m_prcs = m_secret.prcs;
        
        // set init answer
        if(vAnswer != null && g_enum.QuestionType.MATRIX.id == vAnswer.type) {
            m_prcs.setAnswer(vAnswer.answers);
            m_prcs.setRowOther(vAnswer.rowOther);
            m_prcs.setColOther(vAnswer.colOther);
        }
        
        m_render.setOptEventHandler(function(vOptIndexes, vRotherValue, vCotherValue) {
            m_prcs.setAnswer(vOptIndexes);
            m_prcs.setRowOther(vRotherValue);
            m_prcs.setColOther(vCotherValue);
        });
            
        NUI.Util.ObjectService.annex(that, {});
        return that;
    };
})();

/**
 * Input question
 * @class NUI.Quill.Filler.Question.Input
 * @param vQuestion {object}, NUI.Quill.Entity.Question.*
 * @param vAnswer {object}. NUI.Quill.Entity.Answer.*
 */
NUI.Quill.Filler.Question.Input = (function(){
    var g_enum = NUI.Quill.Enum,
        g_ns = NUI.Quill.Filler.Question;
    
    return function(vQuestion, vAnswer) {
        if(vQuestion == null || !(g_enum.QuestionType.INPUT.id == vQuestion.type)) {
            return null;
        }
            
        var m_secret = {
            answer : vAnswer,
            question : vQuestion
        };
        var that = new g_ns.Base(m_secret),
            m_question = m_secret.question,
            m_render = m_secret.render,
            m_prcs = m_secret.prcs;
            
        // set init answer
        if(vAnswer != null && g_enum.QuestionType.INPUT.id == vAnswer.type) {
            m_prcs.setAnswer(vAnswer.answers);
        }
        
        var m_inputs = m_question.inputs,
            len = m_inputs.length;
        for(var i=0; i<len; i++) {
            m_render.setInputBlurEventHandler(i, (function(vIndex) {
                return function(vValue) {
                    m_prcs.updateAnswer(vIndex, vValue);
                };
            })(i));
        }
        
        NUI.Util.ObjectService.annex(that, {});
        return that;
    };
})();

/**
 * Rank question
 * @class NUI.Quill.Filler.Question.Rank
 * @param vQuestion {object}, NUI.Quill.Entity.Question.*
 * @param vAnswer {object}. NUI.Quill.Entity.Answer.*
 */
NUI.Quill.Filler.Question.Rank = (function(){
    var g_enum = NUI.Quill.Enum,
        g_ns = NUI.Quill.Filler.Question;
    
    return function(vQuestion, vAnswer) {
        if(vQuestion == null || !(g_enum.QuestionType.RANK.id == vQuestion.type)) {
            return null;
        }
            
        var m_secret = {
            answer : vAnswer,
            question : vQuestion
        };
        var that = new g_ns.Base(m_secret),
            m_question = m_secret.question,
            m_render = m_secret.render,
            m_prcs = m_secret.prcs;
            
        // set init answer
        if(vAnswer != null && g_enum.QuestionType.RANK.id == vAnswer.type) {
            m_prcs.setAnswer(vAnswer.answers);
        }
        
        var m_options = m_question.options,
            len = m_options.length;
        for(var i=0; i<len; i++) {
            m_render.setOptEventHandler(i, (function(vIndex) {
                return function(vValue) {
                    m_prcs.updateAnswer(vIndex, vValue);
                };
            })(i));
        }
        
        NUI.Util.ObjectService.annex(that, {});
        return that;
    };
})();

/**
 * Sort question
 * @class NUI.Quill.Filler.Question.Sort
 * @param vQuestion {object}, NUI.Quill.Entity.Question.*
 * @param vAnswer {object}. NUI.Quill.Entity.Answer.*
 */
NUI.Quill.Filler.Question.Sort = (function(){
    var g_enum = NUI.Quill.Enum,
        g_ns = NUI.Quill.Filler.Question;
    
    return function(vQuestion, vAnswer) {
        if(vQuestion == null || !(g_enum.QuestionType.SORT.id == vQuestion.type)) {
            return null;
        }
            
        var m_secret = {
            answer : vAnswer,
            question : vQuestion
        };
        var that = new g_ns.Base(m_secret),
            m_render = m_secret.render,
            m_prcs = m_secret.prcs;
        
        // set init answer
        if(vAnswer != null && g_enum.QuestionType.SORT.id == vAnswer.type) {
            m_prcs.setAnswer(vAnswer.answers);
        }
        
        m_render.setOptEventHandler(function(vOptIndexes, vOtherValue) {
            m_prcs.setAnswer(vOptIndexes);
        });
        
        NUI.Util.ObjectService.annex(that, {});
        return that;
    };
})();

/**
 * ConstSum question
 * @class NUI.Quill.Filler.Question.ConstSum
 * @param vQuestion {object}, NUI.Quill.Entity.Question.*
 * @param vAnswer {object}. NUI.Quill.Entity.Answer.*
 */
NUI.Quill.Filler.Question.ConstSum = (function(){
    var g_enum = NUI.Quill.Enum,
        g_ns = NUI.Quill.Filler.Question;
    
    return function(vQuestion, vAnswer) {
        if(vQuestion == null || !(g_enum.QuestionType.CONSTSUM.id == vQuestion.type)) {
            return null;
        }
            
        var m_secret = {
            answer : vAnswer,
            question : vQuestion
        };
        var that = new g_ns.Base(m_secret),
            m_render = m_secret.render,
            m_prcs = m_secret.prcs;
        
        // set init answer
        if(vAnswer != null && g_enum.QuestionType.CONSTSUM.id == vAnswer.type) {
            m_prcs.setAnswer(vAnswer.answers);
        }
        
        m_render.setOptEventHandler(function(vResults) {
            m_prcs.setAnswer(vResults);
        });
        
        NUI.Util.ObjectService.annex(that, {});
        return that;
    };
})();

/**
 * Location question
 * @class NUI.Quill.Filler.Question.Location
 * @param vQuestion {object}. NUI.Quill.Entity.Question.*
 * @param vAnswer {object}. NUI.Quill.Entity.Answer.*
 */
NUI.Quill.Filler.Question.Location = (function(){
    var g_enum = NUI.Quill.Enum,
        g_ns = NUI.Quill.Filler.Question;
    
    return function(vQuestion, vAnswer) {
        if(vQuestion == null || !(g_enum.QuestionType.LOCATION.id == vQuestion.type)) {
            return null;
        }
            
        var m_secret = {
            answer : vAnswer,
            question : vQuestion
        };
        var that = new g_ns.Base(m_secret),
            m_render = m_secret.render,
            m_prcs = m_secret.prcs;
            
        // set init answer
        if(vAnswer != null && g_enum.QuestionType.LOCATION.id == vAnswer.type) {
            m_prcs.setAnswer(vAnswer.answers);
        }
        
        m_render.setOptEventHandler(function(vCountry, vProvince, vCity) {
            m_prcs.setAnswer([{
                country : vCountry.id,
                province : vProvince.id,
                city : vCity.id
            }]);
        });
            
        NUI.Util.ObjectService.annex(that, {});
        return that;
    };
})();

/**
 * MatrixInput question
 * @class NUI.Quill.Filler.Question.MatrixInput
 * @param vQuestion {object}, NUI.Quill.Entity.Question.*
 * @param vAnswer {object}. NUI.Quill.Entity.Answer.*
 */
NUI.Quill.Filler.Question.MatrixInput = (function(){
    var g_enum = NUI.Quill.Enum,
        g_ns = NUI.Quill.Filler.Question;
    
    return function(vQuestion, vAnswer) {
        if(vQuestion == null || !(g_enum.QuestionType.MATRIXINPUT.id == vQuestion.type)) {
            return null;
        }
            
        var m_secret = {
            answer : vAnswer,
            question : vQuestion
        };
        var that = new g_ns.Base(m_secret),
            m_render = m_secret.render,
            m_prcs = m_secret.prcs;
        
        // set init answer
        if(vAnswer != null && g_enum.QuestionType.MATRIXINPUT.id == vAnswer.type) {
            m_prcs.setAnswer(vAnswer.answers);
            m_prcs.setRowOther(vAnswer.rowOther);
            m_prcs.setColOther(vAnswer.colOther);
        }
        
        m_render.setOptEventHandler(function(vOptValues, vRotherValue, vCotherValue) {
            m_prcs.setAnswer(vOptValues);
            m_prcs.setRowOther(vRotherValue);
            m_prcs.setColOther(vCotherValue);
        });
            
        NUI.Util.ObjectService.annex(that, {});
        return that;
    };
})();

