// Utility library for common CMS javascript functions.
dojo.require("dojo.dom");
dojo.require("dojo.event");
dojo.require("dojo.io");
// For floating-window widget.
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.TaskBar");
dojo.require("dojo.widget.LayoutContainer");
dojo.require("dojo.widget.FloatingPane");
dojo.require("dojo.widget.ResizeHandle");

//*********************************************************************************************
//* Generic Library Functions
//*********************************************************************************************

/**
 * Shorthand function for returning an element by id.
 * @elementId - String id which identifies the given element within the document.
 */
function $(elementId) {
    return document.getElementById(elementId);
}

/**
 * Returns the selected option element from a select box.
 * @elSelectBox - The select element.
 */
function selectedItem(elSelectBox) {
    var i = elSelectBox.selectedIndex;
    return elSelectBox.options[i];
}


//*********************************************************************************************
//* Floating Window
//*********************************************************************************************

function showFloatingWindow( elementId, title, contentUrl, width, height, left ){
    var properties = {
            hasShadow: true,
            displayMinimizeAction: false,
            displayMaximizeAction: false,
            displayCloseAction: true,
            href: contentUrl,
            executeScripts: true,
            title: title,
            titleHeight: "20",
            id: "junk"
    };
    properties.id = elementId;
    node = document.createElement(properties.id);
    //node.style.width = width;
    //node.style.height = height;
    //node.style.left = left;
    //node.style.right = right;
    document.body.appendChild(node);
    var fig = dojo.widget.createWidget("FloatingPane",properties,node);
    return node;
}


//*********************************************************************************************
//* CMS Editor
//*********************************************************************************************

function CmsEditor() {
    this.contextPath = requestContextPath();
    this.rteBasePath = this.contextPath + "js_editor/";
    this.rteCustomFilePath = this.contextPath + "editors/";
    this.NARROW = 540;
    this.WIDE = 718;
}

/*
* Create an instance an Editor
* Note: I would prefer this to be a singleton, but can't quite figure that out yet.
*/
var Editor = new CmsEditor();

/**
 *
 */
function CmsEditor_init(editor, name) {
    if (editor == "dhtml") {
        this.loadRichText(name, this.WIDE);
    }
}
CmsEditor.prototype.init = CmsEditor_init;

/**
 * Create an RT Editor of an abitary size.
 * @editor - Editor type (dhtml)
 * @name -
 * @width - pixel width (718 or 540 typically)
 */
CmsEditor.prototype.newEditor = function (editor, name, width, toolbar) {
    if (editor == "dhtml") {
        this.loadRichTextWithToolbar(name, width, toolbar);
    }
}

/**
 *  Create a narrow RTE suitable for two column layouts.
 */
function CmsEditor_initNarrow(editor, name) {
    if (editor == "dhtml") {
        this.loadRichText(name, this.NARROW);
    }
}
CmsEditor.prototype.initNarrow = CmsEditor_initNarrow;

/**
* Submit a new editor preference to the server for the current User.
*/
function CmsEditor_setPreference(editor) {
    var bUrl = this.contextPath + "blocks/editor-update-ajax.ww";
    dojo.io.bind({
        url: bUrl,
        content: {
            editor: editor
        },
        load: function(type, data, evt) {
            /* Do nothing */
        },
        error: function(type, data, evt) {
            alert("Error!");
        },
        mimetype: "text/json"
    });
}
CmsEditor.prototype.setPreference = CmsEditor_setPreference;

function CmsEditor_loadRichText(textAreaName, width) {
    var editor = new FCKeditor(textAreaName, width, 400);
    editor.BasePath = this.rteBasePath;
    editor.CustomFilePath = this.rteCustomFilePath;
    editor.ToolbarSet = 'CMS';
    editor.ReplaceTextarea();
}
CmsEditor.prototype.loadRichText = CmsEditor_loadRichText;

/**
 * Load with specified toolbar.
 */
CmsEditor.prototype.loadRichTextWithToolbar = function (textAreaName, width, toolbar) {
    var editor = new FCKeditor(textAreaName, width, 400);
    editor.BasePath = this.rteBasePath;
    editor.CustomFilePath = this.rteCustomFilePath;
    editor.ToolbarSet = toolbar;
    editor.ReplaceTextarea();
}

/**
 * Show the TextArea for the given name.
 */
