/* 
   methods for editing index params
   
*/

function arrays_equal(a,b) {
	if (b.length !== a.length) { return false; }
	var as = a.sort();
	var bs = b.sort();
	for (var i=0; i<as.length; i+=1){
		if ( as[i] !== bs[i] ) {
			return false;
		}
	}
	return true;
}

function AlterIndexPanel(rdbAdmin,dbMgr,tablePanel,sqlPanel)
{
	this.rdbAdmin = rdbAdmin;
	this.dbMgr = dbMgr;
	this.tablePanel = tablePanel;
	this.tableId = 'alter-index-table';
	this.panelId = 'alter-index-panel';
	this.maxRowId = 0;
    this.sqlPanel = sqlPanel;
	
	this.init_handlers = function() {
		// initialize click handlers
		//
		var that = this;
		var $table = $('#'+this.tableId);
		$('#alter-index-btn').click(function() {
            that.show();
        });
		$('#alter-index-panel-btn').click(function () {
            that.alter();
        });
		$('#alter_index_add_row').click(function () {
            that.addRowToTable(this);
        });
		$table.find('*.alter_index_del_row').live('click', function() {
            that.delRowFromTable(this);
        });
		$table.find(':input[id^="aindex-itype"]').live('change', function() {
			that.purgeUntyped();
			that.addRowToTable(this);
		});
		$table.find(':input[id^="aindex-flist"]').live('change', function() {
			that.addColumnSpan(this);
		});
		// add click handler to edit query
		$('#aindex-sql-edit').click(function() { 
			var query = $('#alter-index-sql-show').html();
			that.sqlPanel.showQuery(query);
		});
		// handler updates sql display for any change in the data entry
		$table.find('*:input').live('change',function() {
			that.onChange(this);
		});
	};
		  
	this.show = function(mode)
	{
		this.rdbAdmin.resetMessages();
		this.buildTable();
		this.rdbAdmin.showPanel("alter-index-panel");
		this.rdbAdmin.setHeading("Alter indexes: " +
                                 this.tablePanel.sqlTable.tableName);
        this.onChange();
	};
	
	this.delRowFromTable = function(domel)
	{
		var $table = $('#'+this.tableId);
		// if this is last row - don't delete
		if ($table.find('tbody tr:visible').length === 1) {
			alert('Table must have at least one row!');
			return false;
		}
		// remove html
		var $row = $(domel).closest('tr');
		$row.remove();
        this.onChange();
		return true;
	};
	
	this.addRowToTable = function(elem)
	{
		// function to add row# to end of id values
		function make_id_unique($el,i) {
			var id = $el.attr('id');
			if (id && id.length && id.substr(id.length-1)==='_') {
				$el.attr('id',id+i);
			}
		}
		var newrowId = parseInt(this.maxRowId,10) + 1;
		var $table = $('#'+this.tableId);
		// clone hidden row
		var $row = $table.find('#aindex-tr-pattern_').clone().show();
		// new IDs to cloned row and it's children
		$row.find('#aindex-fopts-0_').attr('style','');
		$row.attr('id','aindex-tr_'+this.maxRowId);
		// update all *_ ids with iteration number *_#
		$row.find('td')
			   .add('select',$row)
			   .add('input',$row)
			   .each(function (i) {
			make_id_unique($(this),i);
		});
		// attach new row
		$table.append($row);
		this.maxRowId = newrowId;
		return newrowId;
	};
	
	this.addColumnSpan = function(element)
	{
		// if this is not last element - return false
		if ( $(element).parent().next().length !== 0 ) {
			return;
		}
		var $row = $(element).closest('tr');
		var $fldspan = $row.find('*[id^="aindex-fopts-"]:last').clone();
		var idparts = $fldspan.attr('id').split(/[\-_]/g);
		var colnum = parseInt(idparts[2],10),
            rownum = idparts[3];
		$fldspan.attr('id','aindex-fopts-'+(colnum+1)+'_'+rownum);
		$row.find('td:eq(2)').append($fldspan);
	};
	
	this.purgeUntyped = function()
	{
		var $table = $('#'+this.tableId);
		$table.find('tr:visible').each(function() {
			var $row = $(this); 
			var $val = $row.find('*[id^="aindex-itype"]').val();
			if ( !$val && $val !== undefined ) { $row.remove(); }
		});
	};

	this.onChange = function(domel)
	{
		// var $row = $(domel).closest('tr');
		// var $typeSelect = $row.find('td:eq(1) select');
		this.updateSQLDisplay();
		return false;
	};
	
	this.updateSQLDisplay = function ()
	{
		this.dirty = true;
		var sqlObj = this.createSQLQueryString();
		if ( sqlObj.sql  ) {
            sql = sqlObj.sql;
        }
        else {
			sql = '-- nothing to do yet';
		} 
		$('#'+this.panelId+' #alter-index-sql-show').html(sql);
	};
	
	this.buildTable = function()
	{
		var $table = $('#'+this.tableId);
		// function to add row# to end of id values
		function make_id_unique($el,i) {
			var id = $el.attr('id');
			if (id && id.length && id.substr(id.length-1)==='_') {
				$el.attr('id',id+i);
			}
		}
		// clone hidden row
		var $tplrow = $table.find('#aindex-tr-prior_');
		var $row = $table.find('#aindex-tr-pattern_');
		$table.empty(); //.append($hdr);
		$table.append($row).append($tplrow);
		// add field names to template row
		var fields = this.tablePanel.sqlTable.fields;
		$row.find('#aindex-flist-0_').empty().append($('<option>'));
		for (var i=0; i<fields.length; i+=1) {
			var $opt = $('<option>');
			$opt.html(fields[i].columnName);
			$row.find('#aindex-flist-0_').append($opt);
		}
		// get indexes from tablePanel
		var indexes = this.tablePanel.indexes;
		if (indexes === null || indexes === undefined) {
			return false;
		}
		// put each index in display table
        var k;
		function make_unique() {
			make_id_unique($(this),k);
		}
        for (k=0; k<indexes.length; k+=1) {
			var index = indexes[k];
            var isUnique = index[1], isPrimary = index[2],
                name = index[3], columns = index[6];
			// add html row to table
			var $newrow = $tplrow.clone(true).show();
			// add index name
			$newrow.find('#aindex-iname_').val(name);
			$newrow.find('#aindex-ioldname_').val(name);
			// add index type
			var itypestr = isPrimary ? 'PRIMARY' :
                          (isUnique ? 'UNIQUE' : 'INDEX');
			$newrow.find('#aindex-itype_').closest('td').html(itypestr);
            if (isPrimary) {
                $newrow.find('input:image').css('visibility','hidden');
            }
			// add span with field select control for each field in index
            var colstr = columns.join(', ');
			// clone span
            var $span = $newrow.find('#aindex-fopts_').remove().show();
            // insert column idx 'j' into IDs
            $span.html(colstr).attr('style','');
            $newrow.find('td:eq(2)').append($span);
			// add new row to table
			$newrow.attr('id','aindex-tr_'+this.maxRowId);
			// update all *_ ids with iteration number *_#
			$newrow.find('td')
				   .add('select',$newrow)
				   .add('input',$newrow)
				   .each(make_unique);
			$table.append($newrow);
			this.maxRowId = parseInt(this.maxRowId,10) + 1;
		}
		// add empty row
		this.addRowToTable();
		return true;
	};
	
    this.createSQLQueryString = function ()
    {
		var that = this;
		var tableName = that.tablePanel.sqlTable.tableName;
		// functions to create SQL statements
		function make_rename_statement(oldiName,iName) {
			var sql = 'ALTER INDEX '+quoteIdentifier(oldiName)+
			          ' RENAME TO '+quoteIdentifier(iName);
			return sql;
		} 
		function make_drop_statement(oldiName) {
			var sql = 'DROP INDEX '+quoteIdentifier(oldiName);
			return sql;
		}
		function make_create_statement(iName,iType,iFields)	{
			var sql;
			if (iType === 'UNIQUE') {
				sql = 'CREATE UNIQUE INDEX '+quoteIdentifier(iName)+
				      ' ON '+ quoteIdentifier(tableName)+
					  '('+(iFields.join(','))+')';
			}
			else {
				sql = 'CREATE INDEX '+quoteIdentifier(iName)+
				      ' ON '+ quoteIdentifier(tableName)+
					  '('+(iFields.join(',')) + ')';
			}
			return sql;
		}
		// grab inputs
		var indexes = this.tablePanel.indexes;
		var $table = $('#'+this.tableId);
		// iterate over html-table-rows, generate a list of sql
		var sql = [], knownIndexes = [], status = 'ok';
		$table.find('tr:gt(1)').each(function(i) {
			// for each html row (aftet 2 tpl lines), gather data into variables
			var $row = $(this);
			var iName = $row.find('*[id^="aindex-iname_"]').val();
            // skip empty rows
            if ( !iName ) {
                return true;
            }
			var oldiName = $row.find('*[id^="aindex-ioldname_"]').val();
            if ( oldiName ) {
                knownIndexes.push(oldiName);
                if ( oldiName && iName !== oldiName ) {
                    sql.push(make_rename_statement(oldiName,iName));
                }
            }
            else {
                var iType = $(this).find('select[id^="aindex-itype_"]').val();
                var iFields = [];
                $row.find('*[id^="aindex-flist-"]').each( function() {
                    if ($(this).val() !== '') {
                        iFields.push( $(this).val() );
                    }
                });
                if ( !iName ) {
                    return true;
                }
                // quit if incomplete line
                else if ( !iType || !iFields.length ) {
                    status = 'notok';
                    return false;
                }
				else {
					sql.push(make_create_statement(iName,iType,iFields));
				}
			}
			return true;
		});
        // look for 'unknown' indexes not kept in form, that need to be dropped
        for (var idx in indexes) {
            if (indexes.hasOwnProperty(idx)) {
                var idxname = indexes[idx][3];
                if ( $.inArray(idxname,knownIndexes) === -1 ){
                    sql.push(make_drop_statement(idxname));
                }
            }
        }
        var returnVal = {};
        returnVal.sql = sql.join(';\n');
        returnVal.stat = status;
        return returnVal;
    };

	this.alter = function()
	{
        var that = this;
		// create an aggregate sql statement, and execute it.
        var sqlObj = this.createSQLQueryString();
        var tableName = this.tablePanel.sqlTable.tableName;
		function tbshow() {
			that.tablePanel.show(tableName);
		}
		if ( sqlObj.stat === 'incomplete' ) {
			alert('Alter table data is incomplete.');
		}
		else if ( sqlObj.sql.length ) {
			this.dbMgr.sqlEngine.query( { 'q' : sql,
                                          'callback' : tbshow,
										  'errback' : errback });
		}
		else {
			alert('add or change an index');
		}
	};
}