/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// tables container - will get hidden, when no config service available
var configContent = false;

// config table list
var configTable = false;
var configBody  = false;
var configRow = false;

// factories table list
var factoryBody  = false;
var factoryRow = false;


// editor dialog
var editor = false;
var editorMessage = false;

function configure(pid, create) {
	var uri = pluginRoot + '/' + pid;
	// we have to add a cache killer for IE8
	var postUri = uri + '?post=true&';
	if ( create ) {
		postUri += param.create + '=1&';
	}
	postUri = postUri + 'ts='+new Date().getMilliseconds();
	$.get(postUri, null, displayConfigForm, 'json');
}

function displayConfigForm(obj) {
	var parent = document.getElementById('editorTable');
	clearChildren( parent )

    var trEl = tr( );
    parent.appendChild( trEl );
    
    var tdEl = td( null, { colSpan: "2" } );
    trEl.appendChild( tdEl );
    
    var formEl = createElement( "form", null, {
			id    : "editorForm",
            method: "POST",
            action: pluginRoot + "/" + obj.pid
        });
    tdEl.appendChild( formEl );
    
    var inputEl = createElement( "input", null, {
            type: "hidden",
            name: param.apply,
            value: "true"
        });
    formEl.appendChild( inputEl );
    
    // add the factory PID as a hidden form field if present
    if (obj.factoryPid)
    {
        inputEl = createElement( "input", null, {
                type: "hidden",
                name: "factoryPid",
                value: obj.factoryPid
            });
        formEl.appendChild( inputEl );
    }
    
    // add the PID filter as a hidden form field if present
    if (obj[ param.pidFilter ])
    {
        inputEl = createElement( "input", null, {
                type: "hidden",
                name: param.pidFilter,
                value: obj.pidFilter
            });
        formEl.appendChild( inputEl );
    }
    
    inputEl = createElement( "input", null, {
            type: "hidden",
            name: "action",
            value: "ajaxConfigManager"
        });
    formEl.appendChild( inputEl );
    
    inputEl = createElement( "input", null, {
        type: "hidden",
        name: "$location",
        id: "lochidden"
    });
    formEl.appendChild( inputEl );
    
    var tableEl = createElement( "table", null, {
            border: 0,
            width: "100%"
        });
    formEl.appendChild( tableEl );
    
    var bodyEl = createElement( "tbody" );
    tableEl.appendChild( bodyEl );
    
    if (obj.description)
    {
        trEl = tr( );
        tdEl = td( null, { colSpan: "3" } );
        addText( tdEl, obj.description );
        trEl.appendChild( tdEl );
        bodyEl.appendChild( trEl );
    }
    
    if (obj.properties)
    {
        printForm(bodyEl, obj.properties);
    }

    printConfigurationInfo(parent, obj);
	if ( obj.service_location && obj.bundle_location && obj.service_location != obj.bundle_location) {
		editorMessage.removeClass('ui-helper-hidden').text(i18n.err_bind.msgFormat(obj.pid, obj.bundle_location, obj.service_location));
	} else editorMessage.addClass('ui-helper-hidden');

	// ugly workaround for IE6 and IE7 - these browsers don't show correctly the dialog
	var ua = navigator.userAgent;
	if (ua.indexOf('MSIE 6') != -1 || ua.indexOf('MSIE 7') != -1) $(parent).html(parent.innerHTML);

	initStaticWidgets(editor
		.attr('__pid', obj.pid)
		.attr('__location', obj.bundleLocation?obj.bundleLocation:'')
		.dialog('option', 'title', obj.title)
		.dialog('open'));

	// autosize
	$('textarea').trigger('autosize.resize');
}

/* Element */ function addDefaultValue( /* Element */ element ) {
	if (element) {
		element.appendChild( 
			createElement('span', 'default_value ui-state-highlight1 ui-icon ui-icon-alert', {
				title : i18n.dflt_value
			})
		);
	}
	return element;
}

