/*jslint node: true */
/*jslint browser: true*/
/*jslint nomen: true*/
/*jslint plusplus: true */
/*global angular, Class*/

'use strict';

/*
 * env:  - object, which contain
 *  classFilter.includes -
 */

var IncludeExcludeServiceClass = Class.extend({
    $scope: {},
    env: {},
    viewvars: {},
    profileId: '',
    nodes: '',
    getVIEWVariables: function (profileId, nodes) {
        var self = this, $d = self.$q.defer();

        self.profileId = profileId;
        self.nodes = nodes;

        self._getProfiles()
            .then(function () {
                self._getNodes().
                    then(
                    function()
                    {
                        //timeout to prevent $digest error
                        self.$timeout(function() {

                            var result = self._setSelectedNodes();
                            $d.resolve(result);
                        });
                    },
                    function() {
                        var data = {};
                        $d.resolve(data);
                    }).
                    then(function () {
                        $d.resolve(self.viewvars);
                    });
            });

        return $d.promise;
    },

    getProfiles: function () {
        var self = this,  deferred = this.$q.defer();
        self._naviTreeService.getTreeProfiles().then(
            function (result) {
                self.viewvars.treeProfiles = result.data;
                deferred.resolve();
            },
            function (error) {
                self.viewvars.treeProfiles = [];
                deferred.reject();
            }
        );

        return deferred.promise;
    },
    searchHosts: function ($searchText) {
        var self = this,  deferred = this.$q.defer();
        self._naviTreeService.searchHosts($searchText).then(
            function (result) {
                self.viewvars.treeProfiles = result.data;
                deferred.resolve();
            },
            function (error) {
                self.viewvars.treeProfiles = [];
                deferred.reject();
            }
        );

        return deferred.promise;
    },

    getHostsByInventoryFilter: function (filter) {
        var self = this,  deferred = this.$q.defer();
        self._naviTreeService.getHostsByInventory(filter).then(
            function (result) {
                deferred.resolve(result.data);
            },
            function (error) {
                deferred.reject(error);
            }
        );

        return deferred.promise;
    },
    /*
     * - check if profile id set in cookie
     * - check if this profile exist in all profiles list
     */

    _getNodes: function () {
        var self = this, deferred = this.$q.defer(), profileToLoad;

        if (self.profileId) {
            profileToLoad = self._filterTreeByFieldValue(self.viewvars.treeProfiles, 'id', parseInt(self.profileId,10));

            if (!self._commonHelper._isObjEmpty(profileToLoad)) {

                self.updateTreeProfile(profileToLoad).then(
                    function () {
                        deferred.resolve();
                    },
                    function () {
                        deferred.reject();
                    }
                );
            } else {
                // unusual situation - profile not found
                self.$rootScope.$broadcast('environmentProfileNotFound_Event', "Unable to load host profile: " +self.profileId);
                deferred.reject();
            }
        } else {
            // if profile is not set - astrolable will return default profile
            deferred.resolve();
        }

        return deferred.promise;
    },
    _setSelectedNodes: function () {
        var self = this, nodesArray = [], c, index, pointer, selectedNodes, result, i;

        if (self.nodes !== '' && self.nodes !== undefined) {

            nodesArray = angular.fromJson(self.nodes);

            c = nodesArray.length;
            index = 0;
            pointer = self.viewvars.treeNodes;

            selectedNodes = [];
            result = [];

            for (i = 0; i < c; i++) { // first index in cookie array == all host - we don't need it
                if (nodesArray[i] !== 'All hosts') {
                    var curLevel = self._filterTreeByFieldValue(pointer, 'label', nodesArray[i]);
                    result = self.addNodeLevel(curLevel, index);
                    pointer = curLevel['children'];
                    index++;

                    selectedNodes.push(curLevel);
                }
            }

            return result;
        }
    },
    addNodeLevel: function (node, index) {
        var self = this, startIndex, result;

        if (self._commonHelper._isObjEmpty(node) === true) {
            return;
        }
        // remove everthing after the index;
        startIndex = (index === 0) ? 0 : index;

        this.viewvars.nodeLevels = this.viewvars.nodeLevels.slice(0, startIndex + 1);
        this.viewvars.selectedNodeLevel = this.viewvars.selectedNodeLevel.slice(0, startIndex + 1);
        this.viewvars.selectedNodeLevel[index] = node;
        this.viewvars.selectedNode = node;

        if (node.children && node.children.length > 0) {
            this.viewvars.nodeLevels.push(node.children);
        }

        result = this._updateClassEvaluation(this.viewvars.selectedNodeLevel);
        return result;
    },
    _updateClassEvaluation: function (nodes) {
        var self = this, envName = "", regex = [], result = {};

        angular.forEach(nodes, function (val) {
            regex.push(val.classRegex);
        });

        if (regex.length) {
            envName = '(' + regex.join(').(') + ')';
        }

        result.name = envName;
        result.includes = regex;
        return result;
    },
    /**
     * tree - object
     */
    updateTreeProfile: function (tree) {
        var self = this, deferred;
        this.viewvars.selectedProfile = angular.copy(tree);

        deferred = this.$q.defer();
        this._naviTreeService.getTreeNodes(tree).then(
            function (result) {
                self.viewvars.treeNodes  = result.data;
                self.viewvars.nodeLevels = []; // reset nodes
                self.viewvars.selectedNodeLevel = [];
                self.viewvars.nodeLevels.push(result.data);
                deferred.resolve();
            },
            function (error) {
                self.viewvars.treeNodes = [];
                deferred.reject();
            }
        );
        return deferred.promise;
    },
    _filterTreeByFieldValue: function (trees, field, value) {
        var result = {}, keepGoing = true;

        angular.forEach(trees, function (item, itemId) {
            if (keepGoing === true && item[field] !== undefined && item[field] === value) {
                result    = item;
                keepGoing = false;
            }
        });
        return result;
    }
});

(function () {
    var IncludeExcludeServiceProvider = Class.extend({
        instance: new IncludeExcludeServiceClass(),
        $get: ['$rootScope', 'naviTreeService', 'commonHelper', '$q', '$timeout',
            function ($rootScope, naviTreeService, commonHelper, $q, $timeout) {
                this.instance.$rootScope = $rootScope;
                this.instance._naviTreeService = naviTreeService;
                this.instance._commonHelper = commonHelper;
                this.instance.$q = $q;
                this.instance.$timeout = $timeout;
                return this.instance;
            }]
    });

    angular.module('includeExcludeServiceModule', [])
        .provider('includeExcludeService', IncludeExcludeServiceProvider);
}());