/* Data structure to capture item-specific configuration options, such as the
   URL for item context lookups (e.g. document contexts) and references 
   to JS functions to be called when a specific menu item is selected. When
   an action_function is not defined for a menu item, the menu item's href
   link will be followed as usual.
*/
var item_info = {
  "kdoc": {
      "context_url": "/apps/org/workgroup/portal/lookup_document_context.php",
      "action_functions" : {
          "lock": _documentLockModalDialog,
          "unlock": _documentUnlock
      }
  },
  "kfolder": {
      "context_url": "/apps/org/workgroup/portal/lookup_folder_context.php",
      "action_functions" : {
          "archivefolder": _folderArchive,
          "unarchivefolder": _folderUnarchive
      }
  }   
};

////////////////////////////////////////////////////////////////////////////
// Item-specific functions: these apply to one particular item type only. //
////////////////////////////////////////////////////////////////////////////

function _toggleDocumentLockInfo(document_id, is_locked, lock_note) {
    var doc_icon_imgs = $("[id='kdoc_" + document_id + "'] img.kdocicon",
                          "div#content div#main");
    doc_icon_imgs.each(function() {
        var img_src = $(this).attr('src');

        if (is_locked) {
            // Add "_locked" suffix to file name *before* extension
            img_src = img_src.replace(/(.*)(\..*)/, "$1_locked$2");

            // Add lock details to the details flyout, after removing any
            // existing lock info
            $("tbody#kdoc_" + document_id + " tr.docdetails ul.meta li.lock").remove();
            $("tbody#kdoc_" + document_id + " tr.docdetails ul.meta").append("<li class='lock'>Just locked by you with note \"" + lock_note + "\"</li>");
        } else {
            // Removed "_locked" suffix from file name
            img_src = img_src.replace(/(.*)(_locked)(\..*)/, "$1$3");

            // Remove lock info from details flyout
            $("tbody#kdoc_" + document_id + " tr.docdetails ul.meta li.lock").remove();
        }

        $(this).attr('src', img_src);
    });
}

function _documentLockModalDialog(kmenu_container, item_type, item_id, item_href) {
    // Initialize the modal window and add the lock form
    initModal();
    
    var doc_name = $("a[class^='kdoc_']", kmenu_container).text();
    var modalHeading = "You are locking " + doc_name;
    var modalBody = 
        "<form action='' method='post' name='lock' id='lock'>" +
            "<div>" +
                "<input type='hidden' name='document_id' id='document_id' " + 
                    "value='" + item_id + "'>" +
                "<label for='note'>" + 
                    "Enter a message that describes why you are locking this file" + 
                "</label>" +
                "<textarea name='note' id='note'></textarea>" +
            "</div>" +
            "<div class='submit'>" +
                "<input type='submit' value='Lock' name='locksubmit' id='locksubmit'>" +
                "<a href='#' class='cancel'>Cancel</a>" +
            "</div>" +
        "</form>";
    displayModal(false, modalHeading, modalBody);
    
    // Set the focus on the textarea message field
    $("textarea#note", "div.modal div.body").focus();
    
    // Event handler for submit of lock form .
    $("div.modal div.body form#lock").submit(function() {
        // Submit lock POST request upon form submit
       var lock_note = $("textarea#note", $(this)).val();
        var params = {
            'format': 'json',
            'document_id': item_id,
            'lock': 1,
            'lock_note': lock_note
        };
        jQuery.ajax({
            type: "POST",
            url: item_href,
            data: params,
            dataType: "json",
            success: function(post_results, textStatus) {
                if (post_results.success) {
                    _toggleDocumentLockInfo(item_id, post_results.locked,
                                            lock_note);
                }
                initModal();
                displayModal(true, "Lock", "<p>" + post_results.message + "</p>");
            },
            error: function(XMLHttpRequest, textStatus, errorThrown) {
                displayModal(true, "Error", "<p>" + textStatus + "</p>");
            }
        });
        killModal();
        return false;  // Prevent a page reload after the form's submit
    });
}

