/**
 * Phoebe pedagogic planner
 *
 * PHP version 5
 *
 * LICENSE: The GNU General Public License (GPL), version 2. See LICENSE.txt
 *
 * Copyright (c) 2006-2008 JISC/HEFCE/University of Oxford
 *
 * @author      David Balch <david.balch@conted.ox.ac.uk>
 * @license     http://opensource.org/licenses/gpl-license.php GPL2
 * @link        http://phoebe-project.conted.ox.ac.uk/
 */

/* Common functions */
function supportedEnv() {
    // TODO check environment limitations
    return true;
}

var brk = '\u000A';
var pm = new Object; // Object to hold data when re-ordering properties in the template edit view.


// Get querystring values
qs =  new Querystring();

if(typeof tinyMCE != "undefined") {
    // WYSIWYG settings
    tinyMCE.init({
        mode: "none",
        cleanup: true,
        entity_encoding: "raw",
        theme: "advanced",
        plugins: "save",
        content_css: "/inc/css/pFunct.css",
        theme_advanced_buttons1: "bold,italic,underline,separator,strikethrough,bullist,numlist,undo,redo,link,unlink",
        theme_advanced_buttons2: "",
        theme_advanced_buttons3: "",
        theme_advanced_toolbar_location: "top",
        theme_advanced_toolbar_align: "left",
        theme_advanced_path_location: "bottom",
        theme_advanced_resize_horizontal: false,
        theme_advanced_resizing_min_height : 240,
        theme_advanced_resizing: true
    });
}

function maskOn() {
    $('#mask').removeClass("hidden");
}

function maskOff() {
    $('#mask').addClass("hidden");
}

function toggleHide(id) {
    theClass = $('#'+id).attr('class');
    if (!theClass || theClass.indexOf('hidden') == -1) {
        $('#'+id).addClass('hidden');
    } else {
        $('#'+id).removeClass('hidden');
    }
}

function hideNode(id) {
    //alert(id)
    // Hide the node
    $('#' + id).css("display", "none");
    // Add an un-hide button.
    $("#noHidden:visible").addClass("hidden");

    //IE doesn't recognise element.textcontent so have to use element.innerHTML: MS 16/10/2007
    if ($('#'+id+' .propertyName').get(0).innerText) name = $.trim($('#'+id+' .propertyName').get(0).innerText);
    else name = $.trim($('#'+id+' .propertyName').get(0).textContent);
    unhidelink = '<a id="'+id+'unhide" href="#'+id+'" onclick="unhideNode(\''+id+'\');">'+name+'</a> ';
    $("#hiddenNodes").append(unhidelink);
    $("#hiddenNodes").append(document.createTextNode(" "));
}

function unhideNode(id) {
    $('#' + id).css("display", "block");
    $('#'+id+'unhide').remove();
    //console.log($('#hiddenNodes').children().length);
    if ($('#hiddenNodes').children().length < 3) {
        $("#noHidden").removeClass("hidden");
    }
}

function toggleDisplay(whichLayer) { 
    var style2 = document.getElementById(whichLayer).style; 
    style2.display = style2.display? "":"block"; 
}

