﻿// - RadWindowManager has the ability to act as factory for RadWindow objects
// - Provides the radwindow, radprompt, radconfirm and radopen methods
// - Stores windows' state
Type.registerNamespace('Sunny.Web.UI');
Type.registerNamespace('Sunny.Web.UI.WindowManager');

//Backward compatibility function - it needs the existance of a RadWindowManager
//It returns the first registered manager on the page
function GetRadWindowManager()
{
    return Sunny.Web.UI.WindowManager.Manager;
}

window.radalert = function(text, oWidth, oHeight, oTitle)
{
    var oManager = GetRadWindowManager();
	var oWnd = oManager._getStandardPopup("alert", text);

	if (typeof(oTitle) != 'undefined')
	{
		oWnd.set_title(oTitle)
	}
	oWnd.setSize(oWidth ? oWidth : 280 , oHeight ? oHeight : 200);

	//Logical problem - show does not center the [modal] window properly, as the page height is calculated as if scrollbars exist, but they are disababled
	oWnd.show();
	oWnd.center();
	return oWnd;
}

window.radconfirm = function (text, callBackFn, oWidth, oHeight, callerObj, oTitle)
{
    var oManager = GetRadWindowManager();
	var oWnd = oManager._getStandardPopup("confirm", text);

	if (typeof(oTitle) != 'undefined')
	{
		oWnd.set_title(oTitle)
	}
	oWnd.setSize(oWidth ? oWidth : 280 , oHeight ? oHeight : 200);

	oWnd.set_clientCallBackFunction(function(sender, result)
	{
	    if (callBackFn) callBackFn(result);	  
	});

	//Logical problem - show does not center the [modal] window properly, as the page height is calculated as if scrollbars exist, but they are disababled
	oWnd.show();
	oWnd.center();
	return oWnd;
}

window.radprompt = function (text, callBackFn, oWidth, oHeight, callerObj, oTitle, initialValue)
{
    var oManager = GetRadWindowManager();

	var oWnd = oManager._getStandardPopup("prompt", text, initialValue);

	if (typeof(oTitle) != 'undefined')
	{
		oWnd.set_title(oTitle)
	}
	oWnd.setSize(oWidth ? oWidth : 280 , oHeight ? oHeight : 200);

	oWnd.set_clientCallBackFunction(function(sender, result)
	{
	    if (callBackFn) callBackFn(result);	  
	});

	//Logical problem - show does not center the [modal] window properly, as the page height is calculated as if scrollbars exist, but they are disababled
	oWnd.show();
	oWnd.center();
	
	//NEW: Hack to set default text of more than one word in IE - it simpy won't show otherwise!
	if (initialValue && $Sunny.isIE)
	{	
	    var input = oWnd.get_popupElement().getElementsByTagName("INPUT")[0];
	    if (input) input.value = initialValue;    
	}
	
	return oWnd;
}

window.radopen = function(url, name)
{
    var oManager = GetRadWindowManager();
    return oManager.open(url, name);
}

//-------------------------------------------------------------//
Sunny.Web.UI.RadWindowManager = function(element)
{
    /// <exclude/>
    Sunny.Web.UI.RadWindowManager.initializeBase(this, [element]);
    this._windowIDs = [];
    this._windows = [];
    this._preserveClientState = false;
    
    //Backward compatibility layer
    this.Open = this.open;
    this.GetWindowByName = this.getWindowByName;
    this.GetWindowById = this.getWindowById;
    this.GetActiveWindow = this.getActiveWindow;
    this.GetWindowObjects = this.get_windows;
    this.GetWindows = this.get_windows;
    this.Cascade = this.cascade;
    this.Tile = this.tile;
    this.RestoreAll = this.restoreAll;
    this.MaximizeAll = this.maximizeAll;
    this.MinimizeAll = this.minimizeAll;
    this.ShowAll = this.showAll;
    this.CloseAll = this.closeAll;
    this.CloseActiveWindow = this.closeActiveWindow;
    this.MinimizeActiveWindow = this.minimizeActiveWindow;
    this.RestoreActiveWindow  = this.restoreActiveWindow;
}

