Source: Models/TableStyle.js

'use strict';

/*global require*/
var clone = require('terriajs-cesium/Source/Core/clone');
var defaultValue = require('terriajs-cesium/Source/Core/defaultValue');
var defined = require('terriajs-cesium/Source/Core/defined');
var freezeObject = require('terriajs-cesium/Source/Core/freezeObject');
var when = require('terriajs-cesium/Source/ThirdParty/when');

var inherit = require('../Core/inherit');
var TableColumnStyle = require('./TableColumnStyle');
var updateFromJson = require('../Core/updateFromJson');

/**
 * A set of properties that define how a table, such as a CSV file, should be displayed.
 * If not set explicitly, many of these properties will be given default or guessed values elsewhere,
 * such as in CsvCatalogItem.
 *
 * @alias TableStyle
 * @constructor
 * @extends TableColumnStyle
 *
 * @param {Object} [options] The values of the properties of the new instance. Options may include all those options found in TableColumnStyle, plus:
 * @param {String} [options.regionVariable] The name of the variable (column) to be used for region mapping.
 * @param {String} [options.regionType] The identifier of a region type, as used by RegionProviderList.
 * @param {String} [options.dataVariable] The name of the default variable (column) containing data to be used for scaling and coloring.
 * @param {String|Integer|null} [options.timeColumn] The column name or index to use as the time column. Defaults to the first one found.
 *        Pass null for none. Pass an array of two, eg. [0, 1], to provide both start and end date columns.
 * @param {String|Integer} [options.xAxis] The column name or index to use as the x-axis, if charted. Defaults to the first one found.
 * @param {Object} [options.columns] Column-specific styling, with the format { columnIdentifier1: tableColumnStyle1, columnIdentifier2: tableColumnStyle2, ... },
 *                 where columnIdentifier is either the name or the column index (zero-based).
 */
var TableStyle = function(options) {
    options = defaultValue(options, defaultValue.EMPTY_OBJECT);

    TableColumnStyle.call(this, options);

    /**
     * The name of the variable (column) to be used for region mapping.
     * @type {String}
     */
    this.regionVariable = options.regionVariable;

    /**
     * The identifier of a region type, as used by RegionProviderList.
     * @type {String}
     */
    this.regionType = options.regionType;

    /**
     * The name of the default variable (column) containing data to be used for scaling and coloring.
     * @type {String}
     */
    this.dataVariable = options.dataVariable;

    /**
     * The column name or index to use as the time column. Defaults to the first one found. Pass null for none.
     * Pass an array of two, eg. [0, 1], to provide both start and end date columns.
     * @type {String|Integer|String[]|Integer[]|null}
     */
    this.timeColumn = options.timeColumn;

    /**
     * The column name or index to use as the time column. Defaults to the first one found. Pass null for none.
     * Pass an array of two, eg. [0, 1], to provide both start and end date columns.
     * @type {String|Integer}
     */
    this.xAxis = options.xAxis;

    /**
     * Column-specific styling, with the format { columnIdentifier1: tableColumnStyle1, columnIdentifier2: tableColumnStyle2, ... },
     * where columnIdentifier is either the name or the column index (zero-based).
     * @type {Object}
     */
    this.columns = objectToTableColumnStyle(options, []);  // If any promises are created (thanks to colorPalette), they are lost here.

};

inherit(TableColumnStyle, TableStyle);

// When columns is updated via json, turn it into TableColumnStyle objects.
// Do this in updateFromJson so we can keep track of the promises required by the colorPalette option.
// This also has the advantage of not using the TableColumnStyle constructor to set the properties, which causes problems with colorPalette too.
TableStyle.prototype.updateFromJson = function(json, options) {
    var promises = [updateFromJson(this, json, options)];
    this.columns = objectToTableColumnStyle(json, promises, options);
    return when.all(promises);
};

TableStyle.prototype.updaters = clone(TableStyle.prototype.updaters);

// Disable the 'columns' updaters, so we do not update columns here; do it directly in the updateFromJson function.
// Why? TableColumnStyle's colorPalette actually returns a promise. The updaters can't handle a promise, but updateFromJson can.
TableStyle.prototype.updaters['columns'] = function(tableStyle, json, propertyName) {
};

freezeObject(TableStyle.prototype.updaters);

function objectToTableColumnStyle(json, promises, options) {
    if (defined(json.columns)) {
        var columns = {};
        for (var propertyName in json.columns) {
            if (json.columns.hasOwnProperty(propertyName)) {
                columns[propertyName] = new TableColumnStyle();
                var thisPromise = columns[propertyName].updateFromJson(json.columns[propertyName], options);
                if (defined(thisPromise)) {
                    promises.push(thisPromise);
                }
            }
        }
        return columns;
    }

}

module.exports = TableStyle;