﻿/// <reference name="MicrosoftAjax.debug.js" />
/// <reference name="MicrosoftAjaxTimer.debug.js" />
/// <reference name="MicrosoftAjaxWebForms.debug.js" />
/// <reference name="AjaxControlToolkit.ExtenderBase.BaseScripts.js" assembly="AjaxControlToolkit" />
/// <reference name="AjaxControlToolkit.Common.Common.js" assembly="AjaxControlToolkit" />
/// <reference name="AjaxControlToolkit.Compat.DragDrop.DragDropScript.js" assembly="AjaxControlToolkit" />

Type.registerNamespace('Infocaster.Web.Ajax');

Infocaster.Web.Ajax.DropTargetBehavior = function(element) {
    Infocaster.Web.Ajax.DropTargetBehavior.initializeBase(this, [element]);

    var _dropCueID = null;
    var _dropCue = null;
    var _dragGroup = null;
    var _tag = null;
}
Infocaster.Web.Ajax.DropTargetBehavior.prototype = {
    initialize : function() {
        Infocaster.Web.Ajax.DropTargetBehavior.callBaseMethod(this, 'initialize');
        //Register ourself as a droptarget
        AjaxControlToolkit.DragDropManager.registerDropTarget(this); 
    },

    dispose : function() {
        //Unregister ourself as the droptarget
        AjaxControlToolkit.DragDropManager.unregisterDropTarget(this);
        Infocaster.Web.Ajax.DropTargetBehavior.callBaseMethod(this, 'dispose');
    },

    get_DropCueID : function() {
        return this._dropCueID ;
    },
    set_DropCueID: function(value) {
        this._dropCueID = value;
        if (value == null)
            this._dropCueID = null;
        else
            this._dropCue = $get(value);
    },
    get_DropCue : function(){
        return this._dropCue;
    },
    add_onDrop : function(handler) {
        this.get_events().addHandler("onDrop", handler);
    },
    
    remove_onDrop : function(handler) {
        this.get_events().removeHandler("onDrop", handler);
    },  
    add_onEnter: function(handler) { this.get_events().addHandler("onEnter", handler); },
    remove_onEnter : function(handler) { this.get_events().removeHandler("onEnter", handler); },   
    add_onLeave: function(handler) { this.get_events().addHandler("onLeave", handler); },
    remove_onLeave : function(handler) { this.get_events().removeHandler("onLeave", handler); },   
    // onDrop property maps to onDrop event
    get_onDrop : function() {
        return this.get_events().getHandler("onDrop");
    },
    set_onDrop : function(value) {
        if (value && value.length > 0) {
            var func = $common.resolveFunction(value);
            if (func) { 
                this.add_onDrop(func);
            } else {
                throw Error.argumentType('value', typeof(value), 'Function', 'resize handler not a function, function name, or function text.')
            }
        }
    },
    get_onEnter : function() {
        return this.get_events().getHandler("onEnter");
    },
    set_onEnter : function(value) {
        if (value && value.length > 0) {
            var func = $common.resolveFunction(value);
            if (func) { 
                this.add_onEnter(func);
            } else {
                throw Error.argumentType('value', typeof(value), 'Function', 'resize handler not a function, function name, or function text.')
            }
        }
    },
    get_onLeave : function() {
        return this.get_events().getHandler("onLeave");
    },
    set_onLeave : function(value) {
        if (value && value.length > 0) {
            var func = $common.resolveFunction(value);
            if (func) { 
                this.add_onLeave(func);
            } else {
                throw Error.argumentType('value', typeof(value), 'Function', 'resize handler not a function, function name, or function text.')
            }
        }
    },
    set_Tag: function(value) {
        this._tag = value;
    },
    get_Tag : function() {
        return this._tag;
    },
    get_DropGroup: function(){
        return this._dropGroup;
    },
    set_DropGroup: function(val){
        this._dropGroup = val;
    },
    _raiseEvent : function( eventName, eventArgs ) {
        var handler = this.get_events().getHandler(eventName);
        if( handler ) {
            if( !eventArgs ) eventArgs = Sys.EventArgs.Empty;
            handler(this, eventArgs);
        }
    },
    get_dropTargetElement: function() { return this.get_element(); },
    // bool canDrop(DragMode, DataType, Data)
    canDrop: function(DragMode, DataType, Data) {
        return (Data != null && Data.get_DropGroup() == this.get_DropGroup());
    },
    // void drop(DragMode, DataType, Data)
    drop: function(DragMode, DataType, Data) {
        this._insertItem(Data.get_element());
        this._hideDropCue();
        this._raiseEvent("onDrop", new Infocaster.Web.Ajax.DropEventArgs(this, Data, this._findItemIndex()));
    },
    // void onDragEnterTarget(DragMode, DataType, Data)
    onDragEnterTarget: function(DragMode, DataType, Data) { 
        this._showDropCue(Data);
        this._raiseEvent("onEnter", new Infocaster.Web.Ajax.DropEventArgs(this, Data, this._findItemIndex()));
    },
    // void onDragLeaveTarget(DragMode, DataType, Data)
    onDragLeaveTarget: function(DragMode, DataType, Data) {
        this._hideDropCue(Data); 
        this._raiseEvent("onLeave", new Infocaster.Web.Ajax.DropEventArgs(this, Data, this._findItemIndex()));
    },
    // void onDragInTarget(DragMode, DataType, Data)
    onDragInTarget: function(DragMode, DataType, Data) { this._repositionDropCue(Data);  },
    
    //Helper functions
    _hideDropCue: function(){
        if (this.get_DropCue() != null)
            Sys.UI.DomElement.setVisible(this.get_DropCue(), false);
    },
    //Shows the dropcue for the given item
    _showDropCue: function(data){
        var dropCue = this.get_DropCue();
        if (dropCue != null){
            //Make it visible          
            $common.setVisible(dropCue, true);
        
            //Determine the size of the dropcue
            var bounds = $common.getBounds(data.get_element());
            dropCue.style.width = bounds.width + "px";
            dropCue.style.height = bounds.height + "px";
            
            this._repositionDropCue(data);
        }
    },
    //Repositions the dropcue for the data given
    _repositionDropCue: function(data){
        var dropCue = this.get_DropCue();
        if (dropCue != null){
            var pos = Sys.UI.DomElement.getLocation(data.get_element()); 
            var closeChild = this._findItemAt(pos.x, pos.y, data.get_element());
            var el = this.get_element();
            //First remove before insert again, certain browsers might behave strange when leaving the parent
            if (Sys.Browser.agent != Sys.Browser.InternetExplorer){ //Removing in IE wont make a difference except for loads of frame drops
                if (dropCue.parentNode != null)
                    dropCue.parentNode.removeChild(dropCue);
            }
            el.insertBefore(dropCue, closeChild);
        }
    },
    _findItemAt : function(x, y, item)
    {
        var el = this.get_element();
        
        var child = el.firstChild;
        while( child != null )  {
            if( child != this._dropCue && 
                child != item &&
                !child.nodeName.startsWith('#'))
            {
                var pos = $common.getLocation(child);
                if( y <= pos.y) {
                    return child;
                }
            }
            child = child.nextSibling;
        }
        return null;
    },
    _findItemIndex : function(item){
        var el = this.get_element();    
        var child = el.firstChild;
        var counter = 0;
        while( child != null ) {
            if(!child.nodeName.startsWith('#')) {
                counter++;
                if (child == item){
                    return counter;
                }
            }
            child = child.nextSibling;
        } 
        return 0;
    },
    _insertItem: function(item){
        Sys.Debug.assert(item != null);
    
        var dropCue = this.get_DropCue();
        var el = this.get_element();
        
        //Remove the item from the current parent
        if (item.parentNode != null)
            item.parentNode.removeChild(item);
               
        //If there is no dropcue or not placed, determine the place ourselfs 
        if (dropCue == null || dropCue.style.display == 'none') {
            var pos = Sys.UI.DomElement.getLocation(item); 
            var closeChild = this._findItemAt(pos.x, pos.y, item);
            el.insertBefore(item, closeChild);
        }
        else{
            //Insert the item before the dropCue
            el.insertBefore(item, dropCue);
        }
    }
}
Infocaster.Web.Ajax.DropTargetBehavior.registerClass('Infocaster.Web.Ajax.DropTargetBehavior', 
AjaxControlToolkit.BehaviorBase,
AjaxControlToolkit.IDropTarget);

