/*
    Every page with navigation includes this file
*/
var Navigator = new Object();

var MenuType = 
{
    None: 0,
    Button: 1,
    Tree: 2,
    Page: 4,
    Tab: 8,
    Main: 16,
    Dropdown: 32
};

var MenuTypeId = 
{
    0: "None",
    1: "Button",
    2: "Tree",
    4: "Page",
    8: "Tab",
    16: "Main",
    32: "Dropdown"
}

// ==================================================
// Information
// ==================================================
Navigator.GetFilterType = function()
{
    if (window.Filter != null) return Filter.Type;
    else return "";
}

// ==================================================
// Active functions
// ==================================================
Navigator.OpenId = function(menuitemId)
{
    menuitem = Navigator.Menuitems[menuitemId];
    
    if (menuitem == null){
        if (this.Parent != null){
            this.Parent.OpenId(menuitemId);
        } else {
            alert("unable to open menuitem '" + menuitemId + "'");
        }
    } else {
        this.Open(menuitem);
    }
}

Navigator.Open = function(menuitem)
{
    //check if the menuitem is a button
    if (menuitem.Type == "Button"){
        // open in popup
        Projector.OpenPopupDocument(this.GetUrl(menuitem));
        return;
    }
    
    if ((menuitem.Owner == null && this.RootId == "main") || (menuitem.Owner != null && menuitem.Owner.Id == this.RootId)){
        var url = this.GetUrl(menuitem);
        // This navigator can open the menuitem directly
        if (url != null){
            Projector.OpenUrl(url);       
        } else if (menuitem.Children != null && menuitem.Children.length > 0) {
            // open first child
            this.Open(menuitem.Children[0]);
        }
    } else {
        // link is inside this hierarchy branch
        if (this.Menuitems[menuitem.Id] != null){ 
            var subitemId = menuitem.Id;
            
            // find the correct ascendent for this projector
            while (!((menuitem.Owner == null && this.RootId == "main") || (menuitem.Owner != null && menuitem.Owner.Id == this.RootId)))
            {
                if (menuitem.Owner != null)
                {
                    menuitem = menuitem.Owner;
                } else
                {
                    alert("Unable to open menuitem '" + menuitem.Id + "', wrong navigator.");
                    return;
                }
            }
        
            // open ascendent
            var url = this.GetUrl(menuitem);
            if (url.indexOf("?") == -1) url += "?page=" + subitemId;
            else url += "&page=" + subitemId;
            
            Projector.OpenUrl(url);
            
        // link is out side this branch of the hierarchy
        } else {
            alert("outside branch");
            this.Parent.Open(menuitem);
        }
    }
}

Navigator.OpenHome = function()
{
    if (this.RootId == 'main'){
        this.Open(this.Hierarchy[0]);
    } else {
        this.Parent.OpenHome();
    }
}

Navigator.GetUrl = function(menuitem){
    if (menuitem.IsOwner == true) return "./menuitem.htm?id=" + menuitem.Id;
    else if (menuitem.DocumentUrl != null) return menuitem.DocumentUrl;
}

Navigator.GetDeepLink = function(menuitem)
{
    if (menuitem == null) return 'index.htm';
    return 'index.htm?page=' + menuitem.Id;
}

// ==================================================
// Initialization functions
// ==================================================
Navigator.Init = function(htmlObject, id, isRoot)
{
    // determine identifier
    this.HtmlObject = htmlObject;
    this.Id = id;
    this.IsRoot = (isRoot === true);
    
    if (isRoot === true)
    {
        // this navigator is the root
        this.RootId = GetURLParam("id");
    
        if (this.RootId == ""){
            // main root
            this.RootId = "main";
            this.Hierarchy = window.Hierarchy;
            this.Menuitems = window.Menuitems;
            this.MenuTypes = this.GetMenuTypes(this.Hierarchy);
            this.MainMenuType = this.GetMainMenuType();
        } else {
            // the root is a node inside the menu
            
            // determine root menuitem
            this.Root = window.Menuitems[this.RootId];
            
            // determine navigation types
            this.MenuTypes = this.GetMenuTypes(this.Root.Children);
            this.MainMenuType = this.GetMainMenuType();            

            // use the root is a child menuitem if it has content
            if (this.Root.DocumentUrl != null){
                this.Split(this.Root, this.MainMenuType);
            }
            
            // Get Hierarchy
            this.Hierarchy = this.Root.Children;          
            this.Menuitems = UnfoldMenu(this.Hierarchy);
        }
    } else 
    {
        this.RootId = GetURLParam("id");
        if (this.RootId == null) alert("No root identifier for navigator found!");
        
        // determine parent
        if (window.parent != null && window.parent != window && window.parent.Navigator != null)
        {
            this.Parent = window.parent.Navigator;
        } else if (window.opener != null && window.opener.Navigator != null)
        {
            this.Parent = window.opener.Navigator;
        }
        
        // determine root menuitem
        if (this.Parent != null) this.Root = this.Parent.Menuitems[this.RootId];
        else this.Root = window.Menuitems[this.RootId];
        
        // determine navigation types
        this.MenuTypes = this.GetMenuTypes(this.Root.Children);
        this.MainMenuType = this.GetMainMenuType();
        
        // use the root is a child menuitem if it has content
        if (this.Root.DocumentUrl != null) this.Split(this.Root, this.MainMenuType);
        
        // Get Hierarchy
        this.Hierarchy = this.Root.Children;
        this.Menuitems = UnfoldMenu(this.Hierarchy);
    }
    
    this.OnLoad = new Event();
    this.OnDocumentLoad = new Event();
       
    // Create the navigation
    this.Show();
    
    // Open Default menuitem
    this.ActiveMenuitem = null;
    this.OpenDefaultMenuitem();
}

