﻿(function ($) {
    $.fn.customFieldDefinition = function (settings) {
        var selectTag = "<select></select>";
        var optionTag = "<option></option>";
        var divTag = "<div></div>";
        var config = $.extend({}, $.fn.customFieldDefinition.defaults, settings);

        function parseXML(xml) {
            if (window.ActiveXObject && window.GetObject) {
                var dom = new ActiveXObject('Microsoft.XMLDOM');
                dom.loadXML(xml);
                return dom;
            }
            if (window.DOMParser)
                return new DOMParser().parseFromString(xml, 'text/xml');
            throw new Error('No XML parser available');
        }

        function getListTypeHtml(connStr, selectCmd, txtField, valField, valStrField) {
            var attributesHtml = '<tr class="customfield-list-row"><td>ConnectionString</td><td><input class="customfields" type="text" value="' + connStr + '" /></td><td><span class="customfields-required-hide">*</span></td></tr>';
            attributesHtml += '<tr class="customfield-list-row"><td>SelectCommand</td><td><input class="customfields" type="text" value="' + selectCmd + '" /></td><td><span class="customfields-required-hide">*</span></td></tr>';
            attributesHtml += '<tr class="customfield-list-row"><td>TextField</td><td><input class="customfields" type="text" value="' + txtField + '" /></td><td><span class="customfields-required-hide">*</span></td></tr>';
            attributesHtml += '<tr class="customfield-list-row"><td>ValueField</td><td><input class="customfields" type="text" value="' + valField + '" /></td><td><span class="customfields-required-hide">*</span></td></tr>';
            attributesHtml += '<tr class="customfield-list-row"><td>Values</td><td><input class="customfields" type="text" value="' + valStrField + '" /></td><td><span class="customfields-required-hide">*</span></td></tr>';

            return attributesHtml;
        }

        function getAttributesHtml(id, name, type, connStr) {
            return getAttributesHtml(id, name, type, "", "", "", "", "");
        }

        function getAttributesHtml(id, name, type, connStr, selectCmd, txtField, valField, valStrField) {
            var attributesHtml = '<table><tr><td>Id</td><td><input class="customfields-required" type="text" value="' + id + '" /></td><td><span class="customfields-required-hide">*</span></td></tr>';
            attributesHtml += '<tr><td>Name</td><td><input class="customfields-required" type="text" value="' + name + '" /></td><td><span class="customfields-required-hide">*</span></td></tr>';
            attributesHtml += '<tr><td>Type</td><td><select>';
            attributesHtml += '<option' + ((type == "Text") ? " selected='selected'" : "") + '>Text</option>';
            attributesHtml += '<option' + ((type == "DateTime") ? " selected='selected'" : "") + '>DateTime</option>';
            attributesHtml += '<option' + ((type == "List") ? " selected='selected'" : "") + '>List</option>';
            attributesHtml += '<option' + ((type == "Time") ? " selected='selected'" : "") + '>Time</option>';
            attributesHtml += '</select></td></tr>';

            if (type == "List")
                attributesHtml += getListTypeHtml(connStr, selectCmd, txtField, valField, valStrField);

            attributesHtml += "</table>";
            return attributesHtml;
        }

        function getNewPropertyRow(id, value) {
            return '<tr><td><input type="Text" value="' + id + '" /></td><td><input type="text" value="' + value + '" /></td><td><a href="#" class="deleteCustomField" id="' + id + '" href="#">Delete</a></td></tr>';
        }

        function customFieldSelectChange(selectedVal, div, toRemove, hiddenInput) {
            var domXML = parseXML(hiddenInput.val());
            div.html('');
            var attributesHtml = '';
            if (selectedVal != 'ADD') {
                $(domXML).find('FIELD[ID="' + selectedVal + '"]').each(function () {
                    div.dialog('option', 'title', 'Edit Field Definition - ' + $(this).attr("ID"));

                    attributesHtml = getAttributesHtml($(this).attr("ID"), $(this).attr("Name"), $(this).attr("Type"), $(this).attr("ConnectionString"), $(this).attr("SelectCommand"), $(this).attr("TextField"), $(this).attr("ValueField"), $(this).attr("Values")).replace('</table>', '');

                    $.each(this.attributes, function (i, attrib) {
                        var name = attrib.name;
                        var value = attrib.value;
                        if (name != "ID" && name != "Name" && name != "Type" && name != "ConnectionString" && name != "SelectCommand" && name != "TextField" && name != "ValueField" && name!="Values")
                            attributesHtml += getNewPropertyRow(name, value);
                    });
                });
            }
            else {
                div.dialog('option', 'title', 'Add New Field Definition');
                attributesHtml = getAttributesHtml('', '', 'Text').replace("</table>", "");

            }

            attributesHtml += '<tr><td><input type="text" value="" /></td><td><input type="text" value="" /></td><td><a class="addCustomField" href="#">Add</a></td></tr>';
            attributesHtml += '</table>';
            div.append(attributesHtml);

            div.find('.addCustomField').click(function () {
                var id = $(this).parent().parent().find('input:first').val().replace(' ', '');
                var value = $(this).parent().parent().find('input:last').val();
                var newPropertyHtml = getNewPropertyRow(id, value);

                //reset values
                $(this).parent().parent().find('input:first').val('');
                $(this).parent().parent().find('input:last').val('');

                $(newPropertyHtml).insertBefore($(this).parent().parent());
                return false;
            });

            div.find('select:first').change(function () {
                if ($(this).find('option:selected:first').text() == "List") {
                    $(this).parent().parent().after(getListTypeHtml("", "", "", "", ""));
                }
                else {
                    div.find('.customfield-list-row').remove();
                }
            });

            div.find('input:first').blur(function () {
                $(this).val($(this).val().toUpperCase().replace(/\s+/g, ''));
            });

            div.find('input:eq(1)').blur(function () {
                var idElement = div.find('input:first');
                if (idElement.val() == '') {
                    idElement.val($(this).val().toUpperCase().replace(/\s+/g, ''));
                }
            });

            toRemove = new Array();
            div.dialog('open');
        }

        function refreshSelect(select, hiddenInput) {
            select.empty();
            //Add the "Add New..." option
            if (config.allowAdd) {
                select.append($(optionTag)
                                .attr("value", "ADD")
                                .text('Add New...'));
            }

            var domXML = parseXML(hiddenInput.val());
            //Add each Field as an option

            $(domXML).find('FIELD').each(function () {
                select.append($(optionTag)
                                .attr("value", $(this).attr("ID"))
                                .text($(this).attr("Name")));
            });
        }

        return this.each(function () {
            var $this = $(this);

            (function () {
                var methods = {
                    initialize: function () {
                        $this.parent().append($(divTag));
                        $this.parent().append($(selectTag)
                            .attr("size", "5"));

                        var div = $this.parent().find('div:last');
                        var select = $this.parent().find('select:last');
                        var hiddenInput = $this;
                        //in case the custom fields are empty
                        if (hiddenInput.val() == "")
                            hiddenInput.val('<FIELDS></FIELDS>');

                        //var domXML = parseXML(hiddenInput.val());
                        var toRemove = new Array();

                        div.dialog({
                            autoOpen: false,
                            height: 350,
                            width: 500,
                            modal: true,
                            title: '',
                            buttons: {
                                'Close': function () {
                                    $(this).dialog('close');
                                },
                                'Delete': function () {
                                    if (confirm('Are you sure you want to delete this field')) {
                                        //TODO remove field from xml values
                                        var domXML = parseXML(hiddenInput.val());
                                        var title = $(this).dialog('option', 'title');
                                        var editing = title.split('-').length > 1;
                                        var id = '';
                                        if (!editing) {
                                            $(this).dialog('close');
                                            return;
                                        }
                                        else
                                            id = $.trim(title.split('-')[1]);

                                        var fields = domXML.getElementsByTagName('FIELD');
                                        var field;
                                        $.each(fields, function (i, v) {
                                            if ($(v).attr('ID') == id)
                                                field = v;
                                        });

                                        if (field) {
                                            domXML.documentElement.removeChild(field);
                                            select.find('option[value="' + id + '"]').remove();
                                        }

                                        var json = $.xmlToJSON(domXML);
                                        hiddenInput.val(json.toString());

                                        $(this).dialog('close');
                                    }
                                },
                                'Save Changes': function () {
                                    //update xml values
                                    var domXML = parseXML(hiddenInput.val());
                                    var div = $(this);
                                    var id = $(this).find('input:first').val();
                                    var oldId = id;
                                    var title = $(this).dialog('option', 'title');
                                    var validateID = false;
                                    var editing = title.split('-').length > 1;
                                    var json = $.xmlToJSON(domXML);

                                    if (editing) {
                                        oldId = $.trim(title.split('-')[1]);
                                        if (oldId != id)
                                            validateID = true;
                                    }
                                    else
                                        validateID = true;

                                    if (validateID) {
                                        if ($(domXML).find('FIELD[ID="' + id + '"]').length != 0) {
                                            alert("The given ID already exists, cannot insert duplicate ID's");
                                            return;
                                        }
                                        else {
                                            //we need to update the value of the option
                                            select.find('option[value="' + oldId + '"]').val(id);
                                        }
                                    }

                                    $('.customfields-required').each(function () {
                                        var span = $(this).parent().parent().find('span:first');
                                        if ($(this).val() == "") {
                                            span.removeClass('customfields-required-hide');
                                            span.addClass('customfields-required-show');
                                        }
                                        else {
                                            span.removeClass('customfields-required-show');
                                            span.addClass('customfields-required-hide');
                                        }
                                    });

                                    if ($('.customfields-required-show').length != 0) {
                                        return;
                                    }

                                    if (!editing) {
                                        var childNode = domXML.createElement("FIELD");
                                        domXML.documentElement.appendChild(childNode);
                                        $(domXML).find('FIELD:last').attr('ID', id);
                                    }
                                    else {
                                        $.each(toRemove, function (i, v) {
                                            $(domXML).find('FIELD[ID="' + oldId + '"]').removeAttr(v);
                                        });
                                    }

                                    div.find('tr').each(function () {
                                        var attId = '';
                                        var value = ''
                                        if ($(this).find('input').length == 2) {
                                            attId = $(this).find('input:first').val();
                                            value = $(this).find('input:last').val();
                                        }
                                        else {
                                            attId = $(this).find('td:first').text();
                                            value = $(this).find('input:first').val();

                                            if (attId == "Id")
                                                attId = "ID";
                                            if (attId == "Name" && !editing) {
                                                select.append($(optionTag)
                                                    .attr("value", id)
                                                    .text(value));
                                            }
                                            else if (attId == "Name" && editing) {
                                                select.find('option[value="' + id + '"]').text(value);
                                            }

                                            if (attId == "Type") {
                                                value = $(this).find('select:first').val();
                                            }
                                        }

                                        if (attId != '')
                                            $(domXML).find('FIELD[ID="' + oldId + '"]').attr(attId, value);
                                    });

                                    var json = $.xmlToJSON(domXML);
                                    //alert(json.toString());
                                    hiddenInput.val(json.toString());
                                    $(this).dialog('close');
                                }
                            }
                        });

                        refreshSelect(select, hiddenInput);

                        //Handles deleting an attribute
                        $('.deleteCustomField').live('click', function () {
                            $(this).parent().parent().remove();
                            toRemove.push($(this).attr('id'));
                        });

                        hiddenInput.hide();
                        hiddenInput.dblclick(function () {
                            refreshSelect(select, hiddenInput);
                            select.toggle();
                            hiddenInput.toggle();
                        });

                        select.dblclick(function () {
                            select.toggle();
                            hiddenInput.toggle();
                        });

                        var handler = function (s) {
                            if ($(this).val() != null)
                                customFieldSelectChange($(this).val(), div, toRemove, hiddenInput);
                        };

                        select.bind('click', handler);

                        //handle the click event
                        select.change(function (s) {
                            if ($(this).val() != null) {
                                customFieldSelectChange($(this).val(), div, toRemove, hiddenInput);

                                //once change has fired, we don't need to worry about click anymore
                                if ($(this).find('option').length > 1)
                                    select.unbind('click', handler);
                            }
                        });
                    }
                };

                methods.initialize();

            })();
        });
    }

    $.fn.customFieldDefinition.defaults = {
        allowAdd: true,
        allowEdit: true,
        allowDelete: true
    }
})(jQuery);
