//Copyright 2007 Roman Ardern-Corris
//Licenced to 3legs.com

/*
    This object is a common ancestor to any ligo component that visualises a dataset
    Currently it is used for the following components:
        ligoGrid
        ligSelect

    FIXME:
        ligoButton should also use this

    This component is not designed to ever be instantiated directly, it is abstract
*/


extend(ligoDSVisualiser, ligoCommon);

function ligoDSVisualiser (paramsObj) {
    //Constructor

    //all parameters are passed in JSON notation

    //Attributes
    this.instanceName;          //The name of the variable that is used for this object (I know this is horrible)
    this.Dataset;               //Instance of a ligoDataset
    this.div;                   //The name of the target div
    this.display = [];          //All display stuff (css_*, only_display_cols_with_label)
    this.selectedRowId;         //Holds the html id of the current row
    this.colsToDisplay = [];    //Array of columns to display [true, true, false, true], display cols 0,1 and 3 not 2.
    this.initialNoRowSel;       //if true then no row is selected (call setCurrentRow(-1))
    this.nullAs = '';           //string to display when a value is null
    this.displayFormats = {};   //this is a replacement client side version of dataset.formats (which will be deprecated)
                                //  keys can either be column index or a field name
    this.displayFormatsColIdx = []; //array linking column numbers to the appropriate formatspec (readonly)
    this.active = true;         //flag to stop rendering of component, must be implemented in each sub class

    ligoDSVisualiser.superclass.call(this, paramsObj);

    this._div = $(this.div);

    this.Dataset.addDependant(this);

}

//#####################################################################################################################

ligoDSVisualiser.prototype.hello = function () {
    alert("Grid: Hello");
}

//#####################################################################################################################

ligoDSVisualiser.prototype.setActive = function (active) {
    this.active = active;
    this.render();
}

//#####################################################################################################################

ligoDSVisualiser.prototype._init_display_formats = function () {
    //This method populates the displayFormatsColIdx attribute.
    //This attribute acts like a cache linking column number to the correct formatspec
    
    //the field identifier can either be numeric (for a column index) or a string to use the field name
    //the special field identifier * can be used to set a default
    
    //handle setting a default formatspec (the * char)
    if (this.displayFormats['*']) {
        var default_formatspec = this.getFormatSpec( this.displayFormats['*'] );
        var num_columns = this.Dataset.data[0].length
        for (var i=0; i<num_columns; i++) {    //use the first row of the dataset to get the column indexes
            this.displayFormatsColIdx[i] = default_formatspec;
        }
    }
                                
    //Now apply specific formats for the columns
    for (var field_identifier in this.displayFormats) {
        var columnIdx;
        var format;
        
        //skip the default identifier character, we will handle this later
        if (field_identifier == '*') {
            continue;
        }
        
        //assign the columnIdx
        if( isNaN(field_identifier) ) {    //this is a field name            
            columnIdx = this.Dataset.nameIndex[field_identifier];
        }
        else {  //this is a column index
            columnIdx = field_identifier;
        }
               
        //use the columnIdx to cache the formatspec
        if (columnIdx) {    //we have found our column
            var format = this.displayFormats[field_identifier];
            this.displayFormatsColIdx[columnIdx] = this.getFormatSpec( format );
        }
    }
    
}

//#####################################################################################################################

ligoDSVisualiser.prototype.getFormatSpec = function (format) {
    //This uses the short format name that is passed in the objects construction
    //and returns the more verbose format spec description   
    
    var format_specs = {
        'TEXT'      :   {  'format' : 'TEXT',       'basic' : 'TEXT', 'aggregatable' : false },
        'NUMERIC'   :   {  'format' : 'NUMERIC',    'basic' : 'NUMERIC', 'aggregatable' : true },
        'THOUSANDS' :   {  'format' : 'THOUSANDS',  'basic' : 'NUMERIC', 'aggregatable' : true },
        'CURRENCY'  :   {  'format' : 'CURRENCY',   'basic' : 'NUMERIC', 'aggregatable' : true },
        'INT'       :   {  'format' : 'INT',        'basic' : 'NUMERIC', 'aggregatable' : true },
        'SENTENCE'  :   {  'format' : 'SENTENCE',   'basic' : 'TEXT', 'aggregatable' : false },
        'UPPER'     :   {  'format' : 'UPPER',      'basic' : 'TEXT', 'aggregatable' : false },
        'LOWER'     :   {  'format' : 'LOWER',      'basic' : 'TEXT', 'aggregatable' : false },
        'DAY'       :   {  'format' : 'DAY',        'basic' : 'TEXT', 'aggregatable' : false },
        'DAY0'      :   {  'format' : 'DAY0',       'basic' : 'TEXT', 'aggregatable' : false },
        'MONTH'     :   {  'format' : 'MONTH',      'basic' : 'TEXT', 'aggregatable' : false },
        'MONTH0'    :   {  'format' : 'MONTH0',     'basic' : 'TEXT', 'aggregatable' : false },
        'DATE'      :   {  'format' : 'DATE',       'basic' : 'DATE', 'aggregatable' : false }, //date format should be as mysql (2009-05-14 21:20:01)
        'TIME'      :   {  'format' : 'TIME',       'basic' : 'DATE', 'aggregatable' : false },
        'DATETIME'  :   {  'format' : 'DATETIME',   'basic' : 'DATE', 'aggregatable' : false }
    };
    
    if (! format) { //if there is no format then use TEXT
        format = 'TEXT';
    }
    
    return( format_specs[format] );
    
}

//#####################################################################################################################

