/**
 * 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/
 */

var appName = "Phoebe";
var propTypes;
var refTypes;
var desId;
var editStructure = true;
// Variable to queue prop editing operations
var editPropOps = new Array();

$(document).ready(function(){
    if (supportedEnv()) {
        // We can run in this environment, so lets do it.
        // Hide unsupportedMsg
        $('#unsupportedMsg').remove();
        // Show Phoebe elements
        $('#phoebeArea').removeClass('hidden');
        $('#designMeta').append('<p id="initLoadMsg">Loading template...</p>');

        // Get the design data
        designData = "/db/getDesign.php?mode=json&design_id="+qs.get('design_id');
        $.getJSON(designData, function(json){
            receiveDesign(json, 'struct');
            $('#initLoadMsg').remove();
            $('#editNodes').removeClass('hidden');
        });
    }
});

function createNewProp(form) {
    // Create a new property, and make ready to add to current design
    // We add the new prop at the end of the design, so set root item number to
    // one more then the current number of top level props.
    root_item_number = $('#designRoot > div').size() + 1;

    if (form.multiplicity.checked) {
        multiplicity = 1;
    } else {
        multiplicity = '';
    }
    // Add to database and get the prop_id
    newPropId = $.post("/db/addProp.php", {
        title : form.newPropTitle.value,
        field_type : form.fieldType.value,
        parent_design_id : form.desId.value,
        root_item : root_item_number,
        multiplicity : multiplicity
    }, function(data) {
        var i=parseInt(data);
        if(!isNaN(i)) {
            // Database record created.
            // Set up the new property as an object
            myProp = {
                "prop_id":data,
                "parent_design_id":form.desId.value,
                "parent_id":null,
                "root_item": root_item_number,
                "type":"0",
                "title":form.newPropTitle.value,
                "field_type":form.fieldType.value,
                "value":null,
                "first_child_id":null,
                "multiplicity":multiplicity,
                "next_sibling_id":null
            }

            // Add new prop to the page, ready for the user to move somewhere
            processNode(myProp);

            // Activate buttons
            enablePropButtons(data);

            // Make dragable
            $('#designRoot').SortableAddItem(document.getElementById('p'+data));

        } else {
            // Creation failed.
            // TODO: Warn user properly.
            alert('An error occured. '+data);
        }
    });
}

function editProp(rawId) {
    // Clear the property ops var
    editPropOps = new Array();
    id = rawId.replace('p', '');

    // Create edit interface from the property
    theProp = $('#'+rawId);
    oldTitle = $('#'+rawId+' .propertyName').eq(0).text();
    faceHtml = '<form id="editPropDialog" class="dialog" action="">';
    faceHtml += '<h2>Edit property: '+oldTitle+'</h2>';

    faceHtml += ' <fieldset><legend>Core details';
    faceHtml += ' <a href="#" onclick="toggleHide(\'editPropCore\'); return false;"><img width="16" height="16" src="/inc/img/eye.gif" alt="" title="Click to hide this section"/></a></legend>';
    faceHtml += ' <div id="editPropCore">';
    faceHtml += ' <label>Title: <span id="'+rawId+'_title" class="editable editPropTitle">'+oldTitle+'</span></label><br/>';

    if ($('#'+rawId+' .guideLink').attr('href')) {
        guideRefUrl = $('#'+rawId+' .guideLink').attr('href');
        guideRefId = $('#'+rawId+' .guideLink').attr('id');
    } else {
        guideRefUrl = '';
        guideRefId = 'new';
    }
    faceHtml += ' <label title="'+refTypes[0].description+'">'+refTypes[0].name+' URL: <span id="'+guideRefId+'" class="editable editPropUrl">'+guideRefUrl+'</span></label>';
    faceHtml += '<br/><label>Allow clones in design: <input id="multiplicity_'+id+'" type="checkbox" name="multiplicity" value="1"';
    if($('#'+rawId+ ' .addButton').size() > 0) {
        faceHtml += ' checked="checked"';
    }
    faceHtml += ' onchange="setProp(this);"/></label> ';
    faceHtml += ' </div></fieldset>';

    for(i=1; i<refTypes.length; i++){
        // Loop through reference types, provide a fieldset for each
        faceHtml += ' <fieldset><legend>'+refTypes[i].name+' URLs';
        faceHtml += ' <a href="#" onclick="toggleHide(\'editProp'+refTypes[i].name+'\'); return false;"><img width="16" height="16" src="/inc/img/eye.gif" alt="" title="Click to hide this section"/></a></legend>';
        faceHtml += ' <div id="editProp'+refTypes[i].name+'">';
        faceHtml += ' <p>'+refTypes[i].description+'</p>';
        faceHtml += ' <div id="refs'+i+'">';
        $('#'+rawId+refTypes[i].name+'Links a').each(function(){
            // Display refs for each type
            faceHtml += buildRefUi($(this).attr('id'), $(this).attr('href'));
        });
        faceHtml += ' </div>';
        faceHtml += '<hr/>';
        faceHtml += ' <label>Add new URL: <input type="text" id="addProp'+refTypes[i].name+'Url" class="newUrl"/></label>';
        faceHtml += ' <input type="button" value="Add" onclick="addRef('+id+', \'addProp'+refTypes[i].name+'Url\', '+i+' );"/>';
        faceHtml += ' </div></fieldset>';
    }

    faceHtml += ' <div class="dialogControls">';
    faceHtml += '  <input type="button" value="Close" onclick="closeEditProp();"/>';
    faceHtml += ' </div>';
    faceHtml += '</form>';

    // Add to page
    maskOn();
    $(faceHtml).appendTo($("#phoebeArea"));

    // Enable small text inputs
    $(".editPropTitle").editable("/db/setPropTitle.php", {
        indicator: "Saving...", tooltip: 'Click to edit', onblur: 'submit'
    }, function(value, settings) {
        // Update value on the page
        // TODO: Don't delete the links
        title = $('#'+this.id.replace('_title', '')+' .propertyName:first');
        //console.log(title);
        title.text(value);
    });
    $(".editPropUrl").editable("/db/setRefUrl.php", {
        indicator: "Saving...", tooltip: 'Click to edit', onblur: 'submit'
    }, function(value, settings) {
        // TODO: Update value on the page
        //$('#'+this.id.replace('_title', '')+' .propertyName:first a').attr('href', value);
    });
}