function _documentUnlock(kmenu_container, item_type, item_id, item_href, ondone_f) {            
    initModal();    
    var params = {
        'format': 'json',
        'document_id': item_id,
        'unlock': 1
    };
    jQuery.ajax({
        type: "POST",
        url: item_href,
        data: params,
        dataType: "json",
        success: function(post_results, textStatus) {
            if (post_results.success) {                    
                _toggleDocumentLockInfo(item_id, post_results.locked, "");
            }
            displayModal(true, "Unlock", "<p>" + post_results.message + "</p>");
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            displayModal(true, "Error", "<p>" + textStatus + "</p>");
        }
    });        
}

function _folderArchiveToggle(kmenu_container, item_type, item_id, item_href, ondone_f, action) {
    initModal();
    var params = {
        'format': 'json',
        'folder_id': item_id,
        'action': action
    };
    jQuery.ajax({
        type: "POST",
        url: item_href,
        data: params,
        dataType: "json",
        success: function(post_results, textStatus) {
           displayModal(true, "Folder " + action + "d", 
               "<p>" + post_results.message + "</p>");
           if (post_results.success) {
              var folder_archived_span = $(
                "[id^='kfolder_" + item_id + "'] h3 span", "div#content div#main");
              if (action == 'archive') {
                 folder_archived_span.show();
              } else {
                 folder_archived_span.hide();
              }
           }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            displayModal(true, "Error", "<p>" + textStatus + "</p>");
        }
    });
}

function _folderArchive(kmenu_container, item_type, item_id, item_href, ondone_f) {
    _folderArchiveToggle(kmenu_container, item_type, item_id, item_href, ondone_f, 'archive');
}

function _folderUnarchive(kmenu_container, item_type, item_id, item_href, ondone_f) {
    _folderArchiveToggle(kmenu_container, item_type, item_id, item_href, ondone_f, 'unarchive');
}

////////////////////////////////////////////////////////
// Generic action menu functions: apply to all menus. //
////////////////////////////////////////////////////////

function initModal(){
    // Initialize the modal window container
    $("div#main", "div#content").append("<div class='modal'>" +
        "<div class='header'>" +
        "<a href='#' class='cancel'>Close</a>" +
        "<h4>Modal Window</h4>" +
        "</div>" +
        "<div class='body'>" +
        "</div>" +
        "</div>" + 
        "<div class='mask'></div>"
    );
    // Position the modal window
    modalWindow = $("div.modal", "div#main");
    xPos = ($(window).width() * 0.5) - (modalWindow.width() * 0.5);
    yPos = (($(window).scrollTop() + ($(window).height() * 0.5)) - (modalWindow.width() * 0.5));
    modalWindow.css("left", xPos);
    modalWindow.css("top", yPos);

    // Resize the background mask
    $("div.mask").css("height", $(document).height());
    $("div.mask").css("width", $(window).width());

    // On window resize, resize the background mask and resposition the modal window
    $(window).bind('resize', function() {
        $("div.mask").css("height", $(document).height());
        $("div.mask").css("width", $(window).width());
        xPos = ($(window).width() * 0.5) - (modalWindow.width() * 0.5);
        yPos = (($(window).scrollTop() + ($(window).height() * 0.5)) - (modalWindow.width() * 0.5));
        modalWindow.css("left", xPos);
        modalWindow.css("top", yPos);
    });
}

function displayModal(addOkButton, heading, body) {
    // Add meaningful header and body content to the modal window
    $("div.header h4", "div.modal").text(heading);
    if (addOkButton) {
        body += "<div class='submit'>"
              + "<input class='cancel' type='submit' value='OK' name='OK' id=''>" 
              + "</div>";
    }
    $("div.body", "div.modal").append(body);    

    // Display the modal window
    $("div.modal", "div#main").fadeIn();
    $("div.mask", "div#main").fadeIn();

    attachCancelModalWindowHandler();    
}