function CmsEditor_loadTextarea(name) {
    this.elemTextarea(name).style.display = 'inline';
    this.elemRte(name).style.display = 'none';
}
CmsEditor.prototype.loadTextarea = CmsEditor_loadTextarea;

function CmsEditor_elemTextarea(attributeName) {
    var element = $(attributeName);
    return element;
}
CmsEditor.prototype.elemTextarea = CmsEditor_elemTextarea;

function CmsEditor_elemRte(name) {
    return $(name + "___Frame");
}
CmsEditor.prototype.elemRte = CmsEditor_elemRte;

/**
 *  Hooked to external drop down.
 */
function CmsEditor_changeEditor(selectEditor, name, width) {
    var i = selectEditor.selectedIndex;
    var selectedEditor = selectEditor.options[i].value;

    var rteCreated = this.elemRte(name) != null;
    if (selectedEditor == "dhtml" && !rteCreated) {
        this.loadRichText(name, width);
    } else if (selectedEditor == "dhtml" && rteCreated) {
        this.elemTextarea(name).style.display = 'none';
        this.elemRte(name).style.display = 'inline';
        this.oEditor(name).SetHTML(this.elemTextarea(name).value, true);
    } else {
        this.loadTextarea(name);
        var xhtml = this.oEditor(name).GetXHTML(true);
        this.elemTextarea(name).value = xhtml;
    }
    this.setPreference(selectedEditor);
}
CmsEditor.prototype.changeEditor = CmsEditor_changeEditor;

/**
*   Stupid hack I had to put in. If you swap from a RTE to Textarea, change the textarea,
*   it will copy the RTE's value back into the textarea as part of submitting.
*   To get rid of this behaviour, after you update the textarea, I copy from textarea->RTE.
*
*   Would be unneeded if i could disable the RTE once its in the page somehow, but I can't.
*/
function CmsEditor_hackTextareaLoseFocus(name) {
    // Throws undefined error if not RTE loaded. Probably ignoreable
    this.oEditor(name).SetHTML(this.elemTextarea(name).value, true);

}
CmsEditor.prototype.hackTextareaLoseFocus = CmsEditor_hackTextareaLoseFocus;

function CmsEditor_oEditor(name) {
    // Throws undefined error if not RTE loaded. Probably ignoreable

    return FCKeditorAPI.GetInstance(name);
}
CmsEditor.prototype.oEditor = CmsEditor_oEditor;

//*********************************************************************************************
//* CmsHelp Class
//*********************************************************************************************
/**
*  Define Help class
*/
function CmsHelp() {

}

/**
 *  Create quasi-singleton
 */
var Help = new CmsHelp();

/**
 *  Popup a help window.
 *  @id - String - The id of the <div> to show.
 *  @elHelpIcon - Element - The element representing the help icon (for alignment).
 */
CmsHelp.prototype.show = function(elementId, x, y) {
    var helpWindow = $(elementId);
    helpWindow.style.top = x;
    helpWindow.style.left = y;
    helpWindow.style.display = 'block';
}

/**
 *  @elHelpWindow - Element - The help window itself.
 */
CmsHelp.prototype.hide = function(id) {
    $(id).style.display = 'none';
}

//*********************************************************************************************
//* PopupWindow Class
//*********************************************************************************************

/**
 *  Define popup window class
 * @idContent - The id of the element to use for content of the body.
 * @w - Width in pixels of the popup.
 */
function PopupWindow(idContent, w) {
    this.width = w;
    this.buildPopup();
    this.insertIntoPage(idContent);
}

/**
 *
 */
PopupWindow.prototype.insertIntoPage = function(idContent) {
    var pw = this.window;

    // Insert dummy element before the content.
    var insertPoint = document.createElement("span");
    insertPoint.id = "insertPopupWindow";
    dojo.dom.insertBefore(insertPoint, $(idContent));

    // Remove the old content from the page
    var content = $(idContent);
    if (content == null) {
        alert("Programming error: Must include an element named '" + idContent + "' in the page for Popup Window to work.");
    }
    content.parentNode.removeChild(content);
    content.style.display = 'block';
    content.className = "popup_content";

    this.windowContent = content;
    this.middle.appendChild(content);

    dojo.dom.insertBefore(pw, insertPoint);

    // Remove dummy insert
    insertPoint.parentNode.removeChild(insertPoint);
}