function fieldTypeSelect(current) {
    selector = '<label>Field type <select id="fieldType">';
    for (var i = 0; i <= fieldTypes.length; i++) {
        type = fieldTypes[i];
        selector += ' <option title="'+type['description']+'" value="'+type['field_type_id']+'">'+type['field_type_name'];
        if(current == type['field_type_id']) {
            selector += 'selected="selected"';
        }
        selector += '</option>';
    }
    selector += '</select></label> | ';

}

function buildRefUi(refId, refHref) {
    // Build up the HTML UI for a property reference/
    //console.log('refId: '+refId+', refHref: '+refHref);
    refHtml = ' <div id="'+refId+'edit" class="anEditPropUrl">';
    refHtml += ' <input type="text" id="'+refId+'" value="'+refHref+'">';
    refHtml += ' <a href="#" onclick="delRef(\''+refId+'\'); return false;"><img width="16" height="16" src="/inc/img/del.gif" alt="" title="Click to delete this URL"/></a>';
    refHtml += ' </div>';

    return  refHtml;
}

function addRef(thePropId, hrefId, theRefType) {
    //console.log('addRef: '+thePropId+', '+hrefId+', '+theRefType);
    // Get new ref details
    refTypeName = refTypes[theRefType].name;
    //console.log("Check type: "+theRefType);
    theHref = $('#'+hrefId).attr('value');

    // Add ref to database
    addOp = $.post("/db/addRef.php", {
        parent_property_id : thePropId,
        parent_design_id : qs.get('design_id'),
        type : theRefType,
        uri : theHref
    }, function(data) {
        var i=parseInt(data);
        if(!isNaN(i)) {
            // Database record created, add ref to UI
            newRefHtml = buildRefUi(i, theHref);
            $(newRefHtml).appendTo($("#refs"+theRefType));
            $(propLink(theRefType, refTypeName, data, theHref)).appendTo($('#p'+thePropId+refTypeName+'Links'));
        }
    });
}

function delRef(rawId) {
    // Delete a reference
    var answer = confirm("Delete this reference?")
    if (answer){
        // Remove ref from database
        id = rawId.replace('r', '');
        deleteOp = $.post("/db/delRef.php", {refId: id});

        // Remove link from design on page
        $("#"+rawId).remove();
        // Remove link from prop edit dialog
        $("#"+rawId+'edit').remove();
    }
}