Sunny.Web.UI.RadWindowManager.prototype =
{
    //NEW
    get_zIndex : function()
    {
        /// <exclude />
        return Sunny.Web.UI.RadWindowUtils._zIndex;
    },

    set_zIndex : function(value)
    {
        var zIndex = parseInt(value);
        if (isNaN(value)) return;
        Sunny.Web.UI.RadWindowUtils._zIndex = value;
    },

    initialize : function(element)
    {
        //Set z-Index
        try
        {
            var zIndex = this.get_element().style.zIndex;
            if (zIndex) this.set_zIndex(zIndex);
        } catch(e){;};

        /// <exclude/>
        //Create a list of window objects
        this._initialize();

        //Try to register as a page window manager
        this._registerAsPageManager();

        //Restore state
        //AutoSave - preserve client window state in a cookie
	    if(this.get_preserveClientState())
	    {
		    this.restoreState();
	    }
    },

    dispose : function()
    {
        /// <exclude/>

        var preserveState = this.get_preserveClientState();
        if (preserveState)
        {
            this.saveState();
        }

        this._disposeWindows();
        this._windows = null;
        Sunny.Web.UI.RadWindowManager.callBaseMethod(this, 'dispose');
    },

    open : function(url, wndName)
    {
	    var oWnd = this.getWindowByName(wndName);
	    if (!oWnd)
	    {
	        //Backward compatibility - if no wndName is provided, create a new one
	        if (!wndName)
	        {
	            wndName = this.get_id() + this._getUniqueId();
	        }

		    oWnd = this._createWindow(wndName);
	    }


//Svetlina - 22.12.08 - the setUrl method should not be used here when have ReloadOnShow=true or if we open the same RadWindow again because it is called also in the show() method

        if(url && !oWnd.get_reloadOnShow() && oWnd._iframe && oWnd._iframe.src != url) 
        {
           oWnd.setUrl(url);
        }
	    else if(url) oWnd._navigateUrl = url;   

	    oWnd.show();

	    return oWnd;
    },


    getActiveWindow : function()
    {
        return Sunny.Web.UI.RadWindowController.get_activeWindow();
    },

    getWindowById : function(id)
    {
	    var oArr = this.get_windows();
	    for (var i=0; i < oArr.length; i++)
	    {
		    var oWnd = oArr[i];
		    if (id == oWnd.get_id())
		    {
			     return oWnd;
		    }
	    }
	    return null;
    },

    getWindowByName : function(name)
    {
	    var oArr = this.get_windows();
	    if (!oArr) return null;

	    for (var i=0; i < oArr.length; i++)
	    {
		    var oWnd = oArr[i];
		    if (name == oWnd.get_name())
		    {
			     return oWnd;
		    }
	    }
	    return null;
    },

    //Called when a window is being disposed on destroy on close = true
    removeWindow : function (oWnd)
    {
        if (!oWnd) return;
        var w = this.getWindowByName(oWnd.get_name());
        var windows = this.get_windows();
        if (w) Array.remove(windows, w);
    },

    //---------------------------------------------------- Utility methods -------------------------------------------//
    _getUniqueId : function()
    {
        return "" + (new Date() - 100);
    },

    _initialize : function()
    {
        //Obtain window objects from the page and add them to the window collection
        var array = this._windowIDs;

        for (var i = 0; i < array.length; i++)
        {
            var windowID = array[i];
            var oWindow = $find(windowID);

            if (!oWindow) continue;

            //Set a reference in the window to the window manager!
            oWindow.set_windowManager(this);

            //Add to window collection
            this._windows[this._windows.length] = oWindow;
        }
    },

     _disposeWindows : function()
    {
       for (var i=0; i < this._windows.length; i++)
       {
            var t = this._windows[i];

            //Windows' dispose method will be called second time here - at least for the windows that originally existed on the page!
            //This can potentially lead to problems
            //So, dispose only windows that are cloned from the window manager and did not exists before
            if(t.isCloned()) t.dispose();
       }
       this._windows = [];
    },

     _createWindow : function(wndName, copyEventHandlers)
    {
        var wnd = this.clone(wndName, copyEventHandlers);
        this._windows[this._windows.length] = wnd;

        //Set a reference in the window to the window manager!
        wnd.set_windowManager(this);
	    return wnd;
    },

    _replaceLocalization : function(searchString, localizationHash)
	{
		var replacer = /##LOC\[(.*?)\]##/;
		while (searchString.match(replacer))
		{
			var replacement = localizationHash[RegExp.$1] ? localizationHash[RegExp.$1] : "";
			searchString = searchString.replace(replacer, replacement)
		}
		return searchString;
	},


    _getStandardPopup : function(popupType, popupText, initialContent)
    {
        //Set a more complex name to the window to FireFox causigng probs when the name of the window <iframe name = alert
        var newWnd = this._createWindow(popupType + this._getUniqueId(), false);

        //Set destroy on close = true
        newWnd.set_destroyOnClose(true);
        
        //NEW: Make it ignore restriction zone        
        newWnd.set_restrictionZoneID(null);

        //Set modal
        newWnd.set_modal(true);

        //Set a content element
        var div = document.getElementById(this.get_id() + "_" + popupType.toLowerCase() + "template");

        //STEP 1 - Replace the template {}
        var endString = this._stringFormat(
                             div.innerHTML,     //the original template content
                             newWnd.get_id(),   //the window ID (to get a reference to the window object)
                             popupText,         //the text to be displayed in the popup
                             initialContent ? initialContent : ""   //the initial content (in case of radprompt)
                            );

        //STEP 2 - Add Localization
        endString = this._replaceLocalization(endString, Sunny.Web.UI.RadWindowUtils.Localization);

        //STEP 3 - Set content
        var newDiv =  document.createElement("DIV");
        newDiv.innerHTML = endString;

        newWnd.set_behaviors(Sunny.Web.UI.WindowBehaviors.Close);
        newWnd.set_visibleStatusbar(false);
        newWnd.set_contentElement(newDiv);

        //NEW: Set focus
        var input = newWnd.get_contentElement().getElementsByTagName("INPUT")[0];

        //NEW: Allow the alert and confirm buttons (which are A elements to get focus as well)
        if (!input)
        {
            input = newWnd.get_contentElement().getElementsByTagName("A")[0];
        }

        if (input && input.focus)
        {
           window.setTimeout(function()
           {            
                //NEW: prompt causes IE7 to block in scenario where user would click outside the focused button and then close the prompt. When using setActive, rather than focus, all works fine
                //NEWER: When an alert is loaded with AJAX - e.g. RadAjaxManager1.ResponseScripts.Add there is an exception in IE when calling setActive - even though it is a valid call
                var setFocus = true;
                if (input.setActive)
                { 
                    try
                    {
                        input.setActive();
                        setFocus = false;
                    } catch(e){;}
                }                    
                if (setFocus) input.focus();                
            }, 0);
        }

        return newWnd;
    },

    _stringFormat : function(text)
     {
        for (var i = 1; i < arguments.length; i++)
        {
            text = text.replace(new RegExp("\\{" + (i - 1) + "\\}", "ig"), arguments[i]);
        }
        return text;
     },


    _registerAsPageManager : function()
    {
        var existingManager = Sunny.Web.UI.WindowManager.Manager;
        var myID = this.get_id();
        if (existingManager && existingManager.get_id() == myID)
        {
            //existing manager, not disposed
            existingManager.dispose();
            Sunny.Web.UI.WindowManager.Manager = null;
        }
        if (existingManager && !existingManager.get_id())
        {
            //existing manager, but already disposed
            Sunny.Web.UI.WindowManager.Manager = null;
        }

        if (!Sunny.Web.UI.WindowManager.Manager)
        {
            Sunny.Web.UI.WindowManager.Manager = this;
        }
    },

    //---------------------------------------------------- Save state -------------------------------------------//

    //Called by radwindow's dispose as it is called prior to radwindowmanager's dispose
    saveWindowState : function(oWnd)
    {
        //Skip if window is not created
        if (!oWnd || !oWnd.isCreated()) return;

	    var bounds = oWnd.getWindowBounds();
	    var oVal =
			       (oWnd.isVisible() || oWnd.isMinimized()) + "@" +
			       bounds.width + "@" +
			       bounds.height + "@" +
			       bounds.x + "@" +
			       bounds.y + "@" +
			       oWnd.isMinimized();
	    this._setRadWindowCookie(oWnd.get_id(), oVal);
    },


    saveState : function()
	{
		var oWnds = this.get_windows();
		for (i=0; i < oWnds.length; i++)
		{
			var oWnd = oWnds[i];
			//Save state only of windows that are cloned from RadWindowManager. The framework will take care of the others
		    if (oWnd.isCloned() ) this.saveWindowState(oWnd);
		}
	},

    restoreState : function()
    {
		function restoreWindow(oWnd, oStr)
		{
			var array = oStr.split("@");
			if (array.length > 1)
			{
				if ("true" == array[0] && !oWnd.isVisible()) oWnd.show();


				//If we set timeout to 0 there is problem in IE - it sometimes shows both the minimized window and the window itself
				//However, if it is > 0 then there is flickering on the screen.
				//TODO: Hopefully eventually there would be some good workaround for this
				window.setTimeout(function()
				{
					if(parseInt(array[1]) > 0) oWnd.set_width(array[1]);
					if(parseInt(array[2]) > 0) oWnd.set_height(array[2]);

					//If not visible, do not call moveTo
					if ("true" == array[0]) oWnd.moveTo(parseInt(array[3]), parseInt(array[4]));
					if ("true" == array[5])
					{
						oWnd.minimize();
					}
				}, 1);
			}
		};


		var oWnds = this.get_windows();

		for (i=0; i < oWnds.length; i++)
		{
			var oWnd = oWnds[i];
			var oStr = this._getRadWindowCookie(oWnd.get_id());

			if (oStr)
			{
				restoreWindow(oWnd, oStr);
			}
		}
    },

	_getOnlyCookie : function()
	{
		var sName = "RadWindowCookie";

		var aCookie = document.cookie.split("; ");
		for (var i=0; i<aCookie.length; i++)
		{
			var aCrumb = aCookie[i].split("=");
			if (sName == aCrumb[0]) return aCrumb[1];
		}
		return null;
	},

	_setRadWindowCookie : function(sName, sValue)
	{
		sName = "[" + sName + "]";
		var stringToSplit = this._getOnlyCookie();
		var begStr = "";
		var endStr = "";

		if (stringToSplit)
		{
			var array = stringToSplit.split(sName);
			if (array && array.length > 1)
			{
				begStr = array[0];
				endStr =array[1].substr(array[1].indexOf("#") + 1);
			}
			else endStr = stringToSplit;
		}

		var today = new Date();
		today.setFullYear(today.getFullYear() + 10);
		document.cookie = "RadWindowCookie" + "=" + (begStr + sName +"-" + sValue + "#" + endStr) + ";path=/;expires=" + today.toUTCString() + ";";
	},

	_getRadWindowCookie : function(sName)
	{
		var cook = this._getOnlyCookie();
		if (!cook) return;

		var sValue = null;
		sName = "[" + sName + "]";

		var index = cook.indexOf(sName);
		if (index >=0)
		{
			var endIndex = index + sName.length + 1;
			sValue = cook.substring(endIndex, cook.indexOf("#", endIndex));
		}
		return sValue;
	},

	//---------------------------------------------------- More public API -------------------------------------------//
    cascade : function()
    {
	    var oTop = 0;
	    var oLeft = 0;
	    var oArray = this._getWindowsSortedByZindex();

	    for (var i=0; i<oArray.length; i++)
	    {
		    var oWnd = oArray[i];
		    if (!oWnd.isClosed() && oWnd.isVisible())
		    {
			    var oRet = oWnd.restore();
			    oWnd.moveTo(oTop, oLeft);
			    oWnd.setActive(true);
			    oTop += 25;
			    oLeft += 25;
		    }
	    }
    },


    tile : function()
    {
	    var oArray = this._getWindowsSortedByZindex();
	    //Heuristic - let's say we have a maximum of 5 columns.
	    //Calculate the smallest number of rows that you need to fit the windows
	    var oLen = 0;
	    //Only the visible windows should be used
	    for (var i=0; i < oArray.length; i++)
	    {
		    var oWin = oArray[i];

		    if (!oWin.isClosed() && oWin.isVisible())
		    {
			    oLen++;
		    }
	    }

	    var oMaxCols = 5;
	    var oCols = 0;
	    var oRows = 1;

	    if (oLen <= oMaxCols)
	    {
		     oCols = oLen;
	    }
	    else
	    {
		    var i = 2;
		    //Try to get a heuristic by multiplying the (oLength * i) > (oMaxCols i-1)
		    while ((oLen * i) < (oMaxCols * (i+1)))
		    {
			    i++;
			    if (i > 6) break;//In case something goes wrong
		    }
		    oRows = i;
		    //Calculate cols
		    oCols = Math.ceil(oLen / oRows);
	    }


	    var oScreen = $Sunny.getClientBounds();

	    //See to what two-dimentional grid it correspends
	    var oWinWidth  = Math.floor(oScreen.width / oCols);
	    var oWinHeight = Math.floor(oScreen.height / oRows);
	    var left = document.documentElement.scrollLeft || document.body.scrollLeft;
		var top = document.documentElement.scrollTop || document.body.scrollTop;

	    var tiledWindowCount = 0;
	    for (var i = 0; i < oArray.length; i++)
	    {
		    var oWin = oArray[i];
		    if (!oWin.isClosed() && oWin.isVisible())
		    {
			    tiledWindowCount++;
			    if ( (tiledWindowCount-1) % (oCols) == 0 && tiledWindowCount > oCols)
			    {
				    top += oWinHeight;
				    left =  document.documentElement.scrollLeft || document.body.scrollLeft;
			    }

			    oWin.restore();
			    oWin.moveTo(left, top);
			    oWin.setSize(oWinWidth, oWinHeight);
			    left += oWinWidth;
		    }
	    }
    },

    closeActiveWindow : function()
    {
	    this._executeActiveWindow("close");
    },

    minimizeActiveWindow : function()
    {
	    this._executeActiveWindow("minimize");
    },

    restoreActiveWindow : function()
    {
	    this._executeActiveWindow("restore");
    },

    closeAll : function()
    {
	    this._executeAll("close");
    },

    showAll : function()
    {
	    this._executeAll("show");
    },

    minimizeAll : function()
    {
	    this._executeAll("minimize");
    },

    maximizeAll : function()
    {
	    this._executeAll("maximize");
    },

    restoreAll : function()
    {
	    this._executeAll("restore");
    },


    _getWindowsSortedByZindex : function()
    {
	    var oArray = this._windows.concat([]);//Clone the original array
	    var oSortFun = function(oWin1, oWin2)
	    {
	        var z1 = oWin1.get_zindex();
	        var z2 = oWin2.get_zindex();

	        if (z1 == z2) return 0;
		    return (z1 < z2 ? -1 : 1);
	    };

	    return oArray.sort(oSortFun);
    },

    _executeAll : function(fnName)
    {
	    if (!this._windows) return;

	    var oArray = this._windows.concat([]);
	    for (var i=0; i < oArray.length; i++)
	    {
		    oArray[i][fnName]();
	    }
    },

    _executeActiveWindow : function(cmdName)
    {
        var activeWindow = this.getActiveWindow();
	    if (activeWindow && "function" == typeof(activeWindow[cmdName]))
	    {
		    activeWindow[cmdName]();
	    }
    },

    //---------------------------------------------------- Properties methods -------------------------------------------//
    get_preserveClientState : function()
    {
        /// <summary>
        /// Gets the value indicating whether window objects' state (size, location, behavior) will be persisted in a client cookie to restore state over page postbacks.
        /// </summary>
        /// <value type="bool">
        /// The current setting
        /// </value>
        return this._preserveClientState;
    },

    set_preserveClientState : function(value)
    {
        /// <summary>
        /// Sets a value indicating whether window  objects' state (size, location, behavior) will be persisted in a client cookie to restore state over page postbacks.
        /// </summary>
        /// <param name="value" type="bool">
        /// The new value
        /// </param>

        //Set the value
        if (this._preserveClientState != value)
        {
            this._preserveClientState = value;
        }
    },


    //Called by the server to initialize the WindowManager
    set_windowControls : function(value)
    {
        /// <exclude/>
        //It must come in the form of strings
        this._windowIDs = eval(value);

        //Dispose all [old] windows (if any);
        this._disposeWindows();
    },

    //Needed by the framework to propery call the set_windowControls!
    get_windowControls : function()
    {
        /// <exclude/>
    },

    get_windows : function()
    {
        return this._windows;
    }
}

Sunny.Web.UI.RadWindowManager.registerClass('Sunny.Web.UI.RadWindowManager', Sunny.Web.UI.RadWindow);

if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();