Infocaster.Web.Ajax.DropEventArgs = function(dropZone, dragSource, position) {
    this._dropZone = dropZone;
    this._dragSource = dragSource;
    this._position = position;
}
Infocaster.Web.Ajax.DropEventArgs.prototype = {
    get_DropZone: function(){
        return this._dropZone;
    },
    get_DragSource: function(){
        return this._dragSource;
    },
    get_Position: function(){
        return this._position;
    },
    //Tries to locate the next component
    find_Next: function(){
        var dropZone = this.get_DropZone().get_element();
        var dragSource = this.get_DragSource().get_element();
        var child = dropZone.firstChild;
        var found = false;
        while( child != null ) {
            if (found && child.id != this.get_DropZone().get_DropCueID())
                break; //We found child 
            if (child == dragSource)
                found = true;
            child = child.nextSibling;
        } 
        if (child == null) //If no child is found, return null
            return null;
        var next = null;    
        Array.forEach(Sys.Application.getComponents(), function(c){
            if (Infocaster.Web.Ajax.DragSourceBehavior.isInstanceOfType(c) && c.get_element() == child){
                next = c;
            }
        }, child);
        return next;
    }
}
Infocaster.Web.Ajax.DropEventArgs.registerClass('Infocaster.Web.Ajax.DropEventArgs');


if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();