function receiveDesign(data, mode) {
    if(data['OWNER'] == false) {
        $('#designRoot').html('<br><p>Sorry, you do not have permission to edit this design.</p><p>Return to <a href="/designs.php">Your designs</a>.</p>');
    } else {
        // Design info
        desId = data.designInfo.design_id;
        addEditableDescription(data.designInfo);
        //console.log(data.designInfo);

        // Type naming data
        propTypes = data.propertyTypes;
        refTypes = data.referenceTypes;

        // Design properties
        designProps = data.props.children;

        //console.log("Start processing design");
        for (prop in designProps) {
            if (prop != 'indexOf') {
                processNode(designProps[prop]);
            }
        }
        //console.log("Processed all design");

        addOutlineList(designProps);

        // Enable property buttons
        enablePropButtons('');
        if(mode == 'struct') {
            // make nodes dragable
            $('.node').Sortable({
                accept: 'node',
                axis: 'vertically',
                handle: '.handle',
                activeclass: 'sortableactive',
                hoverclass: 'sortablehover',
                helperclass: 'sorthelper',
                opacity: 0.5,
                onStart: function() {
                    //console.log("onStart");
                    // Update the pm object with data about this property when it is dragged.
                    pm.source = $(this).parent();
                    pm.sourceOrigSerialized = $.SortSerialize(pm.source.attr('id'));
                    pm.sourceId = $(this).parent().attr('id');
                    pm.subjectId = $(this).attr('id');
                    pm.subjectPrevSiblingId = $(this).prev().attr('id');
                    pm.subjectNextSiblingId = $(this).next().attr('id');
                    pm.subject = $(this);
                },
                onStop: function() {
                    //console.log("onStop");
                    /*
                    pm.subject = null;
                    pm.source = null;
                    */
                },
                onChange: propMoved // Execute propMoved() when property order is changed.
            });
        }

        $("#hiddenNodes").removeClass("hidden");

        // Enable Outline reveal/hide
        $("#outlineContainer").removeClass("hidden");
        $("#outlineContainer").bind("mouseover", function(){
            $("#oview").removeClass('hidden');
        });
        $("#outlineContainer").bind("mouseout", function(){
            $("#oview").addClass('hidden');
        });
    }
}

function addEditableDescription(designInfo){
    // Design metadata small text inputs
    $('#designMeta').append('<h2><span id="title_'+designInfo['design_id']+'">'+designInfo['title']+'</span></h2>');
    $('#title_'+designInfo['design_id']).editable("/db/setDesVals.php", {
        indicator: "Saving...", tooltip: 'Click to edit', onblur: 'submit'
    });

    $('#designMeta').append('<p><span id="description_'+designInfo['design_id']+'">'+designInfo['description']+'</span></p>');
    $('#description_'+designInfo['design_id']).editable("/db/setDesVals.php", {
        indicator: "Saving...", tooltip: 'Click to edit', onblur: 'submit'
    });

/* Needs to save to the right place...
    // Enable big text inputs
    $('#description_'+designInfo['design_id']).click( function() {
        id = $(this).attr('id');

        // Enable editor
        tinyMCE.execCommand('mceToggleEditor', false, id);
        tinyMCE.execCommand('mceFocus', false, id);

        // Show save button
        //console.log('test id: '+id);
        id = id.replace('_input', '_controls');
        //console.log('test id: '+id);
        $("#"+id).css("display", "block");
    });
*/
}

function addOutlineList(designProps) {
    oList = $('<ul id="oview" class="hidden"><li><a href="#designMeta">Top</a></li></ul>');

    var theProp = new Array();
    var theTitle = new Array();
    var theProp_count = 0;
    var result = "";
    var item = "";
    for (i in designProps) {
        theProp = designProps[i];

        if (i != 'indexOf') {
            item = $('<li id="ov'+theProp['prop_id']+'"><a href="#p'+theProp['prop_id']+'" onclick="closeEditProp(); unhideNode(\'p'+theProp['prop_id']+'\');">'+theProp['title']+'</a></li>');
            if(theProp['children']) {
                childList = $('<ul></ul>');
                // Recurse through children
                for (child in theProp['children']) {
                    theChild = theProp['children'][child];
                    if (child != 'indexOf') {
                        $(childList).append('<li id="ov'+theChild['prop_id']+'"><a href="#p'+theChild['prop_id']+'" onclick="closeEditProp(); unhideNode(\'p'+theProp['prop_id']+'\'); unhideNode(\'p'+theChild['prop_id']+'\');">'+theChild['title']+'</a></li>');
                    }
                }
                $(item).append(childList);
            }
        }

        $(oList).append(item);
    }

        $(oList).append('<li><a href="#hiddenNodes">Hidden fields</a></li>');
    $('#outlineContainer').append(oList);
}

function closeEditProp(){
    $('#editPropDialog').remove();
    maskOff();
}

