﻿// © Copyright Strategy Builders Inc. 2000-2009. All rights reserved.
//   
// The entire contents of this file is protected by International and
// U.S.Copyright Laws. Unauthorized reproduction, distribution, 
// redistribution and reverse engineering of any or all portion of the code 
// contained in this file is strictly prohibited and may
// result in severe civil and criminal penalties and will be
// prosecuted to the maximum extent possible under the law.
//  
// RESTRICTIONS 
//  
// THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES  
// ARE CONFIDENTIAL AND PROPRIETARY TRADE  
// SECRETS OF Strategy Builders Inc. 
//  
// THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED
// FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE  
// COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE 
// AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT  
// AND PERMISSION FROM Strategy Builders Inc. 
//  
// CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON 
// ADDITIONAL RESTRICTIONS. 
//  


function Control(id) {
    this._id = id;
    this._parent = null;
    this._html = null;
    this._template = null;
    this._loadingTemplate = 'Loading ...';
    this._isLoading = false;
    this._attributes = {}; //new Array();
//    this._InnerHTMLControlEvents = new Array();
//    this._InnerHTMLControlIds = new Array();
    this._eventHandlers = new Array();
    this._registerEventExpressions = new Array();
    this._updateFieldAttributeExpressions = new Array();
    this._validateFieldExpressions = new Array();
    this._htmlControlIncreament = 0;

    this._lastSwitchResult = null;
    this._keepOutputing = true;
    this._caseMatchedSwitch = false;
}

Control.prototype.isLoading = function () {
    return this._isLoading;
}

Control.prototype.LoadingComplete = function () {
    this._isLoading = false;
}

Control.prototype.StartLoading = function () {
    this._isLoading = true;
}

Control.prototype.getHTML = function () {
    var template = '';
    if (this._isLoading) template = this._loadingTemplate;
    else template = this._template;

    //        if (this.getParent() == null) alert(this.getId() + '\'s parent is null');

    if (template == '') return '';

    var nodata = true;
    var myJSONText = JSON.stringify(this._attributes);
    //    alert('1:' + myJSONText);

    //    for (var i in this._attributes) {
    //        alert(i);
    //    alert('2:' + template);
    //    alert(document.getElementById(template).innerHTML);
    template = tmpl(template, this._attributes);
    //        alert('3:' + template);
    //        nodata = false;
    //    }

    //    if (nodata) {
    //        alert(template);
    //        template = tmpl(template)({});
    //        alert(template);
    //    }

    this._htmlControlIncreament = 0;

    var expressionStartPos = -1;
    var expressionEndPos = -1;
    do {
        expressionStartPos = template.indexOf('%%', expressionEndPos + 1);

        if (expressionStartPos > -1) {
            expressionEndPos = template.indexOf('%%', expressionStartPos + 1);
            var expressionName = template.substring(expressionStartPos + 2, expressionEndPos);

            var wasOutputing = this._keepOutputing;
            expressionValue = this.evaluateExpression(expressionName);
            if (wasOutputing && !this._keepOutputing) {
                expressionValue = '<!--' + expressionValue
            }
            if (!wasOutputing && this._keepOutputing) {
                expressionValue = '-->' + expressionValue
            }

            //$get('txtErrorBox').value += 'expressionName->' + expressionName + '\n';
            //$get('txtErrorBox').value += 'expressionValue->' + expressionValue + '\n\n\n';
            //$get('txtErrorBox').value += 'template->' + template + '\n\n\n';

            // Very important
            // if first line is uncommented then product list works fine
            // if second line is uncommented then switch case works fine
            //template = template.split('%%' + expressionName + '%%').join(expressionValue);
            template = template.replace('%%' + expressionName + '%%', expressionValue);

            //$get('txtErrorBox').value += 'template->' + template + '\n\n\n';

            var expressionValueLength = 0;
            if (expressionValue != null && expressionValue != 'undefined') {
                expressionValueLength = expressionValue.length;
            }
            expressionEndPos = expressionEndPos - expressionName.length - 2 + expressionValueLength;

        }

    } while (expressionStartPos > -1);

    this._html = template;
    return this._html;
}

Control.prototype.getRegisterEventExpressions = function() {
    return this._registerEventExpressions;
}

Control.prototype.getUpdateFieldAttributeExpressions = function() {
    return this._updateFieldAttributeExpressions;
}

Control.prototype.getValidateFieldExpressions = function() {
    return this._validateFieldExpressions;
}