/**
 *
 */
PopupWindow.prototype.toString = function() {
    return "PopupWindow: " + this.windowContent;
}
/**
 *
 */
PopupWindow.prototype.buildPopup = function() {
    var pw = document.createElement("div");
    pw.className = "popup_window";

    var toolBar = document.createElement("div");
    toolBar.className = "popup_top_bar";

    var left = document.createElement("img");
    left.src = url("ajax/windows/images/top_left.gif");
    left.align = "left";

    var topCenter = document.createElement("img");
    topCenter.src = url("ajax/windows/images/top_center.gif");
    topCenter.className = "topCenterImage";

    var buttons = document.createElement("div");
    buttons.className = "popup_top_buttons";

    var closeButton = document.createElement("img");
    closeButton.src = url("ajax/windows/images/close.gif");
    closeButton.className = "closeButton";

    var right = document.createElement("img");
    right.src = url("ajax/windows/images/top_right.gif");

    var middle = document.createElement("div");
    middle.className = "popup_middle";

    var bottom = document.createElement("div");
    bottom.className = "popup_bottom";

    pw.appendChild(toolBar);
    toolBar.appendChild(left);
    toolBar.appendChild(topCenter);
    toolBar.appendChild(buttons);
    buttons.appendChild(closeButton);
    buttons.appendChild(right);
    pw.appendChild(middle);
    pw.appendChild(bottom);

    // Initial styles
    pw.style.width = this.width;

    // set attributes
    this.window = pw;
    this.middle = middle;

    // Connect Events
    var popup = this;
    dojo.event.connect(closeButton, "onclick", function() {
        popup.hide();
    });
}
/**
 *
 */
PopupWindow.prototype.show = function(x, y) {
    this.window.style.display = 'block';
    this.window.style.top = y;
    this.window.style.left = x;
}

/**
 *
 */
PopupWindow.prototype.hide = function() {
    this.window.style.display = 'none';
}

/**
 *  Loads an external file into the popup window.
 *  @x
 *  @y
 */
PopupWindow.prototype.showFile = function(file, x, y) {
    this.x = x;
    this.y = y;
    var pw = this;
    dojo.io.bind({
        url: file,
        load: function(type, data, evt) {
            pw.windowContent.innerHTML = data;
            pw.show(pw.x, pw.y);
        },
        useCache: false,
        preventCache: true,
        error: function(type, data, evt) {
            alert("Error. Could not retrieve file '" + file + "', " + data);
        },
        mimetype: "text/html"
    });

}

//*********************************************************************************************
//* PopupWindowManager Class
//*********************************************************************************************

/**
 *  Define PopupWindowManager class
 */
function PopupWindowManager() {
    this.windows = new Object();
}
/**
 *  Ideally should be static
 */
var PopupManager = new PopupWindowManager();

/**
 *
 */
PopupWindowManager.prototype.newWindow = function(idInsertionPoint, width) {
    var pw = new PopupWindow(idInsertionPoint, width);
    this.windows[idInsertionPoint] = pw;
}

/**
 *  Close a window by name.
 */
PopupWindowManager.prototype.hide = function(windowName) {
    this.windows[windowName].hide();
}

/**
 *  Creates or displays an existing window, given the current windowName.
 *  Reuses the popup it created before if called again.
 *
 */
PopupWindowManager.prototype.showWindow = function(windowName, url, x, y, width) {
    if (!this.windows[windowName]) {
        var wind = new PopupWindow(windowName, width);
        this.windows[windowName] = wind;
    }
    this.windows[windowName].showFile(url, x, y);
}

PopupWindowManager.prototype.storeWindow = function(windowName, url, x, y, width) {
    if (!this.windows[windowName]) {
        var wind = new PopupWindow(windowName, width);
        this.windows[windowName] = wind;
    }
    this.windows[windowName].showFile(url, x, y);
    this.windows[windowName].hide();
}

PopupWindowManager.prototype.getElementById = function(windowName, elementId) {
    if (!this.windows[windowName]) {
        return null;
    }
    return this.windows[windowName].windowContent.getElementById( elementId );
}

//*********************************************************************************************
//* WorkFlowManager Class
//*********************************************************************************************
/**
 *
 */
