/// class PD.Web.UI.Controls.TreeViewDragAndDropModule
/// using PD.Web.UI.Controls.TreeViewModule

PD.Web.UI.Controls.TreeViewDragAndDropModule =
PD.Web.UI.Controls.TreeViewModule.extend({

    //===================================
    // EVENT HANDLERS
    //===================================

    _onDrag: function (e) {

    },

    _onDragEnd: function (e) {

    },

    _onDragStart: function (e) {
    
    },

    _onDrop: function (e) {

        var that = this,
            tree = this.get_kendo(),
            srcData = null,
            dstData = null,
            dragArgs = null,
            dropHandler = this.getOption("onDrop", undefined);

        e.preventDefault();

        if (!this.isValidDrop(e)) {
            e.setValid(false);
            return;
        }

        srcData = tree.dataItem(e.sourceNode);
        dstData = tree.dataItem(e.destinationNode);
        dropArgs = {
            src: srcData,
            dst: dstData,
            position: e.dropPosition,
            commit: function () {

                that._commitDrop(e.dropPosition, {
                    node: e.sourceNode,
                    data: srcData,
                }, {
                    node: e.destinationNode,
                    data: dstData
                });

            }
        };

        if (dropHandler == null) {
            dropArgs.commit();
        }
        else {
            dropHandler(dropArgs);
        }

    },

    //===================================
    // PUBLIC METHODS
    //===================================

    isValidDrop: function (e) {
    
        var args = this._getDropEventArgs(e);

        return args.dropInTree
            && !args.dropOnSelf
            && ((!args.dropOnTree && !args.dropOnRoot) || (args.dropOnRoot && args.dropOnNode));

    },

    getOptionSettings: function () {
        return {
            dragAndDrop: true
        }
    },

    ready: function () {
        this.get_kendo().bind("drop", $.proxy(this._onDrop, this));
    },

    //===================================
    // PRIVATE METHODS
    //===================================

    _getDropEventArgs: function (e) {
    
        var treeNode = this.get_kendo().element;

        return {
            dropInTree: $(e.dropTarget).closest(".k-treeview").is(treeNode),
            dropOnTree: $(e.dropTarget).is(treeNode),
            dropOnRoot: $(e.dropTarget).closest("LI").parent().parent().hasClass("k-treeview"),
            dropOnNode: $(e.dropTarget).closest(".k-in").hasClass("k-state-hover"),
            dropOnSelf: $(e.dropTarget).is(e.sourceNode) || $.contains(e.sourceNode, e.dropTarget)
        }

    },

    _commitDrop: function (dropPosition, src, dst) {

        var that = this,
            tree = this.get_tree(),
            kendo = this.get_kendo(),
            $srcNode = null,
            $dstNode = null,
            srcId = null,
            srcChildren = null,
            srcSelected = null,
            loadChildrenOnDrop = false;

        if (src.data == null || dst.data == null) {
            return;
        }

        $srcNode = $(src.node);
        $dstNode = $(dst.node);
        loadChildrenOnDrop = !dst.data.loaded() || (dst.data.loaded() && !dst.data.hasChildren);

        if (dropPosition === "over" && loadChildrenOnDrop) {

            srcId = src.data.id,
            srcChildren = src.data.toJSON().items;
            srcSelected = tree.isSelected(srcId);

            kendo.remove($srcNode);

            dst.data.hasChildren = true;
            dst.data.loaded(false);
            dst.data.load();

            tree.get_deferred().add(function () {

                var srcData = kendo.dataSource.get(srcId);

                that._persistNodeExpansion(tree, kendo, dropPosition, {
                    node: kendo.element.find("[data-uid=" + srcData.uid + "]"),
                    data: srcData,
                    children: srcChildren,
                    isSelected: srcSelected
                }, dst);

            });

        }
        else {

            switch (dropPosition) {
                case "over":
                    kendo.append($srcNode, $dstNode);
                    break;
                case "before":
                    kendo.insertBefore($srcNode, $dstNode);
                    break;
                case "after":
                    kendo.insertAfter($srcNode, $dstNode);
                    break;
            }

            kendo.expand($dstNode);

        }
        
    },

    _persistNodeExpansion: function (tree, kendo, dropPosition, src, dst) {
        
        var $dstNode = $(dst.node);

        if (src.isSelected) {
            setTimeout(function () {
                tree.select(src.data.id, false);
                kendo.expand($dstNode);
            }, 100);
        }
        else {
            kendo.expand($dstNode);
        }

    }

});