var _ = require('underscore');
var BaseWidget = require('./base');
var debug = require('debug')('windshaft:widget:formula');

var dot = require('dot');
dot.templateSettings.strip = false;

var formulaQueryTpl = dot.template([
    'SELECT',
    '{{=it._operation}}({{=it._column}}) AS result,',
    '(SELECT count(1) FROM ({{=it._query}}) _cdb_formula_nulls WHERE {{=it._column}} IS NULL) AS nulls_count',
    'FROM ({{=it._query}}) _cdb_formula'
].join('\n'));

var VALID_OPERATIONS = {
    count: true,
    avg: true,
    sum: true,
    min: true,
    max: true
};

var TYPE = 'formula';

/**
 {
     type: 'formula',
     options: {
         column: 'name',
         operation: 'count' // count, sum, avg
     }
 }
 */
function Formula(query, options) {
    if (!_.isString(options.operation)) {
        throw new Error('Formula expects `operation` in widget options');
    }

    if (!VALID_OPERATIONS[options.operation]) {
        throw new Error("Formula does not support '" + options.operation + "' operation");
    }

    if (options.operation !== 'count' && !_.isString(options.column)) {
        throw new Error('Formula expects `column` in widget options');
    }

    BaseWidget.apply(this);

    this.query = query;
    this.column = options.column || '1';
    this.operation = options.operation;
}

Formula.prototype = new BaseWidget();
Formula.prototype.constructor = Formula;

module.exports = Formula;

Formula.prototype.sql = function(psql, override, callback) {
    if (!callback) {
        callback = override;
        override = {};
    }

    var _query = this.query;
    var formulaSql = formulaQueryTpl({
        _query: _query,
        _operation: this.operation,
        _column: this.column
    });

    debug(formulaSql);

    return callback(null, formulaSql);
};

Formula.prototype.format = function(result) {
    var formattedResult = {
        operation: this.operation,
        result: 0,
        nulls: 0
    };

    if (result.rows.length) {
        formattedResult.operation = this.operation;
        formattedResult.result = result.rows[0].result;
        formattedResult.nulls = result.rows[0].nulls_count;
    }

    return formattedResult;
};

Formula.prototype.getType = function() {
    return TYPE;
};

Formula.prototype.toString = function() {
    return JSON.stringify({
        _type: TYPE,
        _query: this.query,
        _column: this.column,
        _operation: this.operation
    });
};
