'use strict';
/*
 * Functions which produce SQL string from SQL scope
 *
 */

reports.factory('sqlHelper', ['wizardSharedService', function(wizardSharedService) {

    var SQL = {};

    var $scope = {};
    $scope.Comparison  = Comparison;
    $scope.Logical     = Logical;
    $scope.Order       = Order;
    $scope.Limit       = Limit;


    SQL.setSQLScope = function (SQLScope) {
        $scope.SQL = SQLScope;
    };

    /* ---------------------SQL FUNCTIONS  ---------------------------------- */

    SQL.getSQL_SELECT  = function() {

        var select = 'SELECT ';
        var tmp    = new Array();

        // check if object is empty with _underscore.js
        if(_.isEmpty($scope.SQL.fields)) {
            return false;
        }

        // join fields into tmp array
        angular.forEach($scope.SQL.fields, function(field, key) {
            var fieldWithAlias = '';

            switch (field.dataType) {
                case 'real':
                case 'integer':
                    fieldWithAlias = 'cast(' + field.sqlField + ' AS ' + field.dataType + ') AS "' + field.label + '"';
                    break;
                default:
                    fieldWithAlias = field.sqlField + ' AS "' + field.label + '"';
            }

            tmp.push(fieldWithAlias);
        });

        if(tmp.length > 0) {
            //select = select + '\'' + tmp.join('\',\'') + '\'';  // wrap with quotes
            select = select +  tmp.join(', ');  // wrap with quotes
            return select;
        }

        return false;
    };


    SQL.getSQL_FROM = function() {
        let from = 'FROM ';
        let join_str = '';

        // find main table
        const mainTable = Object.keys($scope.SQL.tables).find(key => $scope.SQL.tables[key] === 'main');

        // if selected tables length is 1 then no need to iterate tables object
        if (Object.keys($scope.SQL.tables).length != 1) {
            angular.forEach($scope.SQL.tables, function(joinType, tableName){
                if (DCA_TABLES[tableName] === undefined) {
                    // this could happen when report has extra table that does not present in dca.js
                    // e.g. table has deleted from dca.js
                    notify.error('Table ' + tableName + ' is not currently supported for reports on this hub.');
                    return;
                }

                let pk_key = DCA_TABLES[tableName]['Keys'].primary_key;
                if (pk_key === undefined) {
                    notify.error('Table ' + tableName + ' has no primary_key property. Please ask your administrator to check DCA array.');
                    return;
                }

                switch (joinType) {
                    case 'leftJoin':
                        join_str +=  ' LEFT JOIN ' + tableName + ' ON ' + tableName + '.' + pk_key  + ' = ' + mainTable + '.' +  pk_key;
                        break;
                    case 'innerJoin':
                        join_str +=  ' INNER JOIN ' + tableName + ' ON ' + tableName + '.' + pk_key  + ' = ' + mainTable + '.' +  pk_key;
                        break;
                }
            });
        }

        from += mainTable + join_str;

        return from;
    };

    SQL.getSQL_WHERE   = function() {
        var where = 'WHERE ', fieldName = '';
        var tmp   = new Array();


        var selectedComparison = false;
        var selectedLogical    = false;


        // check if object is empty with _underscore.js
        if(_.isEmpty($scope.SQL.filters)) {
            return false;
        }

        angular.forEach($scope.SQL.filters, function(field, key){

            // no comparision selected
            if (field.comparison === undefined)
            {
                return; // works as continue
            }

            selectedComparison = _.find($scope.Comparison, function (item) {
                return item.value === field.comparison;
            });

            // check if this coparison required value (field > value), for example  a=5, a<6, if ignoreempty=false - this mean that value is required
            if (selectedComparison.ignoreempty === true && (field.value === '' || field.value === undefined) ) {
                return;  // works as continue
            }

            var str = '';
            var arr = [];



            // TODO:
            // find real sanitize method
            // clonedFrom has original field name
            fieldName = (field.clonedFrom !== undefined ? field.clonedFrom : field.sqlField);

            if (selectedComparison.ignoreempty === true)  // for comparision which require argument
            {
                // wrap value with quotes
                var  quotes = '';
                if(field.comparison === 'ILIKE' || field.comparison === 'NOT ILIKE') {
                    quotes = "'";
                }
                else if (field.dataType !== 'integer' && field.dataType !== 'real') {
                    quotes = "'";
                }

                switch (field.comparison) {
                    case "IN":
                    case "NOT IN":
                        str  = fieldName + ' ' + field.comparison + ' ' + '(\''+ (field.value) + '\')' ;
                        break;

                    case "ANY":
                    case "ALL":
                        str  = quotes + field.value + quotes  + "=" + field.comparison + "(" + fieldName + ')' ;
                        break;

                    default:
                        str  = fieldName + ' ' + field.comparison + ' ' +  quotes + (field.value) + quotes ;
                }


            }
            else { // for comparision which not require argument, like is null
                str  += fieldName + ' ' + field.comparison;
            }

            arr.condition = str;
            arr.logical   = field.logical;

            tmp.push(arr);

        }); // end foreach


        // return where strin, cut logical OR | AND from last filter
        if(tmp.length >0) {
            var length = tmp.length;
            var i = 0;
            for (i=0; i<length; i++)
            {
                if (i< (length-1) )
                {
                    where += ' ' + tmp[i].condition + ' ' + tmp[i].logical;
                }
                else
                {
                    where += ' ' + tmp[i].condition;
                }
            }
            return where;
        }


        return false;
    };

    SQL.getSQL_GROUPBY = function() {

        var groupby = 'GROUP BY ';
        var tmp    = new Array();

        // check if object is empty with _underscore.js
        if(_.isEmpty($scope.SQL.groupby)) {
            return false;
        }

        // join fields into tmp array
        angular.forEach($scope.SQL.groupby, function(field, key){
            // for real fields, we use their sqlfield name
            // for cloned fields, we use their name (alias)
            if(field.clonedFrom === undefined)
            {
                tmp.push(field.sqlField);
            }
            else
            {
                tmp.push(field.name);
            }
        });

        if(tmp.length > 0) {
            //groupby = groupby + '\'' + tmp.join('\',\'') + '\'';  // wrap with quotes
            groupby = groupby +  tmp.join(', ');  // wrap with quotes
            return groupby;
        }

        return false;
    };

    SQL.getSQL_ORDERBY = function() {

        var orderby = 'ORDER BY ';
        var tmp    = new Array();


        // check if object is empty with _underscore.js
        if(_.isEmpty($scope.SQL.orderby)) {
            return false;
        }

        // join fields into tmp array
        angular.forEach($scope.SQL.orderby, function(field, key){
            // for real fields, we use their sqlfield name
            // for cloned fields, we use their name (alias)

            var str = ' ' + field.order; // get order direction

            if(field.clonedFrom === undefined)
            {
                tmp.push(field.sqlField + str);
            }
            else
            {
                tmp.push(field.name + str);
            }
        });

        if(tmp.length > 0) {
            orderby = orderby + tmp.join(', ');  // wrap with quotes
            return orderby;
        }

        return false;
    };

    SQL.getSQL_LIMIT   = function() {
        var limit = '';
        if ($scope.SQL.limit !== null && $scope.SQL.limit !== '' && $scope.SQL.limit !== undefined) {
            limit = 'LIMIT ' + $scope.SQL.limit;
        }
        return limit;
    };

    SQL.getSQL_FULL    = function() {
        var select  = '';
        var from    = '';
        var where   = '';
        var groupby = '';
        var orderby = '';
        var limit   = '';

        select = SQL.getSQL_SELECT();
        if (select !== false) {
            $scope.SQL.SQLSTRING  = select;
        } else if (sessionStorage.getItem('sql')) {
           let sessionSQL = JSON.parse(sessionStorage.getItem('sql'));
           return sessionSQL.SQLSTRING || false;
        } else if (wizardSharedService.restoreScopeState() != undefined) {
            return wizardSharedService.restoreScopeState().SQLSTRING || false;
        } else {
            $scope.SQL.SQLSTRING = [];
            return false; // we can't have valid SQL without select
        }

        from = SQL.getSQL_FROM();
        if (from !== false)
        {
            $scope.SQL.SQLSTRING += ' '+from;
        }

        where = SQL.getSQL_WHERE();
        if(where !== false) {
            $scope.SQL.SQLSTRING += ' ' + where;
        }

        groupby = SQL.getSQL_GROUPBY();
        if(groupby !== false) {
            $scope.SQL.SQLSTRING += ' ' + groupby;
        }

        orderby = SQL.getSQL_ORDERBY();
        if(orderby !== false) {
            $scope.SQL.SQLSTRING += ' ' + orderby;
        }


        limit = SQL.getSQL_LIMIT();
        if(limit !== false) {
            $scope.SQL.SQLSTRING += ' ' + limit;
        }
        if($scope.SQL.SQLSTRING !=='' && $scope.SQL.SQLSTRING !== false)
        return $scope.SQL.SQLSTRING.trim();
        else
        return '';
    };

    return SQL;
}]);