function WorkFlowManager() {

}
var WorkFlow = new WorkFlowManager();

/**
 *
 */
WorkFlowManager.prototype.currentPageId = function() {
    return $("currentPageId").innerHTML;
}
/**
 * Assigns a content item/page to somebody.
 * @idSelectBox - The id of the select box.
 */
WorkFlowManager.prototype.assign = function(idSelectBox) {
    var select = $(idSelectBox);
    var userId = selectedItem(select).value;

    var pageId = this.currentPageId();
    dojo.io.bind({
        url: url("navigation/workflow/assign-task.ww"),
        content: {
            userId: userId,
            itemId: pageId
        },
        load: function (type, data, evt) {
            // Visual Cue
            $("statusMarker").innerHTML = " (Assigned!)";
        },
        error: function(type, data, evt) {
            alert("Error!");
        },
        mimetype: "text/json"
    });
}
//*********************************************************************************************************************
//* Content Item Introspector functions
//*********************************************************************************************************************
function ItemIntrospector() {

}
var Introspector = new ItemIntrospector();

/**
 *
 */
ItemIntrospector.prototype.updateAttributes = function() {
    this.fetchAttributes(this.update);
}
ItemIntrospector.prototype.updateBlockInfoHelp = function() {
    this.fetchBlockAttributes(this.updateBlockHelp);
}
/**
 *
 */
ItemIntrospector.prototype.updateHelpOnly = function() {
    this.fetchBlockAttributes(this.updateHelp);
}
/**
 *  Gets all the Attributes for the given block.
 */
ItemIntrospector.prototype.fetchBlockAttributes = function(fnOnSuccess) {
    var modelpicker = $("modelpicker");
    var introspector = this;
    dojo.io.bind({
        url: url("blocks/contenttagging/listattributes.ww"),
        content: {
            key: modelpicker.options[modelpicker.selectedIndex].value
        },
        load: fnOnSuccess,
        error: function(type, data, evt) {
            alert("Error! Couldn't fetch Block attributes from server.");
        },
        mimetype: "text/json"
    });
}

/**
 *  Find all the attributes for the given block.
 */
ItemIntrospector.prototype.fetchAttributes = function(fnOnSuccess) {
    var modelpicker = $("modelpicker");
    var introspector = this;
    dojo.io.bind({
        url: url("modelinglab/attribute/list.ww"),
        content: {
            modelId: modelpicker.options[modelpicker.selectedIndex].value
        },
        load: fnOnSuccess,
        error: function(type, data, evt) {
            alert("Error! Couldn't fetch Content Model attributes from server.");
        },
        mimetype: "text/json"
    });
}
/**
 *
 */
ItemIntrospector.prototype.update = function(type, data, evt) {
    var sortBy = $("sort-by-attributes");
    var selectedAttribute = $("selected-attribute");

    // Update the drop down
    dojo.dom.removeChildren(sortBy);
    for (i = 0; i < data.length; i++) {
        var optAttribute = document.createElement("option");
        optAttribute.value = data[i].id;
        optAttribute.innerHTML = data[i].name;
        if (selectedAttribute.value == data[i].id) {
            optAttribute.selected = "true";
        }
        sortBy.appendChild(optAttribute);
    }

    // update the help too
    Introspector.updateHelp(type, data, evt);

}

/**
 *
 */
ItemIntrospector.prototype.updateHelp = function(type, data, evt) {
    var helpList = $("helpAttributesList");
    dojo.dom.removeChildren(helpList);
    for (var i = 0; i < data.length; i++) {
        var li = document.createElement("li");
        li.innerHTML = data[i].columnName;
        helpList.appendChild(li);
    }
    var picker = $("modelpicker");
    $("helpModel").innerHTML = picker.options[picker.selectedIndex].innerHTML;
}

/**
 * Updates the Help Popup for Blocks with the correct list of attributes.
 */
ItemIntrospector.prototype.updateBlockHelp = function(type, data, evt) {
    var helpList = $("helpAttributesList");
    dojo.dom.removeChildren(helpList);
    for (var i = 0; i < data.length; i++) {
        var li = document.createElement("li");
        li.innerHTML = data[i].name;
        helpList.appendChild(li);
    }
    var picker = $("modelpicker");
    $("helpModel").innerHTML = picker.options[picker.selectedIndex].innerHTML;
}