// Hide the modal window and remove the elements from the DOM
function killModal(){
    $("div.modal", "div#main").fadeOut();
    $("div.mask", "div#main").fadeOut();
    $("div.modal", "div#main").remove();
    $("div.mask", "div#main").remove();
}

// Cancels a modal window upon ESC, or click of cancel link / close button
function attachCancelModalWindowHandler() {
    // Attach window cancel handler to modal dialog
    $("div.modal .cancel").click(function(){
        killModal();
        return false;
    });

    // ESC button pressed while modal window was active
    $(document).keyup(function(event){
        if (event.keyCode == 27) {
            killModal();
            return false;
        }
    });    
}

// Parses the type string and numeric ID portion of a menuable item's 'id' 
// attribute, based on the assumption that this attribute contains a 
// string in the format "type_numericid", for example 'kdoc_123'
function parseItemTypeAndId(id_string) {
    if (!id_string || id_string.search('_') < 0) {
        return false;
    }    
    return id_string.split('_');
}

// Returns any context information associated with this item.
function getItemContext(item_type, item_id) {
    var itemElem =
        $("[id='" + item_type + "_" + item_id + "']", "div#content div#main");
    var spanElems = itemElem.find("span.itemcontext:first");
    return spanElems.text();
}

// Toggle visiblity of action menu
// Note that $.browser is deprecated as of jquery 1.3
function hideShowContextualMenuHandler(ul_container) {
    if (ul_container.hasClass("expand")) {
        ul_container.removeClass("expand");
        if ($.browser.msie) {
          $("ul.nav-actions").removeClass("forceIndex");
        }
    }
    else {
        // Un-expand any other menus that may have been clicked previously
        $("ul.nav-actions li ul").removeClass("expand");
        ul_container.addClass("expand");
        if ($.browser.msie) {
          ul_container.parents("ul").addClass("forceIndex");
        }
    }
}

// Handle a selection from an item's menu.
function menuActionClickHandler() {
    
    var kmenu_container = $(this).parents(".kmenuable")[0]

    hideShowContextualMenuHandler($(this).parents("ul"));

    // Find the item's type and ID       
    var id_string = $(this).parents(".kmenuable").attr("id");
    var typeAndId = parseItemTypeAndId(id_string);
    var item_type = typeAndId[0];
    var item_id = typeAndId[1];
    
    // Lookup item-specific action function, if any special ones defined (in 
    //    array at top of file).
    var action_type = $(this).attr("class");
    var action_function = item_info[item_type].action_functions[action_type];
    if (action_function) {
        // Invoke item-specific action function.
        action_function(kmenu_container, item_type, item_id, $(this).attr("href"));
        return false; // Do not follow this item's link.
    } else {
        // No item-specific action function, follow menu item's link as normal.
        return true;        
    }
}

// Populate the contents of the Javascript action menu for a given 
// kmenu_container using information in the given array of action objects.
// Each action object must be a dictionary containing 'label', 'type' and 
// 'action_url' keyed values.
function populateActionMenu(ul_container, actions) {
    ul_container.parent().find(">a").removeClass("fetch");

    // Build LI item to represent each action) entry.
    html_str = "";
    for (actionref in actions) {
        var action = actions[actionref];
        html_str += "<li><a class='" + action.type + "' ";
        html_str += "href='" + action.action_url + "' ";
        html_str += ">" + action.label + "</a></li>";
    }

    // Insert action items' LI representation into menu. 
    ul_container.append(html_str);

    // Attach handler for menu actions
    $("li a", ul_container).click(menuActionClickHandler);
}