function delProp(rawId) {
    id = rawId.replace('p', '');
    if ($('#'+rawId).parent().attr('id') == 'designRoot') {
        // Fix order of root items
        isRoot = true;
    }
    // Remove node from database
    deleteOp = $.post("/db/delProp.php", {
        prop_id : id
    }, function(data) {
        if(data == 0) {
            // Remove node from page
            $("#"+rawId).remove();
            if (isRoot) {
                // Fix order of root items
                updateRootOrder();
            }
            // Remove node from Outline nav
            $("#ov"+id).remove();
        }
    });
}

function enablePropButtons(prop) {
    if(prop != '') {
        // If we're passed a property id, only set events for that property
        prop = '#p'+prop+' ';
    }

    // Enable small text inputs
    $(prop+".editable").editable("/db/setPropVal.php", {
        indicator : "Saving...",
        tooltip   : 'Click to edit',
        onblur    : 'submit'
    });

    // Enable big text inputs
    $(prop+".editable_textarea").click( function() {
        id = $(this).attr('id');

        // Enable editor
        tinyMCE.execCommand('mceToggleEditor', false, id);
        tinyMCE.execCommand('mceFocus', false, id);

        // Show save button
        //console.log('test id: '+id);
        id = id.replace('_input', '_controls');
        //console.log('test id: '+id);
        $("#"+id).css("display", "block");
    });

    // Activate multiple field add buttons
    $(prop+".addButton").click( function(){
        id = $(this).attr("id");
        id = id.substring(0, id.indexOf('Add'));
        clonePropNode(id, true);
    });

    // Activate clone field delete buttons
    $(prop+".delButton").click( function(){
        id = $(this).attr("id");
        id = id.substring(0, id.indexOf('Del'));
        delProp(id);
    });

    // Activate hide buttons
    $(prop+".hideButton").click( function(){
        id = $(this).attr("id");
        id = id.substring(0, id.indexOf('Hide'));
        hideNode(id);
    });
}

function processNode(prop) {
    // Check whether prop is an object, to filter out props (sent by IE) which aren't objects.
    if (typeof prop == 'object'){
        // Create new UI for prop
        out = newPropUI(prop);

        // Output node to page
        $(parentId).append(out);

        // Recurse through children
        for (child in prop.children) {
            processNode(prop.children[child]);
        }
        //$(parentId).append('<div class="node dummy"/>');
    }
}