function printForm( /* Element */ parent, /* Object */ properties ) {
    var propList;
    for (var prop in properties)
    {
        var attr = properties[prop];

		// create optionality element
		var optElement = false;
		if (attr.optional) {
			var elAttributes = {
                type: "checkbox",
                name: "opt" + prop,
				title: i18n.opt_value
            };
			if (attr.is_set) {
				elAttributes['checked'] = 'checked';
			}
			optElement = createElement( "input", "optionality", elAttributes);
		} else {
			optElement = text( "" );
		}
		// create the raw
        var trEl = tr( null, null, [
				td( null, null, [ optElement ] ),
                td( null, null, [ text( attr.name ) ] )
            ]);
        parent.appendChild( trEl );

        var tdEl = td( null, { style: { width: "99%" } } );
        trEl.appendChild( tdEl );
  
        if (attr.value != undefined)
        {
            // check is required to also handle empty strings, 0 and false
            var inputName = (prop == "action" || prop == "propertylist" || prop == "apply" || prop == "delete") ? '$' + prop : prop;
			var inputEl = createInput( inputName, attr.value, attr.type, '99%' );
            tdEl.appendChild( inputEl );
            tdEl.appendChild( createElement( "br" ) );
        }
        else if (typeof(attr.type) == 'object')
        {
        	// assume attr.values and multiselect
        	createMultiSelect( tdEl, prop, attr.values, attr.type, '99%' );
            tdEl.appendChild( createElement( "br" ) );
        }
        else if (attr.values.length == 0)
        {
            tdEl.appendChild( createSpan( prop, "", attr.type ) );
        }
        else
        {
            for (var i=0;i<attr.values.length;i++)
            {
                tdEl.appendChild( createSpan( prop, attr.values[i], attr.type ) );
            }
        }
        
		if (!attr.is_set) {
			addDefaultValue( tdEl );
		}

        if (attr.description)
        {
            addText( tdEl, attr.description );
        }
        
        if (propList) {
            propList += ',' + prop;
        } else {
            propList = prop;
        }
    }
    
    parent.appendChild( createElement( "input", null, {
            type: "hidden",
            name: param.propertylist,
            value: propList
        })
    );
    
    // FIX for IE6 and above: checkbox can only be checked after it is in the DOM
    $(".checked_box").attr("checked", true).removeClass("checked_box");
}

function printConfigurationInfo( /* Element */ parent, obj )
{
    parent.appendChild( tr( null, null, [
            createElement( "th", null, { colSpan: "2" }, [
                text( i18n.cfg_title )
            ])
        ])
    );
    
    parent.appendChild( tr( null, null, [
            td( null, null, [
                text( i18n.pid )
            ]),
            td( null, null, [
                text( obj.pid )
            ])
        ])
    );

    if (obj.factoryPid)
    {
        parent.appendChild( tr( null, null, [
                td( null, null, [
                    text( i18n.fpid )
                ]),
                td( null, null, [
                    text( obj.factoryPid )
                ])
            ])
        );
    }
    
    var binding = obj.bundle_location;
    if (!binding)
    {
        binding = i18n.unbound;
    } else {
    	$("#lochidden").val(binding);
    }
    
    parent.appendChild( tr( null, null, [
            td( null, null, [
                text( i18n.binding )
            ]),
            td( null, null, [
                createElement( "input", null, {
                    type: "text",
                    name: "$location",
                    style: { width: '99%' },
                    value: binding,
                    id: "locinput"
                })                             
            ])
        ])
    );
    if ( binding === i18n.unbound ) {
    	$("#locinput").addClass("placeholder-active");
    }
	$("#locinput").on("focus", function() {
	    if ($("#locinput").val() === i18n.unbound) {
	        $("#locinput").removeClass("placeholder-active");
	        $("#locinput").val("");
	    }
	});
	$("#locinput").on("blur", function() {
	    if($("#locinput").val() === "") {
	        $("#locinput").val(i18n.unbound);
	        $("#locinput").addClass("placeholder-active");
	    }
	});
	$("#locinput").on("keydown", function(event) {
	    if (event.keyCode == 27){
	        $("#locinput").val("");
	    }
	});
	if ( obj.bundleLocation && obj.bundleLocation != "" ) {
	    parent.appendChild( tr( null, null, [
	                                         td( null, null, [
	                                             text( "" )
	                                         ]),
	                                         td( null, null, [
	                                             text( obj.bundleLocation )
	                                         ])
	                                     ])
	                                 );		
	}
}


var spanCounter = 0;
/* Element */ function createSpan(prop, value, type) {
    spanCounter++;
    var newId = prop + spanCounter;
    
    var addButton = createElement("input", null,
    		{   type: "button",
    	        style: {width : "5%"},
    	        value: "+"
    	    }
      );
    $(addButton).click(function() {addValue(prop, newId)});
    var remButton = createElement("input", null,
    		{   type: "button",
    	        style: {width : "5%"},
    	        value: "-"
    	    }
      );
    $(remButton).click(function() {removeValue(newId)});
    var spanEl = createElement( "span", null, { id: newId }, [
        createInput( prop, value, type, '89%' ), addButton, remButton,
        createElement("br")
    ]);
    
    return spanEl;
}