ligoDSVisualiser.prototype.applyFormat = function (value, formatspec) {
    
    if (formatspec != null) {
        //handle null values
        //displayValue() will format nulls if we do not have a format
        if (formatspec.basic == 'NUMERIC') {
            if (value == null || value == '') {
                value = 0;
            }
        }
        else if (formatspec.basic == 'TEXT') {
            if (value == null) {
                value = '';
            }
        }
        else if (formatspec.basic == 'DATE') {
            if (value == null) {
                value = '0000-00-00 00:00:00';
            }
        }
        
        
        if (formatspec.format == 'CURRENCY') {
            value = parseFloat(value);
            if (typeof(value.toFixed) == 'function') {
                value = value.toFixed(2);
                value = this.addCommasToNumber(value);
            }
        }
        
        if (formatspec.format == 'INT') {
            value = parseInt(value);
        }
        
        if (formatspec.format == 'NUMERIC') {
            value = parseFloat(value);
            value = this.addCommasToNumber(value);
        }
        
        if (formatspec.format == 'UPPER') {
            if (typeof(value.toUpperCase) == 'function') {
                value = value.toUpperCase();
            }
        }
        
        if (formatspec.format == 'DATETIME') {
            value = this.formatDATETIME(value, formatspec);
        }
        
    }
    
    
    return(value);
    
}

//#####################################################################################################################

ligoDSVisualiser.prototype.parseDate = function (date_string) {
    //date format is 2009-05-14 21:20:01 (yyyy-mm-dd hh:mm:ss)
    var date = {};
    date.year = date_string.substr(0,4);
    date.month = date_string.substr(5,2);
    date.day = date_string.substr(8,2);
    date.hour = date_string.substr(11,2);
    date.min = date_string.substr(14,2);
    date.sec = date_string.substr(17,2);
    
    return(date);
    
}

//#####################################################################################################################

ligoDSVisualiser.prototype.formatDATETIME = function (value, formatspec) {
    var date = this.parseDate(value);
    
    output_string = date.day + '/' + date.month + '/' + date.year + '-' + date.hour + ':' + date.min;
        
    return(output_string);
    
}

//#####################################################################################################################

ligoDSVisualiser.prototype.addCommasToNumber = function (value) {
    
	value += '';
	var x = value.split('.');
	var x1 = x[0];
	var x2 = x.length > 1 ? '.' + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
    
	while ( rgx.test(x1) ) {
		x1 = x1.replace(rgx, '$1' + ',' + '$2');
	}
    
	return( x1 + x2 );
}

//#####################################################################################################################

ligoDSVisualiser.prototype._set_cols_to_display = function () {

    if (this.display.only_display_cols_with_label) {
        for (var i=0; i < this.Dataset.columnLabels.length; i++) {
            if (this.Dataset.columnLabels[i] != 'undef') {
                this.colsToDisplay[i] = true;
            }
        }
    }
    else {
        this.colsToDisplay = this.Dataset.columnNames;
    }

}

//#####################################################################################################################

ligoDSVisualiser.prototype.displayValue = function (value, columnIdx) {
    //this is a wrapper around displaying a value
    //columnIdx is used to get the format for this column
    
    //console.log('Attempting format for columnIdx: ' + columnIdx);
    if (columnIdx != null) {   //try to apply a format
        var formatspec = this.displayFormatsColIdx[columnIdx];
        if (formatspec) {
            value = this.applyFormat( value, this.displayFormatsColIdx[columnIdx] );
        }
    }
    
    //only set to our default nullAs value after we have tried to apply a format
    //(the formatting code may wish to apply its own default for null values)
    if (value == null) {
        value = this.nullAs;
    }
    
    return(value);

}

//#####################################################################################################################

ligoDSVisualiser.prototype.render = function () {
    //abstract
    alert('Render() called in ligoDSVisualiser! Do not use me directly, you should use a subclass that implements render()');
}

//#####################################################################################################################

ligoDSVisualiser.prototype._label_for_column = function (column_index) {

    if (this.Dataset.columnLabels[column_index]) {
        return( this.Dataset.columnLabels[column_index] );
    }
    else {
        return( this.Dataset.columnNames[column_index] );
    }

}

//#####################################################################################################################

ligoDSVisualiser.prototype.makeRowId = function (row_num) {
    return(this.instanceName + '_' + row_num);
    //return(row_num);
}

//#####################################################################################################################

ligoDSVisualiser.prototype.highlightRow = function (row_num) {

    //store the selected row id
    this.selectedRowId = row_num;

}

//#####################################################################################################################

ligoDSVisualiser.prototype.onRowClick = function (row_num) {
    // Tell the dataset that we have focused a row
    this.Dataset.forceNextCallback();
    this.Dataset.setCurrentRow(row_num);
}

//#####################################################################################################################

ligoDSVisualiser.prototype.onRowDblClick = function (row_num) {
    //tell the dataset that we have focused a row
    this.Dataset.forceNextCallback();
    this.Dataset.setCurrentRow(row_num);
}

//#####################################################################################################################
//Standard callback handlers follow

ligoDSVisualiser.prototype._before_render = function () {
    
    this._init_display_formats();
}

//#####################################################################################################################

ligoDSVisualiser.prototype.onDS_dataLoaded = function (source) {
    //Sent by a dataset to tell us that the data has been loaded
    //Standard action is for us to render
    
    
    
    //FIXME: this should just be called by ligoDSVisualiser.prototype.onDS_dataLoaded()
    //but inheritance is not working correctly, so we are going to fudge this into the descendants methods
    this._init_display_formats();
    
    this.render();
}

//#####################################################################################################################

ligoDSVisualiser.prototype.onDS_newData = function (source) {
    //Dataset has changed its data

    this.render();
}

//#####################################################################################################################

ligoDSVisualiser.prototype.onDS_currentRowChange = function (source) {
    //Selected row has changed, so we want to highlight the current row

    this.highlightRow(source.currentRowNum);

}

//#####################################################################################################################
