﻿// - ItkWindowManager has the ability to act as factory for ItkWindow objects
// - Provides the radwindow, radprompt, radconfirm and radopen methods
// - Stores windows' state
Type.registerNamespace('ITkey.Web.UI');
Type.registerNamespace('ITkey.Web.UI.WindowManager');

//Backward compatibility function - it needs the existance of a ItkWindowManager
//It returns the first registered manager on the page
function GetItkWindowManager()
{
    return ITkey.Web.UI.WindowManager.Manager;
}

window.radalert = function(text, oWidth, oHeight, oTitle)
{
    var oManager = GetItkWindowManager();
	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 = GetItkWindowManager();
	var oWnd = oManager._getStandardPopup("confirm", text);

	if (typeof(oTitle) != 'undefined')
	{
		oWnd.set_title(oTitle)
	}
	oWnd.setSize(oWidth ? oWidth : 280 , oHeight ? oHeight : 200);

	oWnd.callBack = function(result)
	{
	    if (callBackFn) callBackFn(result);
	    oWnd.close();
	    oWnd.callBack = null;
	};

	//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 = GetItkWindowManager();

	var oWnd = oManager._getStandardPopup("prompt", text, initialValue);

	if (typeof(oTitle) != 'undefined')
	{
		oWnd.set_title(oTitle)
	}
	oWnd.setSize(oWidth ? oWidth : 280 , oHeight ? oHeight : 200);

	oWnd.callBack = function(result)
	{
	    if (callBackFn) callBackFn(result);
	    oWnd.close();
	    oWnd.callBack = null;
	};

	//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 && $ITkey.isIE)
	{	
	    var input = oWnd.get_popupElement().getElementsByTagName("INPUT")[0];
	    if (input) input.value = initialValue;    
	}
	
	return oWnd;
}

window.radopen = function(url, name)
{
    var oManager = GetItkWindowManager();
    return oManager.open(url, name);
}

//-------------------------------------------------------------//
ITkey.Web.UI.ItkWindowManager = function(element)
{
    /// <exclude/>
    ITkey.Web.UI.ItkWindowManager.initializeBase(this, [element]);
    this._windowIDs = [];
    this._windows = [];
    this._preserveClientState = false;

    //TODO:
    //this._singleNonMinimizedWindow = 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;
}

ITkey.Web.UI.ItkWindowManager.prototype =
{
    //NEW
    get_zIndex : function()
    {
        /// <exclude />
        return ITkey.Web.UI.ItkWindowUtils._zIndex;
    },

    set_zIndex : function(value)
    {
        var zIndex = parseInt(value);
        if (isNaN(value)) return;
        ITkey.Web.UI.ItkWindowUtils._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;
        ITkey.Web.UI.ItkWindowManager.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);
	    }

	    if(url) oWnd.setUrl(url);

	    oWnd.show();

	    return oWnd;
    },


    getActiveWindow : function()
    {
        return ITkey.Web.UI.ItkWindowController.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);

        //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, ITkey.Web.UI.ItkWindowUtils.Localization);

        //STEP 3 - Set content
        var newDiv =  document.createElement("DIV");
        newDiv.innerHTML = endString;

        newWnd.set_behaviors(ITkey.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
                if (input.setActive) input.setActive();
                else 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 = ITkey.Web.UI.WindowManager.Manager;
        var myID = this.get_id();
        if (existingManager && existingManager.get_id() == myID)
        {
            //existing manager, not disposed
            existingManager.dispose();
            ITkey.Web.UI.WindowManager.Manager = null;
        }
        if (existingManager && !existingManager.get_id())
        {
            //existing manager, but already disposed
            ITkey.Web.UI.WindowManager.Manager = null;
        }

        if (!ITkey.Web.UI.WindowManager.Manager)
        {
            ITkey.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._setItkWindowCookie(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 ItkWindowManager. 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._getItkWindowCookie(oWnd.get_id());

			if (oStr)
			{
				restoreWindow(oWnd, oStr);
			}
		}
    },

	_getOnlyCookie : function()
	{
		var sName = "ItkWindowCookie";

		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;
	},

	_setItkWindowCookie : 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 = "ItkWindowCookie" + "=" + (begStr + sName +"-" + sValue + "#" + endStr) + ";path=/;expires=" + today.toUTCString() + ";";
	},

	_getItkWindowCookie : 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 = 40;
	    var oLeft = 40;

	    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 = $ITkey.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;
    }
}

/*
//TODO, Related to _singleNonMinimizedWindow property
MinimizeInactiveWindows = function()
{
	var activeWnd = this.ActiveWindow;
	var theArray = this._windows;
	var oLength = theArray.length;
	for (var i=0; i < oLength; i++)
	{
		var oWin = theArray[i];
		if (oWin != activeWnd) oWin.Minimize();
		//else oWin.Restore();
	}
},
*/
ITkey.Web.UI.ItkWindowManager.registerClass('ITkey.Web.UI.ItkWindowManager', ITkey.Web.UI.ItkWindow);

if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();