function newPropUI(prop) {
    // Construct new node
    propType = propTypes[prop['type']];
    propId = 'p'+prop['prop_id'];
    propVal = (prop['value']) ? prop['value']: '';

    if(editStructure) {
        propPos = ' root_item="'+prop['root_item']+'" first_child_id="'+prop['first_child_id']+'" next_sibling_id="'+prop['next_sibling_id']+'"';
    } else {
        propPos = '';
    }
    out  = '<div class="node proptype:'+prop.type+' property" id="'+propId+'"'+propPos+'>';

    if(editStructure) {
        out += '<div class="nodeEdit">';
        out += '<div class="handle"><ul class="buttons">';
        out += ' <li><a href="#" onclick="editProp(\''+propId+'\'); return false;"><img width="16" height="16" src="/inc/img/spanner.gif" alt="Edit '+propType+'" title="Edit '+propType+'"/></a></li>';
        out += ' <li><a href="#" onclick="clonePropNode(\''+propId+'\', false); return false;"><img width="16" height="16" src="/inc/img/clone.gif" alt="Clone '+propType+'" title="Clone '+propType+'"/></a></li>';
        out += ' <li><a href="#" onclick="delProp(\''+propId+'\'); return false;"><img width="16" height="16" src="/inc/img/del.gif" alt="Delete '+propType+'" title="Delete '+propType+'"/></a></li>';
        out += '</ul>';
        out += '<img width="16" height="16" src="/inc/img/move.gif" alt="Move this '+propType+'" title="Move this '+propType+'"/>';
        out += '</div></div>';
    }

    propControls = '<span class="buttons">';
    if (prop.clone_of != null) {
        propControls += '<img width="16" height="16" src="/inc/img/del.gif" alt="Delete this cloned field" title="Delete this cloned field" class="delButton c:'+prop['clone_of']+'" id="'+propId+'Del"/>';
    } else if (prop.multiplicity == "1") {
        propControls += '<img width="16" height="16" src="/inc/img/add.gif" alt="Click to add another \''+prop['title']+'\'" title="Click to add another \''+prop['title']+'\'" class="addButton" id="'+propId+'Add"/>';
    }
    propControls += '<img width="16" height="16" src="/inc/img/eye.gif" alt="Click to hide this '+propType+'" title="Click to hide this '+propType+'" class="hideButton" id="'+propId+'Hide"/>';
    propControls += '</span>';

    out += '<div class="property row">';
    out += '<span class="th"><label class="propertyName">';
    out += propTitleLink(prop);
    out += '</label>';
    out += propLinks(prop);
    out += '</span><span class="tc">';
    out += propControls;
    //console.log(prop.field_type);

    switch(prop.field_type) {
        // Add the correct type of HTML input
        case '1':
            // Small text
            out += '<span class="editable" id="'+propId+'_input">'+propVal+'</span>';
            break;
        case '2':
            // Large text
            out += '<span class="editable_textarea" id="'+propId+'_input">'+propVal+'</span>';
            out += '<div id="'+propId+'_controls" class="hidden textarea_controls">';
            out += ' <input type="button" onclick="saveMcEditor(\''+propId+'\'); return false;" value="Save"/>';
            out += ' <input type="button" onclick="cancelMcEditor(\''+propId+'\'); return false;" value="Cancel"/>';
            out += '</div>';
            break;
        case '3':
            // Property reference
            out += '<span class="editable" id="'+propId+'_input">'+propVal+'</span>';
            break;
    }
    out += '</span></div>';
    //out += '<div class="node dummy"> </div>';
    out += '</div>';

    // Establish parent id
    if (prop.parent_id == null) {
        // Root object, hard coded
        parentId = '#designRoot';
    } else {
        // Use given id
        parentId = '#p'+prop['parent_id'];
    }

    // Return the new prop node
    return out
}

function propTitleLink(prop) {
    // Write the property title, including a link to default guidance, if any
    var titleLink = "";
    // Insert title - link to guidance if there is any
    if (prop.references) {
        numRefs = prop.references.length;
        for(i=0; i<numRefs; i++){
            if (prop.references[i].type == 0) {
                titleLink += '<a href="'+prop.references[i].uri+'" target="guidanceAreaContent" title="Click for guidance" class="guideLink" id="r'+prop.references[i].ref_id+'">';
                titleLink += prop.title;
                titleLink += ' <img width="16" height="16" src="/inc/img/book.gif" alt="guidance"/></a>';
            }
        } if (titleLink =="") {
            titleLink += prop.title;
        }
    } else {
        titleLink += prop.title;
    }

    return titleLink;
}

function propLinks(prop) {
    // Write non-default guidance link holding spans (even if no refs present,
    // as we may add some on the webpage).
    var links = "";

    links += '<span class="propLinks">';
    for(i=1; i<refTypes.length; i++){
        // Loop through reference types first, to group them together
        links += '<span class="'+refTypes[i].name+'Links" id="p'+prop.prop_id+refTypes[i].name+'Links">';

        if (prop.references) {
            // Insert non-main-guidance reference links if there are any
            numRefs = prop.references.length;
            for(j=0; j<numRefs; j++){
                // Loop over references
                if (prop.references[j].type == i) {
                    links += propLink(i, refTypes[i].name, prop.references[j].ref_id, prop.references[j].uri);
                }
            }
        }
        links += '</span>';
    }
    links += '</span>';

    return links;
}

function propLink(refType, refTypeName, refId, uri) {
    //console.log(refType);
    //console.log(refTypeName);
    //console.log(refId);
    //console.log(uri);
    switch (refTypeName) {
        case "Guidance":
        case "Reference":
            refTypeName = 'book';
            break;
    }
    linkHtml = '<a href="'+uri+'" target="guidanceAreaContent" title="Click for '+refTypeName+'" class="guideLink'+refType+'" id="r'+refId+'">';
    linkHtml += ' <img width="16" height="16" src="/inc/img/'+refTypeName+'.gif" alt="'+refTypeName+'"/></a> ';
    return linkHtml;
}

