ProspectDirector.Modules.EntityTypes.EntityTypeRelationshipsDialog = (function (options) {

    var

        PRIVATE = {

            init: function (options) {

                PRIVATE.options = $.extend({
                    selector: null,
                    data: {
                        entityTypes: null
                    }
                }, options);

                PRIVATE.init_tabStrip();
                PRIVATE.init_typeDropDownList();
                PRIVATE.init_editorTree();
                PRIVATE.init_mapTree();

                PRIVATE.get_okButton().on("click", $.proxy(PRIVATE.okButton_onClick, PRIVATE));

                PRIVATE.options.targetNode = null;
                PRIVATE.options.fallbackNode = null;
                PRIVATE.options.getMapRequestExecuting = false;

                PRIVATE.bindEditorTree();

                $(PRIVATE.options.selector).data("kendoWindow").setOptions({
                    height: 500,
                    width: 650,
                    resizable: true
                });

            },

            get_dialog: function () {
                return $(PRIVATE.options.selector);
            },

            get_tabStrip: function () {
                return PRIVATE.get_dialog().find("[data-role=tabstrip]");
            },

            get_editorTree: function () {
                return PRIVATE.get_dialog().find("[data-role=editor-tree]");
            },

            get_mapTree: function () {
                return PRIVATE.get_dialog().find("[data-role=map-tree]");
            },

            get_typeDropDownList: function () {
                return PRIVATE.get_dialog().find("[data-role=entity-type]");
            },

            get_okButton: function () {
                return PRIVATE.get_dialog().find("INPUT[type=button][data-command=ok]");
            },

            init_tabStrip: function () {

                PRIVATE.get_tabStrip().kendoTabStrip({
                    animation: false,
                    select: $.proxy(PRIVATE.tabStrip_onSelect, PRIVATE)
                });

            },

            init_typeDropDownList: function () {

                var types = PRIVATE.options.data.entityTypes,
                    index = 0;

                for (index = 0; index < types.length; index++) {
                    PRIVATE.get_typeDropDownList().append("<option value=\"" + types[index].id + "\">" + types[index].name + "</option>");
                }

                PRIVATE.get_typeDropDownList().on("change", $.proxy(PRIVATE.typeDropDownList_onChange, PRIVATE));

            },

            init_editorTree: function () {

                var tree = null;

                PRIVATE.get_editorTree().kendoTreeView({
                    dataSource: {
                        schema: {
                            id: "id"
                        }
                    },
                    template: $.proxy(PRIVATE.editorTree_applyNodeTemplate, PRIVATE),
                    dragAndDrop: true,
                    drag: $.proxy(PRIVATE.editorTree_onDrag, PRIVATE),
                    dragstart: $.proxy(PRIVATE.editorTree_onDragStart, PRIVATE),
                    drop: $.proxy(PRIVATE.editorTree_onDrop, PRIVATE),
                    select: $.proxy(PRIVATE.editorTree_onSelect, PRIVATE)
                });

                tree = PRIVATE.get_editorTree().data("kendoTreeView");

                /* add static category nodes */

                tree.append({
                    id: 2,
                    type: "category",
                    name: "Parent Types",
                    icon: "ELEMENT_UP.PNG"
                });

                tree.append({
                    id: 1,
                    type: "category",
                    name: "Child Types",
                    icon: "ELEMENT_DOWN.PNG"
                });

                tree.append({
                    id: 0,
                    type: "category",
                    name: "Available Types",
                    icon: "ELEMENT.PNG"
                });

            },

            init_mapTree: function () {

                PRIVATE.get_mapTree().kendoTreeView({
                    template: $.proxy(PRIVATE.mapTree_applyNodeTemplate, PRIVATE)
                });

            },

            tabStrip_onSelect: function (e) {

                var command = $(e.item).data("command");


                switch (command) {

                    case "map":
                        if (!PRIVATE.options.getMapRequestExecuting) {
                            PRIVATE.bindMapTree();
                        }
                        break;

                }

            },

            typeDropDownList_onChange: function () {
                PRIVATE.bindEditorTree();
                PRIVATE.get_typeDropDownList().disable();
                PRIVATE.get_editorTree().disable();
            },

            editorTree_applyNodeTemplate: function (e) {
                return PRIVATE.mapTree_getNodeTemplate(e.item);
            },

            editorTree_getNodeTemplate: function (e) {

                var $span = $("<span></span>");

                if (e.icon !== null) {
                    icon = "<img src=\"" + ProspectDirector.RUNTIME.resolveUrl("~/application/icons/16x16/") + e.icon + "\" style=\"vertical-align:top;margin-right:5px;\"/>";
                }

                $span.html((icon ? icon : "") + e.name);

                return $span[0].outerHTML;

            },

            mapTree_applyNodeTemplate: function (e) {
                return PRIVATE.mapTree_getNodeTemplate(e.item);
            },

            mapTree_getNodeTemplate: function (e) {

                var $span = $("<span></span>");

                if (e.icon !== null) {
                    icon = "<img src=\"" + ProspectDirector.RUNTIME.resolveUrl("~/application/icons/16x16/") + e.icon + "\" style=\"vertical-align:top;margin-right:5px;\"/>";
                }

                $span.html((icon ? icon : "") + e.name);

                return $span[0].outerHTML;

            },

            editorTree_onDragStart: function (e) {

                var tree = PRIVATE.get_editorTree().data("kendoTreeView"),
                    data = tree.dataItem(e.sourceNode);

                if (data.type === "category") {
                    e.preventDefault();
                }

            },

            editorTree_onDrag: function (e) {

                if (!PRIVATE.editorTree_isValidDrop(e)) {
                    e.setStatusClass("k-denied");
                }

            },

            editorTree_onDrop: function (e) {

                var tree = PRIVATE.get_editorTree().data("kendoTreeView"),
                    sourceId = PRIVATE.get_typeDropDownList().val(),
                    targetId = tree.dataItem(e.sourceNode).id,
                    referenceType = null;

                if (!PRIVATE.editorTree_isValidDrop(e)) {
                    e.setValid(false);
                    return;
                }

                referenceType = tree.dataItem(e.destinationNode).id;

                PRIVATE.options.targetNode = $(e.sourceNode);
                PRIVATE.options.fallbackNode = $(e.sourceNode).parent().closest("LI[data-uid]");

                PD.ajax({
                    type: "POST",
                    url: ProspectDirector.RUNTIME.resolveUrl("~/entitytyperelationship/setrelationship"),
                    data: {
                        sourceTypeId: sourceId,
                        targetTypeId: targetId,
                        type: referenceType
                    },
                    error: $.proxy(PRIVATE.editorTree_onDrop_onError, PRIVATE)
                });

            },

            editorTree_onDrop_onError: function (jqXHR) {

                var tree = PRIVATE.get_editorTree().data("kendoTreeView");

                ProspectDirector.Types.Core.Notifications.error(jqXHR.responseJSON.message);

                if (PRIVATE.options.fallbackNode.length > 0) {
                    tree.append(PRIVATE.options.targetNode, PRIVATE.options.fallbackNode);
                }

            },

            editorTree_onSelect: function (e) {
                e.preventDefault();
            },

            okButton_onClick: function (e) {
                PRIVATE.get_dialog().data("dialog").hide();
            },

            bindMapTree: function () {

                var tree = PRIVATE.get_mapTree().data("kendoTreeView");

                PD.ajax({
                    type: "GET",
                    url: ProspectDirector.RUNTIME.resolveUrl("~/entitytyperelationship/relationshipmap"),
                    success: $.proxy(PRIVATE.bindMapTree_onSuccess, PRIVATE)
                });

            },

            bindMapTree_onSuccess: function (a, b, c) {
                PRIVATE.options.getMapRequestExecuting = false;
                PRIVATE.clearMapTree();
                PRIVATE.addMapNode(a);
            },

            addMapNode: function (data, parentNode) {

                var tree = PRIVATE.get_mapTree().data("kendoTreeView"),
                    node = null,
                    datum = null,
                    index = 0;

                for (index = 0; index < data.length; index++) {

                    datum = data[index];

                    tree.append($.extend({
                        icon: "GRAPH_NODE.PNG"
                    }, datum), parentNode);

                    if (parentNode === undefined || parentNode === null) {
                        node = PRIVATE.get_mapTree().find("LI[data-uid]").last();
                    }
                    else {
                        node = parentNode.find("LI[data-uid]").last();
                    }

                    PRIVATE.addMapNode(datum.relationships, node);

                }

            },

            bindEditorTree: function () {

                var tree = PRIVATE.get_mapTree().data("kendoTreeView");

                PD.ajax({
                    type: "GET",
                    url: ProspectDirector.RUNTIME.resolveUrl("~/entitytyperelationship/relationshipgraph?entityTypeId=" + PRIVATE.get_typeDropDownList().val()),
                    success: $.proxy(PRIVATE.bindEditorTree_onSuccess, PRIVATE)
                });

            },

            bindEditorTree_onSuccess: function (a, b, c) {

                var nodes = null;

                PRIVATE.clearEditorTree();

                nodes = PRIVATE.get_editorTree().find("UL > LI");

                PRIVATE.addEditorNode(a.referencedBy, $(nodes[0]));

                PRIVATE.addEditorNode(a.references, $(nodes[1]));

                PRIVATE.addEditorNode(a.unreferenced, $(nodes[2]));

                PRIVATE.get_typeDropDownList().enable();
                PRIVATE.get_typeDropDownList().focus();
                PRIVATE.get_editorTree().enable();

            },

            addEditorNode: function (data, parentNode) {

                var tree = PRIVATE.get_editorTree().data("kendoTreeView"),
                    index = 0;

                for (index = 0; index < data.length; index++) {

                    tree.append($.extend({
                        icon: "GRAPH_NODE.PNG"
                    }, data[index]), parentNode);

                }

            },

            clearMapTree: function () {

                var tree = PRIVATE.get_mapTree().data("kendoTreeView"),
                    nodes = PRIVATE.get_mapTree().find("UL > LI"),
                    index = 0;

                for (index = 0; index < nodes.length; index++) {
                    tree.remove(nodes[index]);
                }

            },

            clearEditorTree: function () {

                var tree = PRIVATE.get_editorTree().data("kendoTreeView"),
                    nodes = PRIVATE.get_editorTree().find("UL > LI"),
                    index = 0;

                nodes.each(function (index, el) {

                    var children = $(el).find("UL > LI");

                    for (index = 0; index < children.length; index++) {
                        tree.remove(children[index]);
                    }

                });

            },

            editorTree_isValidDrop: function (e) {

                var dropInTree = $(e.dropTarget).closest(".k-treeview").is(PRIVATE.get_editorTree()),
                    dropOnTree = $(e.dropTarget).is(PRIVATE.get_editorTree()),
                    dropOnNode = $(e.dropTarget).closest(".k-in").hasClass("k-state-hover")
                dropOnSelf = $(e.dropTarget).is(e.sourceNode) || $.contains(e.sourceNode, e.dropTarget),
                    tree = PRIVATE.get_editorTree().data("kendoTreeView"),
                    data = null;

                if (dropInTree && !dropOnSelf && !dropOnTree && dropOnNode) {

                    data = tree.dataItem($(e.dropTarget).closest("LI[data-uid]"));

                    return data.type === "category";

                }

                return false;

            }

        },

        PUBLIC = {

        };

    PRIVATE.init(options);

    return PUBLIC;

});