Control.prototype.getEventHandlers = function() {
    return this._eventHandlers;
}

Control.prototype.addEventHandler = function(eventName, eventHandler) {
    this._eventHandlers[eventName] = eventHandler;
}

Control.prototype.getTemplate = function () {
    return this._template;
}

Control.prototype.getLoadingTemplate = function () {
    return this._loadingTemplate;
}

Control.prototype.setTemplate = function (templateText) {
    this._template = templateText;
}

Control.prototype.setLoadingTemplate = function (templateText) {
    this._loadingTemplate = templateText;
}

Control.prototype.getId = function () {
    return this._id;
}

Control.prototype.getParent = function() {
    return this._parent;
}

Control.prototype.setParent = function(parent) {
    this._parent = parent;
}

Control.prototype.setAttribute = function(name, value) {
    //this._attributes[name] = value;
    eval('this._attributes.' + name + '= value');
}

Control.prototype.getAttribute = function(name) {
//return this._attributes[name];
    return eval('this._attributes.' + name);
}

Control.prototype.getAttributeCount = function() {
    //    return this._attributes.length();
    var cnt = 0;
    for (var i in this._attributes) {
        cnt++;
    }
    return cnt;
}

Control.prototype.RegisterEvents = function() {
////    for (var ControlEventName in this._InnerHTMLControlEvents) {
//        var exp = '$get(\'' + this._InnerHTMLControlIds[ControlEventName] + '\').' + this._InnerHTMLControlEvents[ControlEventName] + ' = this.' + ControlEventName + '_EventHandler';
//        this._registerEventExpressions[ControlEventName] = exp;
//    }
}