function saveMcEditor(element_id) {
    var inst = tinyMCE.getInstanceById(element_id+'_input');
    // Save content from an TinyMCE editor instance to the database
    $.post("/db/setPropVal.php", {
        id : element_id+'_input',
        value : inst.getHTML()
    });

    // Switch back to non-editable span
    tinyMCE.execCommand('mceToggleEditor', false, element_id+'_input');
    $("#"+element_id+"_controls").css("display", "none");
}

function cancelMcEditor(element_id) {
    var inst = tinyMCE.getInstanceById(element_id+'_input');
    // Revert content in an TinyMCE editor to before editing.
    if (inst.isDirty()) {
        tinyMCE.execCommand('mceCancel', false, element_id+'_input');
    }

    // Switch back to non-editable span
    tinyMCE.execCommand('mceToggleEditor', false, element_id+'_input');
    $("#"+element_id+"_controls").css("display", "none");
}

function clonePropNode(rawId, fromMultiNode) {
    // Add a new property, cloned from an existing one.
    id = rawId.replace('p', '');
    //console.log("clonePropNode("+rawId+", "+fromMultiNode+")");

    // Get property hierarchy type
    prop_type = $('#'+rawId).attr('class').split(':');
    prop_type = prop_type[1].split(' ');
    prop_type = prop_type[0];
    //console.log(prop_type);

    // Clone prop in database
    $.getJSON("/db/cloneProp.php", {
        prop_id: id,
        prop_type: prop_type,
        design_id: desId,
        from_multi : fromMultiNode
        }, function(json){
            // Database record created.
            //console.log(json);
            // Add property to main UI
            out = insertClone(json, rawId, fromMultiNode);
            if ($('#'+rawId).parent().attr('id') == 'designRoot') {
                //console.log("hi");
                // Fix order of root items
                updateRootOrder();
            }

            // Add property to Outline UI
            $('#ov'+id).after($('<li id="ov'+json['prop_id']+'"><a href="#p'+json['prop_id']+'" onclick="unhideNode(\'p'+json['prop_id']+'\')">'+json['title']+'</a></li>'));

            enablePropButtons(json['prop_id']);
        }
    );
}

function insertClone(prop, nodeToFollow, fromMultiNode) {
    // Create new UI for prop
    out = newPropUI(prop);

    // Output node to page
    $("#"+nodeToFollow).after(out);
    //console.log($("#"+nodeToFollow).after(out).attr('phoebeProp', prop));

    parentId = '#p'+prop.parent_id;
    // Recurse through children
    for (child in prop.children) {
        processNode(prop.children[child]);
    }
}

function setDes(theInput) {
    //console.log(theInput);
    switch (theInput.type) {
        case 'checkbox':
            if(theInput.checked) {
                newValue = 1;
            } else {
                newValue = 0;
            }
            break;
        case 'select-one':
            newValue = theInput.value;
            break;
    }

    newPropId = $.post("/db/setDesVals.php", {
        id: theInput.name, value: newValue
    }, function(data) {return data;});
}

function setProp(theInput) {
    //console.log(theInput);
    switch (theInput.type) {
        case 'checkbox':
            if(theInput.checked) {
                newValue = 1;
            } else {
                newValue = 0;
            }
            break;
        case 'select-one':
            newValue = theInput.value;
            break;
    }

    propField = theInput.name;
    propId = theInput.id.replace(propField+'_', '');

    newPropId = $.post("/db/setPropVal.php", {
        id: propId,
        propField: propField,
        value: newValue
    }, function(data) {
        var reload = confirm("Field updated, but the template editing page\ncannot yet display this type of change.\n\nPlease select \"OK\" to update the page.");
        if (reload) {
            window.location.reload();
        }
    });
}