Navigator.Show = function()
{
    var content = "";
    
    
    content += '<div id="' + this.Id + '_projector" class="projector"></div>';
    rightContent = "";
    
    for (var key in MenuType){
        if ((this.MenuTypes & MenuType[key]) != 0) {
            if (key == "Button" || key == "Tree"){
                rightContent += '<div id="' + this.GetMenuId(key) + '" class="'+ key.toLowerCase() + 'Menu"></div>';
            } else {
                content += '<div id="' + this.GetMenuId(key) + '" class="'+ key.toLowerCase() + 'Menu"></div>';
            }
        }
    }
    
    if (rightContent != "") content += '<div id="' + this.GetMenuId("right") + '" class="rightMenu">' + rightContent + '</div>';
    
    this.HtmlObject.innerHTML = content;
    
    Projector.Init("projector", document.getElementById(this.Id + "_projector"));
    
    for (var key in MenuType){
        if ((this.MenuTypes & MenuType[key]) != 0){
            window[key + "Menu"].Init(document.getElementById(this.GetMenuId(key)));
        }
    }
    
    this.SizeMenus();
}

Navigator.GetMenuId = function(name)
{
    return this.Id + '_' + name.toLowerCase() + 'Menu';
}

/*
    Size all menus to fit the navigator container correctly
*/
Navigator.SizeMenus = function()
{
    var projector = document.getElementById(this.Id + "_projector");
    projector.style.left = "0px";
    projector.style.right = "0px";
    projector.style.top = "0px";
    projector.style.bottom = "0px";

    // size main menu
    if ((this.MenuTypes & MenuType.Main) != 0)
    {
        var mainMenu = document.getElementById(this.GetMenuId("main"));
        
        if (MainMenu.CountRelevant() > 1){
            mainMenu.style.top = "0px";
            mainMenu.style.bottom = "0px";
            mainMenu.style.width = String(mainMenu.offsetWidth) + "px";
            projector.style.left = String(mainMenu.offsetWidth) + "px";
        } else { // don't show main menu if there is only one item inside it
            mainMenu.style.display = "none";
        }
    }
    
    // size tab menu
    if ((this.MenuTypes & MenuType.Tab) != 0)
    {
        var tabMenu = document.getElementById(this.GetMenuId("tab"));
        
        tabMenu.style.top = "0px";
        tabMenu.style.left = "0px";
        tabMenu.style.right = "0px";
        projector.style.top = String(tabMenu.offsetHeight) + "px";
    }
    
    // size tab menu
    if ((this.MenuTypes & MenuType.Dropdown) != 0)
    {
        var dropdownMenu = document.getElementById(this.GetMenuId("dropdown"));
        
        dropdownMenu.style.top = "0px";
        dropdownMenu.style.left = "0px";
        dropdownMenu.style.right = "0px";
        projector.style.top = String(dropdownMenu.offsetHeight) + "px";
    }    
    
    // size tab menu
    if ((this.MenuTypes & MenuType.Page) != 0)
    {
        var pageMenu = document.getElementById(this.GetMenuId("page"));
        
        pageMenu.style.bottom = "0px";
        pageMenu.style.left = "0px";
        pageMenu.style.right = "0px";
        projector.style.bottom = String(pageMenu.offsetHeight) + "px";
    }    
    
    // size tree menu
    if ((this.MenuTypes & MenuType.Tree) != 0)
    {
        var rightMenu = document.getElementById(this.GetMenuId("right"));
        
        rightMenu.style.top = "0px";
        rightMenu.style.bottom = "0px";
        rightMenu.style.right = "0px";
        rightMenu.style.width = "auto";
        projector.style.right = String(rightMenu.offsetWidth) + "px";
    }
}