Control.prototype.evaluateExpression = function(expression) {
    var attributeName = '';
    var attributeValue = '';

    expression = this.trimAll(expression);

    //var re = new RegExp('[ *+/-]');
    var re = new RegExp('[ *+/-]');
    var expressionToSplit = expression;
    var expressionValue = expression;
    expressionToSplit = expressionToSplit.split('(').join(' ');
    expressionToSplit = expressionToSplit.split(')').join(' ');
    expressionToSplit = expressionToSplit.split('=').join(' ');
    expressionToSplit = expressionToSplit.split(';').join(' ');
    expressionToSplit = expressionToSplit.split('%').join(' ');
    var arrOfAttributeName = expressionToSplit.split(re);

    var firstWord = '';
    if (arrOfAttributeName[0] == " " || arrOfAttributeName[0] == "") {
        firstWord = arrOfAttributeName[1];
        arrOfAttributeName.shift();
    }
    else firstWord = arrOfAttributeName[0];
    //    $get('txtErrorBox').value += 'firstWord->' + firstWord + '\n';

    //$get('txtErrorBox').value += expression + '\n';
    //$get('txtErrorBox').value += firstWord + '\n';


    switch (firstWord) {
        case 'event':

            var completeControlName = '';
            var currentControl = this;
            do {
                completeControlName = currentControl.getId() + '_' + completeControlName;
                currentControl = currentControl.getParent();
            } while (currentControl != null);

            var ControlId = completeControlName + this._htmlControlIncreament;
            this._htmlControlIncreament = this._htmlControlIncreament + 1;
            expressionValue = ' id="' + ControlId + '" ';

            var cntrRegisterEvents = 0;
            var cntrUpdateFields = 0;
            //$get('txtErrorBox').value += arrOfAttributeName.length + '\n';
            for (var i = 1; i < arrOfAttributeName.length; i += 2) {
                //$get('txtErrorBox').value += arrOfAttributeName[i] + '\n';
                //$get('txtErrorBox').value += arrOfAttributeName[i + 1] + '\n\n';
                var exp;
                var ControlEventName = arrOfAttributeName[i + 1];
                var JavascriptEventName = arrOfAttributeName[i];
                switch (JavascriptEventName) {
                    case 'UpdateField':
                        exp = this.getAttributeExpression(ControlEventName) + ' = ' + '$get(\'' + ControlId + '\').' + 'value;';
                        this._updateFieldAttributeExpressions[ControlId + '_' + cntrUpdateFields] = exp;
                        cntrUpdateFields = cntrUpdateFields + 1;
                        //alert(exp);
                        break;
                    case 'ValidateField':
                        exp = ' var myRegExp = /' + ControlEventName + '/i; var result = myRegExp.test(' + '$get(\'' + ControlId + '\').' + 'value); if(!result) { ' + '$get(\'' + ControlId + '\').' + 'value' + ' = "<<Invalid value>>"; ' + '$get(\'' + ControlId + '\').' + 'style.backgroundColor="#FFFF66";' + '$get(\'' + ControlId + '\').' + 'focus();' + '$get(\'' + ControlId + '\').' + 'select();' + '} result';
                        this._validateFieldExpressions[ControlId + '_' + cntrUpdateFields] = exp;
                        cntrUpdateFields = cntrUpdateFields + 1;
                        break;
                    default:
                        exp = '$get(\'' + ControlId + '\').' + JavascriptEventName + ' = this.' + ControlEventName + '_EventHandler';
                        this._registerEventExpressions[ControlId + '_' + cntrRegisterEvents] = exp;
                        cntrRegisterEvents = cntrRegisterEvents + 1;
                        //$get('txtErrorBox').value += ControlId + '_' + cntrRegisterEvents + '\n';
                        //$get('txtErrorBox').value += exp + '\n';
                        break;
                }
            }
            break;
        case 'switch':
            for (var j = 1; j < arrOfAttributeName.length; j += 2) {
                attributeName = arrOfAttributeName[j];

                attributeValue = this.evaluateAttribute(attributeName);
                if (attributeValue == null) {
                    attributeValue = 'null';
                }
                if (attributeValue == 'undefined') {
                    attributeValue = 'undefined';
                }
                if (isNaN(attributeValue)) {
                    attributeValue = '\'' + attributeValue + '\'';
                }
                if (attributeValue == '') {
                    attributeValue = '\'\'';
                }

                expressionValue = expressionValue.split(attributeName).join(attributeValue);
                //                alert(expressionValue);
            }

            try {
                expressionValue = expressionValue.split('switch').join('');
                this._lastSwitchResult = eval(expressionValue);
                expressionValue = '';
                this._keepOutputing = false;
            }
            catch (error) {
                //throw new Error('Error evaluationg expression="' + expression + '" value=' + expressionValue + '; ' + error.message);
            }
            break;
        case 'case':

            for (var k = 1; k < arrOfAttributeName.length; k += 2) {
                attributeName = arrOfAttributeName[k];

                attributeValue = this.evaluateAttribute(attributeName);

                expressionValue = expressionValue.split(attributeName).join(attributeValue);

            }

            try {
                var caseExpressionValue;
                expressionValue = expressionValue.split('case').join('');
                caseExpressionValue = eval(expressionValue);
                //                $get('txtErrorBox').value += this._lastSwitchResult + ' == ' + caseExpressionValue + '\n';

                if (this._lastSwitchResult == caseExpressionValue) {
                    this._keepOutputing = true;
                    this._caseMatchedSwitch = true;
                } else {
                    this._keepOutputing = false;
                    this._caseMatchedSwitch = false;
                }
                //                $get('txtErrorBox').value += 'case: case matched?=' + this._caseMatchedSwitch + ';  keepOutputting=' + this._keepOutputing + '\n';
                expressionValue = '';
            }
            catch (error) {
                //throw new Error('Error evaluationg expression="' + expression + '" value=' + expressionValue + '; ' + error.message);
            }
            break;
        case 'default':
            if (this._caseMatchedSwitch) {
                this._keepOutputing = false;
            } else {
                this._keepOutputing = true;
            }
            //$get('txtErrorBox').value += 'default: case matched?=' + this._caseMatchedSwitch + ';  keepOutputting=' + this._keepOutputing + '\n';
            expressionValue = '';
            break;
        case 'end':

            if (arrOfAttributeName[1] == 'switch') {
                this._keepOutputing = true;
                this._lastSwitchResult = null;
                this._caseMatchedSwitch = false;
            }
            //$get('txtErrorBox').value += 'END: case matched?=' + this._caseMatchedSwitch + ';  keepOutputting=' + this._keepOutputing + '\n';

            expressionValue = '';
            break;
        default:
            attributeName = '';
            attributeValue = '';
            for (i in arrOfAttributeName) {
                attributeName = arrOfAttributeName[i];
                attributeValue = this.evaluateAttribute(attributeName);

                if (attributeValue == '') {
                    expressionValue = expressionValue.split(attributeName).join(attributeValue);
                    //expressionValue = this.ReplaceAll(expressionValue, attributeName, '');
                }
                else {
                    expressionValue = expressionValue.split(attributeName).join(attributeValue);
                }
            }
            //alert(expressionValue);
            try {
                //if ((arrOfAttributeName.length > 1) || expressionValue.length > attributeValue.length) {
                if (expressionValue != '') {
                    expressionValue = eval(expressionValue);
                }
            }
            catch (error) {
                //throw new Error('Error evaluationg expression="' + expression + '" value=' + expressionValue + '; ' + error.message);
            }
    }
    return expressionValue;
}