/* Element */ function createInput(prop, value, type, width) {
    if (type == 11) { // AttributeDefinition.BOOLEAN

        var inputEl = createElement( "input", null, {
                type: "checkbox",
                name: prop,
                value: "true"
            });
            
        if (value && typeof(value) != "boolean")
        {
            value = value.toString().toLowerCase() == "true";
        }
        if (value)
        {
        	$(inputEl).addClass("checked_box");
        }
        var hiddenEl = createElement( "input", null, {
            type: "hidden",
            name: prop,
            value: "false"
        });
        var divEl = createElement("div");
        divEl.appendChild(inputEl);
        divEl.appendChild(hiddenEl);
        return divEl;
        
    } else if (typeof(type) == "object") { // predefined values
    
        var selectEl = createElement( "select", null, {
                name: prop,
                style: { width: width }
            });

    	var labels = type.labels;
    	var values = type.values;
        for (var idx in labels) {
            var optionEl = createElement( "option", null, {
                    value: values[idx]
                }, [ text( labels[idx] ) ]);
                
            if (value == values[idx])
            {
                optionEl.setAttribute( "selected", true );
            }
            selectEl.appendChild( optionEl );
    	}
        
    	return selectEl;
        
    } else if (type == 12) { // Metatype 1.2: Attr type 12 is PASSWORD
        return createElement( "input", null, {
            type: "password",
            name: prop,
            value: value,
            style: { width: width }
        });
    } else { // Simple
        var textareaEl = createElement( "textarea", null, {
            name: prop,
            style: { width: width }
        });
        addText(textareaEl, value.toString());
        $(textareaEl).autosize();
        return textareaEl;
    }
}

function createMultiSelect(/* Element */ parent, prop, values, options, width) {
    // convert value list into 'set'
    var valueSet = new Object();
    for (var idx in values) {
    	valueSet[ values[idx] ] = true;
    }
    
   	var labels = options.labels;
   	var values = options.values;
   	for (var idx in labels) {
    
        var inputEl = createElement( "input", null, {
                type: "checkbox",
                name: prop,
                value: values[idx] 
            });
    
        if (valueSet[ values[idx] ])
        {
            inputEl.setAttribute( "checked", true );
        }
        
        var labelEl = createElement( "label", "multiselect" );
        labelEl.appendChild( inputEl );
        addText( labelEl, labels[idx] );
        
        parent.appendChild( labelEl );
   	}
}


function addValue(prop, vidx)
{
    var span = document.getElementById(vidx);
    if (!span)
    {
        return;
    }
    var newSpan = createSpan(prop, '');
    span.parentNode.insertBefore(newSpan, span.nextSibling);
    // FIX for IE6 and above: checkbox can only be checked after it is in the DOM
    $(".checked_box").attr("checked", true).removeClass("checked_box");
	//$(span).ready(initStaticWidgets);
}

function removeValue(vidx)
{
    var span = document.getElementById(vidx);
    if (!span)
    {
        return;
    }
    span.parentNode.removeChild(span);
}

function configConfirm(/* String */ message, /* String */ title, /* String */ location)
{
    if (title) {
        message += "\r\n" + i18n.del_config + title;
    }
    if (location) {
        message += "\r\n" + i18n.del_bundle + location;
    }
    
    return confirm(message);
}

function deleteConfig(/* String */ configId, /* String */ bundleLocation)
{
    if ( configConfirm(i18n.del_ask, configId, bundleLocation) ) {
	$.post(pluginRoot + '/' + configId, param.apply + '=1&' + param.dele + '=1', function() {
	    document.location.href = pluginRoot;
	}, 'json');
	return true;
    }
    return false;
}

function unbindConfig(/* String */ configId, /* String */ bundleLocation)
{
    if ( configConfirm(i18n.unbind_ask, configId, bundleLocation) ) {
	$.post(pluginRoot + '/' + configId, param.unbind + '=1', function() {
	    document.location.href = pluginRoot + '/' + configId;
	}, 'json');
	return true;
    }
    return false;
}

function addConfig(conf) {
	var tr = configRow.clone().appendTo(configBody);
	
	if (!conf.has_config) {
		tr.find('td:eq(0)').empty();
	}

	// rendering name - indented if factory pid is set
	var nms = tr.find('td:eq(1) div');
	if (conf.fpid) { 
        if (conf.nameHint) {
		    nms.after("<span title='" + conf.id + "'>" + conf.nameHint + "</span>");
		} else {
			nms.after(conf.id);
        }
		tr.attr('fpid', conf.name);
	} else {
		nms.addClass('ui-helper-hidden').parent().text(conf.name);
	}

	tr.find('td:eq(1)').click(function() { // name & edit
		configure(conf.id);
	});
	tr.find('td:eq(2)').html(conf.bundle ? '<a href="' + pluginRoot + '/../bundles/' + conf.bundle + '">' + conf.bundle_name + '</a>' : '-'); // binding
	
	// buttons
	tr.find('li:eq(0)').click(function() { // edit
		configure(conf.id);
	});
	tr.find('li:eq(2)').click(function() { // delete
	    	deleteConfig(conf.id, conf.bundle_name);
	});
	if (conf.bundle) {
	    	tr.find('li:eq(1)').click(function() { // unbind
        		unbindConfig(conf.id, conf.bundle_name);
        	}).removeClass('ui-state-disabled');
	}
}

