﻿/// <reference path="jquery-1.3.2.js"/>
/// <reference path="MaskedInput.js"/>
/// <reference path="ParseTemplate.js"/>

Array.prototype.first = function(selector) {
    var value;
    for (var i = 0; i < this.length; i++) {
        if (selector(this[i])) {
            value = this[i];
            break;
        }
    }
    return value;
}

$.aspJsonPost = function(url, data, success, async) {
    return $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        url: url,
        data: data,
        dataType: "json",
        success: success,
        async: async
    });
}




function DMiFormEngine(target, properties) {

    var engine = this;
    var fields;
    var offerId;
    var formId;
    var laprotocolKey;

    this.hijackValidation = function(serverControl) {
        if (Page_ClientValidate) {
            var old = ModifiedPage_ClientValidate ? Page_ClientValidate : Page_ClientValidate;
            Page_ClientValidate = function(validationGroup) {
                if (validationGroup == '' || serverControl.validationgroup == validationGroup) {
                    serverControl.invalid = !engine.validateForm();
                }

                old(validationGroup);
            }
        }
    }

    this.getForm = function() {
        if (properties.form) {
            this.buildForm(properties.form);
        } else if (properties.offerId) {
            $.aspJsonPost(properties.serviceUrl + '/GetByOfferID', '{ offerID: ' + properties.offerId + '}', function(msg) { engine.buildForm(msg.d); }, true);
        } else if (properties.laprotocolKey) {
            $.aspJsonPost(properties.serviceUrl + '/GetByKey', "{ laProtocolKey: '" + properties.laprotocolKey + "'}", function(msg) { engine.buildForm(msg.d); }, true);
        } else {
            $.aspJsonPost(properties.serviceUrl + '/GetByID', '{ formID:' + properties.formId + '}', function(msg) { engine.buildForm(msg.d); }, true);
        }

        $(function() {
            if (properties.submitButton) {
                properties.submitButton.click(function() {
                    engine.submitForm();
                });
            } else if (properties.submitButtonId && properties.submitButtonId != '') {
                var button = $('#' + properties.submitButtonId);
                if (properties.submitButtonMode == 'asp') {
                    var domButton = button.get(0);
                    var existingHandler = domButton.onclick;
                    domButton.onclick = null;
                    button.click(function() {
                        if (engine.validateForm()) {
                            target.append($('<input type="hidden" name="Form' + formId + '_Enabled" value="True"/>'));
                            if (existingHandler) {
                                existingHandler();
                            }
                            return true;
                        }
                        return false;
                    })
                } else {
                    button.click(function() { engine.submitForm(); });
                }
            }
        });


        target.submitForm = this.submitForm;
    }


    this.buildForm = function(jsonForm) {
        fields = new Array();

        if (jsonForm.LAProtocolKey && jsonForm.LAProtocolKey != '') {
            laprotocolKey = jsonForm.LAProtocolKey;
        } else {
            offerId = jsonForm.OfferID;
            formId = jsonForm.FormID;
        }

        var jsonFields = jsonForm.Fields;

        var container = target.clone(true);

        for (var i = 0; i < jsonFields.length; i++) {
            var definition = jsonFields[i];
            var control = this.buildControl(definition);
            if (control) {
                container.append(control);
            }
        }

        target.replaceWith(container);
    }

    this.validateForm = function() {
        var valuesString = this.getValues();
        var result;
        var data = laprotocolKey ? "{ LAprotocolKey: '" + laprotocolKey + ', fields: ' + valuesString + '}' : '{ formID: ' + formId + ', fields: ' + valuesString + '}';
        $.aspJsonPost(properties.serviceUrl + '/Validate', data, function(msg) { result = engine.processValidationErrors(msg.d.Errors); }, false);
        return result;
    }


    this.submitForm = function() {
        var valid = this.validateForm();

        if (valid) {
            var submissionUrl = properties.submissionUrl;
            var preSubmitFunction = properties.preSubmitFunction;
            if (preSubmitFunction) {
                preSubmitFunction();
            }

            var valuesString = this.getValues();
            var data = laprotocolKey ? "{ LAprotocolKey: '" + laprotocolKey + ', fields: ' + valuesString + '}' : '{ formID: ' + formId + ', fields: ' + valuesString + '}';
            $.aspJsonPost(submissionUrl, data, function(msg) { engine.postSubmit(msg.d); }, true);
        }
    }

    this.updateForm = function(fieldName) {
        var valuesString = this.getValues();
        var data = !laprotocolKey ? '{ formID: ' + formId + ', fields: ' + valuesString + ", changedField: '" + fieldName + "'}" : '{ LAProtocolKey: ' + laprotocolKey + ', fields: ' + valuesString + ", changedField: '" + fieldName + "'}";
        $.aspJsonPost(properties.serviceUrl + '/Update', data, function(msg) {
            engine.configureControls(msg.d);
            engine.processValidationErrors(msg.d.Errors);
        }, true);
    }

    this.buildControl = function(definition) {
        var element;
        switch (definition.ControlType) {
            case 'TextBox':
                if (definition.Properties['MultiLine'] === "True") {
                    element = $('<textarea></textarea>');
                    if (definition.Properties['Rows'] > 0) {
                        element.attr("rows", definition.Properties['Rows']);
                    }
                }
                else {
                    element = $('<input type="text"></input>');
                }
                break;
            case 'DropDownListField':
                element = $('<select></select>');
                this.populateSelectList(element, definition.Options);
                break;
            case 'PhoneField':
                element = $('<input type="text"></input>');
                element.mask('(999) 999-9999', { placeholder: ' ' });
                break;
            case 'CheckBoxField':
                element = $('<input type="checkbox"></input>');
                break;
            case 'DateField':
                element = $('<input type="text"></input>');
                element.mask('99/99/9999', { placeholder: ' ' });
                break;
            case 'EcfHeader':
            case 'Header':
                if (properties.showHeaders) {
                    var headerTemplate = properties.headerTemplateId ? $('#' + properties.headerTemplateId) : properties.headerTemplateId;
                    if (headerTemplate) {
                        element = $(headerTemplate.parseTemplate(definition.Properties))
                    } else {
                        element = $('<h1>' + definition.Properties['Text'] + '</h1>');
                    }
                }
                break;
            case 'TextContent':
                var textContentTemplate = properties.textContentTemplateId ? $('#' + properties.textContentTemplateId) : properties.textContentTemplate;
                if (textContentTemplate) {
                    element = $(textContentTemplate.parseTemplate(definition.Properties))
                } else {
                    element = $('<div>' + definition.Properties['Text'] + '</div>');
                }
                break;
            case 'LabelField':
                element = $('<input type="text" readonly="readonly"></input>');
                break;
        }

        if (element) {
            var item;
            if (definition.AutoPostBack) {
                element.change(function() { engine.updateForm(definition.FieldName) });
            }

            if (definition.ControlType != 'Header' && definition.ControlType != 'TextContent') {
                if (definition.Required) {
                    definition.Label = '*' + definition.Label;
                }
                element.attr('id', 'Form' + formId + '_' + definition.ID + '_input');
                element.attr('name', 'Form' + formId + '_Field___' + definition.FieldName);
                if (definition.ReadOnly) {
                    element.attr('readonly', 'readonly');
                }
                var template = properties.template ? properties.template : $('#' + properties.templateId);

                item = $(template.parseTemplate(definition));
                item.find('#magicfield').replaceWith(element);

            } else {
                item = element;
            }

            if (item.attr('class') == '') {
                if (definition.Role && definition.Role != 'Other') {
                    item.addClass(definition.Role.toLowerCase());
                } else {
                    item.addClass('container');
                }
            }

            if (item.attr('id') == '') {
                item.attr('id', 'Form' + formId + '_' + definition.FieldName + '_container');
            }

            var hiddenFields = properties.hiddenFields;
            if (!definition.Visible || (hiddenFields && $.inArray(definition.Role, hiddenFields) != -1)) {
                item.hide();
            }

            if (definition.Value) {
                element.val(definition.Value);
            }
            fields.push({ id: definition.ID, fieldName: definition.FieldName, elementId: element.attr('id'), containerId: item.attr('id') });
        }

        return item;
    }



    this.processValidationErrors = function(newErrors) {
        if (properties.errorMessageContainer && newErrors && newErrors.length > 0) {
            if (properties.errorMessage) {
                properties.errorMessageContainer.text(properties.errorMessage);
            } else {
                properties.errorMessageContainer.text('The fields highlighted below require your attention.');
            }
        }

        var invalidItemClass = properties.invalidItemClass ? properties.invalidItemClass : invalidCssClass;

        if (invalidItemClass) {
            for (var i = 0; i < fields.length; i++) {
                var field = fields[i];
                var element = $('#' + field.elementId);
                var hasError = newErrors.first(function(item) {
                    return item.FieldName == field.fieldName;
                }) != null;
                element.toggleClass(invalidItemClass, hasError);
            }
        }

        return newErrors.length == 0;
    }

    this.getValues = function() {
        var valuesString = '{';

        for (var i = 0; i < fields.length; i++) {
            if (i > 0) {
                valuesString += ', ';
            }
            var field = fields[i]
            valuesString += ("'" + field.fieldName + "': ");
            var val = $('#' + field.elementId).val().replace("'", "&apos;");
            valuesString += val == null || val == '' ? "''" : ("'" + val + "'");
        }

        valuesString += '}';
        return valuesString;
    }

    this.populateSelectList = function(element, options) {
        element.empty();
        element.append('<option value="">--</option>');

        var prevGroup, currGroup;
        var optionsString = '';

        for (var i = 0; i < options.length; i++) {
            var option = options[i];

            currGroup = option.GroupText;
            
            if (currGroup) {
                if (currGroup != prevGroup) {
                    if (i > 0) {
                        optionsString += '</optgroup>';
                    }
                    optionsString += ('<optgroup label="' + currGroup + '">');
                }
            }
            optionsString += ('<option value = "' + options[i].Value + '">' + options[i].Text + '</option>');

            prevGroup = currGroup;
        }

        if (currGroup) {
            optionsString += '</optgroup>';
        }

        element.append(optionsString);
    }


    this.configureControls = function(form) {
        for (var i = 0; i < form.Fields.length; i++) {
            var field = form.Fields[i];
            var current = fields.first(function(item) { return item.id == field.ID; });
            if (current) {
                var control = $('#' + current.elementId);
                if (!field.Visible || (properties.hiddenFields && $.inArray(field.Role, properties.hiddenFields) != -1)) {
                    $('#' + current.containerId).hide();
                } else {
                    $('#' + current.containerId).show();
                }
                if (field.ControlType == 'DropDownListField') {
                    this.populateSelectList(control, field.Options);
                }
                if (field.ReadOnly) {
                    control.attr('readonly', 'readonly');
                }
                control.val(field.Value);
            }
        }
    }



    this.postSubmit = function(result) {
        if (!properties.postSubmitFunction)
            return;

        properties.postSubmitFunction(result);
    }

}


jQuery.fn.loadForm = function(properties) {
    if (this.engine) {
        delete this.engine;
    }
    var engine = new DMiFormEngine(this, properties);
    engine.getForm();
    this.engine = engine;
}