function propMoved() {
    // Update the property's relationships with other properties
    //console.log("propMoved()");
    //console.log(pm);
    pm.destId = pm.subject.parent().attr('id');

    // Remove subject from original source
    // Get first child id from original source's hash
    origChildren = pm.sourceOrigSerialized.hash.split('=')[1];
    if(origChildren.indexOf('&') == -1) {
        origFirstChild = origChildren;
    } else {
        origFirstChild = origChildren.split('&')[0];
    }

    // Is subject a root-level item for source or destination?
    if (pm.sourceId == 'designRoot' || pm.destId  == 'designRoot') {
        // Yes - change root item order
        //console.log('Root property changes');
        updateRootOrder();

        if (pm.destId  != 'designRoot') {
            // Moving out of root: update the insert point.
            //console.log('out of root level');
            if (pm.subject.prev('.node').size() == 0) {
                // First child at destination
                // Update subject's following sibling to dest's "first child".
                updateProp(pm.subjectId, 'next_sibling_id', pm.subject.parent().attr('first_child_id'));

                // Update dest's "first child" to subject.
                updateProp(pm.subject.parent().attr('id'), 'first_child_id', pm.subjectId);
            } else {
                // Not first child at destination, is a following sibling
                // Update subject's following sibling to dest subj's prev sib's "following sibling".
                updateProp(pm.subjectId, 'next_sibling_id', pm.subject.prev().attr('next_sibling_id'));

                if (pm.subject.prev('.node').attr('id')) {
                    // Update subj's prev sib's "following sibling" to subject.
                    updateProp(pm.subject.prev('.node').attr('id'), 'next_sibling_id', pm.subjectId);
                }
            }
            // Clear the subject's root item
            updateProp(pm.subjectId, 'root_item', '');

        } else if (pm.destId  == 'designRoot') {
            // Moving into root: update the removal point.
            //console.log('into root level');
            if(pm.subjectPrevSiblingId && $('#'+pm.subjectPrevSiblingId).parent().attr('id') != 'designRoot') {
                // Orig had prev sib which was not a root object, so
                // update that sib's "following sibling" to the subject's "following sibling"
                updateProp(pm.subjectPrevSiblingId, 'next_sibling_id', pm.subjectNextSiblingId);
            } else {
                // Orig had no prev sib, so must have been first child - update the orig parent
                updateProp(pm.sourceId, 'first_child_id', pm.subjectNextSiblingId);
            }
            // Clear the subject's next sibling
            updateProp(pm.subjectId, 'next_sibling_id', 'null');

        }
    } else {
        // Not a root item
        // Was subject first child of original source?
        if (pm.subjectId == origFirstChild) {
            // Yes
            //console.log("subject first child of original source");
            // Update source's first child to the subject's following sibling.
            updateProp(pm.sourceId, 'first_child_id', $('#'+pm.subjectId).attr('next_sibling_id'));

            // Update the subject's "following sibling" to the dest preceeding sibling's "following sibling".
            updateProp(pm.subjectId, 'next_sibling_id', $('#'+pm.subjectId).prev().attr('next_sibling_id'));

            // Update the dest preceeding sibling's "following sibling" to the subject.
            updateProp($('#'+pm.subjectId).prev().attr('id'), 'next_sibling_id', pm.subjectId);

        } else {
            // No - must have been a following sibling
            //console.log("subject not first child of original source");
            // Update the orig preceding sib's "following sibling" to the subject's following sib
            updateProp(pm.subjectPrevSiblingId, 'next_sibling_id', $('#'+pm.subjectId).attr('next_sibling_id'));

            // Update the subject's "following sibling" to the dest preceding sib's "following sibling"
            updateProp(pm.subjectId, 'next_sibling_id', $('#'+pm.subjectId).prev().attr('next_sibling_id'));

            // Update the dest preceding sib's "following sibling" to the subject
            updateProp($('#'+pm.subjectId).prev().attr('id'), 'next_sibling_id', pm.subjectId);
        }
    }
}

function updateRootOrder() {
    $('#designRoot').children().each(function (i) {
        newRootItem = i+1;
        if($(this).attr('root_item') != newRootItem) {
            //console.log('Change prop: '+$(this).attr('id')+', RootItem #: '+$(this).attr('root_item')+ ', newRootItem #: '+newRootItem);
            updateProp($(this).attr('id'), 'root_item', newRootItem.toString());
        }
    })
}

function updateProp(propId, field, value) {
    // Update a value on a property
    if(value == undefined) {
        value = '';
    }
    propId = propId.replace('p', '');
    value = value.replace('p', '');

    //console.log(propId+', '+field+', '+value);
    $('#p'+propId).attr(field, value);

    if(value == 'null') {
        value = '';
    }
    // Update in the database
    propUpdate = $.post("/db/updateProp.php", {
        field: field,
        prop_id: propId,
        value: value
    });

   //return propUpdate;
}