// Lookup context information for one or more items of a given type, then
// populate the corresponding menu in the DOM.
function lookup_context_and_refresh_menu(item_type, item_id, item_context, ul_container) {
    // Determine the contex lookup URL for this item
    var context_url = item_info[item_type].context_url;

    // Clear out any existing action menu contents.
    ul_container.empty();

    data_arr = {};
    data_arr['item_ids'] = item_id;
    data_arr['context']  = item_context
    // Lookup the item's context
    jQuery.ajax({
        type: "GET",
        url: context_url,
        data: data_arr,
        dataType: "json",
        success: function(context_result, textStatus) {
            if (context_result.success) {
                for (var myid in context_result.items) {
                    if (!context_result.items[myid].actions.length) {
                        ul_container.append("<li><a>You have no actions to perform on this object</a></li>");
                        ul_container.parent().find(">a").removeClass("fetch");
                    } else {
                        var actions = new Array();
                        for (var myaction in context_result.items[myid].actions) {
                            var item_action = context_result.items[myid].actions[myaction];
                            actions.push(item_action);
                        }
                        // build and fill in these actions in the items action menu
                        populateActionMenu(ul_container, actions);
                    }
                }
            }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            hideShowContextualMenuHandler(ul_container);
            initModal();
            displayModal(true, "Error", "<p>" + textStatus + "</p>");
        }
    });
}

// On click:
// Parse the item info from its id
// Dispatch to lookup_context_and_refresh_menu which will make the ajax
// call to get the menu items and fill them in the markup
function actionMenuOnClickHandler(evt) {
    var evt = jQuery.event.fix(evt);
    var clickee = $(evt.target);
    var parent_ul = clickee.parents("ul.nav-actions");
    var ul_container = $("+ ul", clickee);

    if (!ul_container.hasClass("expand")) {
        // Display a spinner to indicate the AJAX call is in progress
        clickee.addClass("fetch");
        hideShowContextualMenuHandler(ul_container);

        var id_string = clickee.parents(".kmenuable").attr("id");
        var typeIdContext = parseItemTypeAndId(id_string);
        var item_type = typeIdContext[0];
        var item_id = typeIdContext[1];
        var item_context = getItemContext(item_type, item_id);
        lookup_context_and_refresh_menu(item_type, item_id,
                                        item_context, ul_container);
    }
    else {
        hideShowContextualMenuHandler(ul_container);
    }
    // Forcibly stop event propagation
    evt.stopPropagation();
    return false;
}

// Add an 'active' class to every ul with the 'nav-actions' class inside the given
// root element, and replace any existing content with the menu representation.
function initActionMenuContent(root_element) {
    root_element.find("ul.nav-actions")
        .addClass("active")
        .html("<li class='toggleactions'><a href='#'>Actions</a><ul></ul></li>");
}

// Attach an onClick event handler to every ul with the 'nav-actions' class inside
// the given root element
function initActionMenuHandler(root_element) {
    root_element.find("ul.nav-actions li.toggleactions > a")
        .click(function(e) {
            return actionMenuOnClickHandler(e);
        });
}

/*
==============================================================================
To initialize action menus on a page you can use one of the following methods.

(1) 
Seed your HTML page with action menu stubs friendly to non-JS browsers:

<ul class='nav-actions active'>
  <li><a href="1">Plain links to display in place of...</a></li>
  <li><a href="2">... action menus for non-JS browsers</a></li>
</ul>

Then invoke the action menu initialization functions on page load, like so:
 
$(document).ready(function() {
    // Replace non-JS links with dynamic action menu
    initActionMenuContent($("div#main"));
    
    // Bind onClick handler to action menu
    initActionMenuHandler($("div#main"));
});

(2)
Alternately, if you are sure that the browser supports Javascript you can 
create pre-rendered action menus directly in HTML like so:

<ul class='nav-actions active'>
  <li class='toggleactions'>
    <a href='#' onclick='actionMenuOnClickHandler(event)'>Actions</a>
    <ul></ul>
  </li>
</ul>

==============================================================================
*/