Control.prototype.ReplaceAll = function(text, strA, strB) {
    while (text.indexOf(strA) != -1) {
        text = text.replace(strA, strB);
    }
    return text;
}

Control.prototype.trimAll = function(sString) {
    while (sString.substring(0, 1) == ' ') {
        sString = sString.substring(1, sString.length);
    }
    while (sString.substring(sString.length - 1, sString.length) == ' ') {
        sString = sString.substring(0, sString.length - 1);
    }
    return sString;
} 

Control.prototype.evaluateAttribute = function(attributeName) {
    var dotPos = attributeName.indexOf('.', 0);
    var attributeValue;

    if (dotPos > 0) {
        var expressionObjectName = attributeName.substring(0, dotPos);
        var expressionRemainingName = attributeName.slice(dotPos + 1);

        var arrayIndexString = '';
        var squareBracketOpenPos = expressionObjectName.indexOf('[', 0);
        if (squareBracketOpenPos > 0) {
            arrayIndexString = expressionObjectName.slice(squareBracketOpenPos);
            expressionObjectName = expressionObjectName.substring(0, squareBracketOpenPos);
            var arrayIndexStringContent = this.ReplaceAll(arrayIndexString, '[', '');
            arrayIndexStringContent = this.ReplaceAll(arrayIndexStringContent, ']', '');
            arrayIndexStringContent = this.ReplaceAll(arrayIndexStringContent, ' ', '');
            arrayIndexStringContent = this.evaluateAttribute(arrayIndexStringContent);
            arrayIndexString = '[' + arrayIndexStringContent + ']';
        }

        var foundAttribute = null;
        var currentControl = this;
        do {
            foundAttribute = currentControl.getAttribute(expressionObjectName);
            if (foundAttribute != 'undefined' && foundAttribute != null) {
                break;
            }
            currentControl = currentControl.getParent();
        } while (currentControl != null);

//        $get('txtErrorBox').value += 'this._attributes[' + expressionObjectName + ']' + arrayIndexString + '.' + expressionRemainingName + '\n';

        //attributeValue = eval('this._attributes[expressionObjectName]' + arrayIndexString + '.' + expressionRemainingName);
        attributeValue = eval('foundAttribute' + arrayIndexString + '.' + expressionRemainingName);
        if (attributeValue == null) {
            //throw new Error('Attribute ' + attributeName + ' not found in attributes.');
            //attributeValue = expressionObjectName + '.' + expressionRemainingName;
            attributeValue = '';
        }
        if (attributeValue == 'undefined') {
            //throw new Error('Attribute ' + attributeName + ' not found in attributes.');
            attributeValue = expressionObjectName + '.' + expressionRemainingName + ' undefined';
        }
    }
    else {
        ///attributeValue = this._attributes[attributeName];
        attributeValue = this.getAttribute(attributeName);
        if (attributeValue == null) {
            //throw new Error('Attribute ' + attributeName + ' not found in attributes.');
            //attributeValue = '';
            attributeValue = attributeName;
        }
        if (attributeValue == 'undefined') {
            //throw new Error('Attribute ' + attributeName + ' not found in attributes.');
            attributeValue = attributeName + ' undefined';
        }
    }
    return attributeValue;
}

Control.prototype.callEventHandler = function(eventHandlerName) {
    var eventHandler = this.getEventHandlers()[eventHandlerName];
    if (eventHandler == null) {
        throw new Error('no event handler implemented with name ' + eventHandlerName);
    }
    else {
        eventHandler(this);
    }
}

Control.prototype.getAttributeExpression = function(attributeName) {
    var dotPos = attributeName.indexOf('.', 0);
    var attributeValue;

    if (dotPos > 0) {
        var expressionObjectName = attributeName.substring(0, dotPos);
        var expressionRemainingName = attributeName.slice(dotPos + 1);
        ///attributeValue = 'this._attributes[\'' + expressionObjectName + '\'].' + expressionRemainingName;
        attributeValue = 'this._attributes.' + expressionObjectName + '.' + expressionRemainingName;
    }
    else {
        ///attributeValue = 'this._attributes[\'' + attributeName + '\']';
        attributeValue = 'this._attributes.' + attributeName + '';
    }
    return attributeValue;
}