function addFactoryConfig(conf) {
	var tr = factoryRow.clone().appendTo(configTable).attr('fpid', conf.name);
	//tr.find('td:eq(1)').text(conf.id); // fpid
	tr.find('td:eq(1)').text(conf.name).click(function() { // name & edit
		configure(conf.id, true);
	});
	// buttons
	tr.find('li:eq(0)').click(function() { // edit
		configure(conf.id, true);
	});
}

function treetableExtraction(node) {
	var td = $(node);
	var text = td.text();
	if (!text) return text;

	// current sort order
	var desc = $(this)[0].sortList[0][1];

	var row = td.parent();
	var fpid = row.attr('fpid');
	
	// factory row
	if ( row.hasClass('fpid') && fpid) return fpid + (desc==1?1:0) + text;

	// bundle or name row
	if ( fpid ) return fpid + desc + text;

	return mixedLinksExtraction(node);
};

$(document).ready(function() {
	configContent = $('#configContent');
	// config table list
	configTable   = $('#configTable');
	configBody    = configTable.find('tbody');
	configRow     = configBody.find('tr:eq(0)').clone();
	factoryRow    = configBody.find('tr:eq(1)').clone();
	
	// setup button - cannot inline in dialog option because of i18n
	var _buttons = {};
	_buttons[i18n.abort] = function() {
		$(this).dialog('close');
	}
	_buttons[i18n.reset] = function() {
		var form = document.getElementById('editorForm');
		if (form) form.reset();
	}
	_buttons[i18n.del] = function() {
	    	if (deleteConfig($(this).attr('__pid'), $(this).attr('__location'))) {
			$(this).dialog('close');
	    	}
	}
	_buttons[i18n.unbind_btn] = function() {
	    	unbindConfig($(this).attr('__pid'), $(this).attr('__location'));
	}
	_buttons[i18n.save] = function() {
		if ( $("#locinput").val() === i18n.unbound ) {
			$("#lochidden").val("");			
		} else {
			$("#lochidden").val($("#locinput").val());			
		}
		
		// get all the configuration properties names
		var propListElement = $(this).find('form').find('[name=propertylist]');
		var propListArray = propListElement.val().split(',');

		// removes the properties, that are unchecked
		$(this).find('form').find('input.optionality:not(:checked)').each( function(idx, el) {
			var name = $(el).attr('name').substring(3); // name - 'opt'
			var index = propListArray.indexOf(name);
			if (index >= 0) {
				propListArray.splice(index, 1);
			}
		});
		propListElement.val(propListArray.join(','));

		$.post(pluginRoot + '/' + $(this).attr('__pid'), $(this).find('form').serialize(), function() {
			// reload on success - prevents AJAX errors - see FELIX-3116
			document.location.href = pluginRoot; 
		});
		$(this).dialog('close');
	}
	// prepare editor, but don't open yet!
	editor = $('#editor').dialog({
		autoOpen : false,
		modal    : true,
		width    : '90%',
		closeText: i18n.abort,
		buttons  : _buttons
	});
	editorMessage = editor.find('p');

	// display the configuration data
	$(".statline").html(configData.status ? i18n.stat_ok : i18n.stat_missing);
	if (configData.status) {
		configBody.empty();
		var factories = {};

		for(var i in configData.pids) {
			var c = configData.pids[i];
			if (c.fpid) {
				if (!factories[c.fpid]) factories[c.fpid] = new Array();
				factories[c.fpid].push(c);
			} else {
				addConfig(c);
			}
		}
		for(var i in configData.fpids) {
			addFactoryConfig(configData.fpids[i]);

			var fpid = configData.fpids[i].id;
			var confs = factories[ fpid ];
			if (confs) {
			    for (var j in confs) {
			        addConfig(confs[j]);
			    }
			    delete factories[ fpid ];
			}
		}
		for(var fpid in factories) {
		    var flist = factories[fpid];
		    for(var i in flist) {
		        delete flist[i].fpid; // render as regular config
		        addConfig(flist[i]);
		    }
		}
		initStaticWidgets(configTable);

		// init tablesorte
		configTable.tablesorter({
			headers: {
				0: { sorter: false },
				3: { sorter: false }
			},
			sortList: [[1,1]],
			textExtraction: treetableExtraction
		}).bind('sortStart', function() { // clear cache, otherwise extraction will not work
			var table = $(this).trigger('update'); 
		}).find('th:eq(1)').click();
	} else {
		configContent.addClass('ui-helper-hidden');
	}
	if (selectedPid) configure(selectedPid);
});