Navigator.ResizeButtonMenu = function()
{
    var projector = document.getElementById(this.Id + "_projector");
    var rightMenu = document.getElementById(this.GetMenuId("right"));
    
    if (ButtonMenu.Buttons.length == 0 && ((this.MenuTypes & MenuType.Tree) == 0)){
        rightMenu.style.display = "none";
        projector.style.right = "0px";
    } else {
        rightMenu.style.display = "";
        rightMenu.style.top = "0px";
        rightMenu.style.bottom = "0px";
        rightMenu.style.right = "0px";
        rightMenu.style.width = "auto";
        projector.style.right = String(rightMenu.offsetWidth) + "px";
    }
}
Navigator.ResizeTabMenu = function()
{
    var projector = document.getElementById(this.Id + "_projector");
    var tabMenu = document.getElementById(this.GetMenuId("tab"));
    var rightMenu = document.getElementById(this.GetMenuId("right"));
    
    projector.style.top = String(tabMenu.offsetHeight) + "px";
    if (rightMenu != null) rightMenu.style.top = String(tabMenu.offsetHeight) + "px";
}


Navigator.OpenDefaultMenuitem = function()
{
    var requestedId = GetURLParam("page");

    if (this.Menuitems[requestedId] != null)
    {
        // open requested menuitem
        this.Open(this.Menuitems[requestedId]);
    } else
    {
        // open default menuitem
        this.Open(this.Hierarchy[0]);
    }
}

/*
    returns a set of all menu types that are used in this navigator
*/
Navigator.GetMenuTypes = function(menuitems)
{
    var result = MenuType.None;
    
    if (menuitems == null) menuitems = this.Hierarchy;
    
    for(var i in menuitems){
        var type = menuitems[i].Type;
        
        if (type != "Button" && type != "None") result |= MenuType[type];
    }
    
    // check seperately for buttons
    if (ButtonMenu.HasRelevant(menuitems)) result |= MenuType.Button;
       
    return result;
}

/*
    returns the dominant MenuType
*/
Navigator.GetMainMenuType = function()
{
    var result = MenuType.None;
    
    for (key in MenuType){
        if ((this.MenuTypes & MenuType[key]) != 0 && MenuType[key] > result) result = MenuType[key];
    }
    
    return result;
}

Navigator.Split = function(menuitem, subtype)
{
    if (menuitem.Children == null) menuitem.Children = new Array();
    menuitem.Children.unshift({
        Id: menuitem.Id, 
        Type: MenuTypeId[subtype], 
        Title: menuitem.Title, 
        IsOwner: "false",
        Parent: menuitem,
        Owner: menuitem,
        DocumentId: menuitem.DocumentId,
        DocumentUrl: menuitem.DocumentUrl,
        Properties: menuitem.Properties
    });
    
    // remove content from the root
    menuitem.DocumentId = null;
    menuitem.DocumentUrl = null;
    menuitem.IsOwner = true;
}

// ==================================================
// Tool functions
// ==================================================
function UnfoldMenu(menuitems, unfolded)
{
    if (menuitems == null) return;
    
    if (unfolded == null) unfolded = new Object();

    for (var i = 0; i < menuitems.length; i++)
    {
        var item = menuitems[i];
        if (unfolded[item.Id] == null) unfolded[item.Id] = item;
        UnfoldMenu(item.Children, unfolded);
    }
    
    return unfolded;
}

function GetURLParam(name)
{
    var regexS = "[\\?&]" + name + "=([^&#]*)";
    var regex = new RegExp(regexS);
    var result = regex.exec(window.location.href);

    if (result == null)
    {
        return "";
    } else
    {
        return result[1];
    }
}

// ==================================================
// Events
// ==================================================
/*
    activated whenever a new page loads in the projector
*/
Navigator.ProjectorLoad = function(menuitemId, opened, contentObject/* body of the loaded document */){
    var menuitem = this.Menuitems[menuitemId];

    if (menuitem == null)
    {
        alert("Unknown menuitem '" + menuitemId + "' loaded. " + this.RootId);
        return;
    }
    
    if (opened === true){
        this.ActiveMenuitem = menuitem;
    } else {
        this.ActiveMenuitem = null;
    }

    // menuitem is loaded in current projector
    this.OnLoad.Trigger([menuitem, opened]);

    if (menuitem.DocumentUrl != null || opened !== true)
    {
        // document is loaded
        this.OnDocumentLoad.Trigger([menuitem, opened, contentObject]);

        if (this.Parent != null)
        {
            this.Parent.ChildLoad(menuitem, opened, contentObject);
        }
    }
}

Navigator.ChildLoad = function(menuitem, opened, contentObject)
{
    // document is last in the line
    this.OnDocumentLoad.Trigger([menuitem, opened, contentObject]);    

    if (this.Parent != null){
        this.Parent.ChildLoad(menuitem, opened, contentObject);
    }
}
