Source: directives/preset/preset.service.js

/**
 * @ngdoc directives
 * @name PresetService
 * @module s4c.directives.present.PresetService
 *
 * @description
 * `PresetService` Componente para acesso ao api do backend e/ou comunicação entre controllers
 * 
 * 
 */
(function () {
    angular.module('s4c.components.preset')
        .factory('Preset', Preset);

    Preset.$inject = [
        'GRIDSTER_OPTIONS_EDICAO',
        'MainState',
        'Base',
        'MsiFilter',
        'DetalhamentoManager',
        '$timeout',
        'MapaService',
        'VideoStreamService',
        'CategoriaAplicacaoService',
        'ParametrosS4C'
    ];

    function Preset(GRIDSTER_OPTIONS_EDICAO, MainState, Base, MsiFilter,
        DetalhamentoManager, $timeout, MapaService, VideoStreamService, CategoriaAplicacaoService, ParametrosS4C) {

        var service = {
            config: {
                preset: {
                    PresetModulos: []
                },
                gridsterOpts: GRIDSTER_OPTIONS_EDICAO,
                edicao: true
            },
            editar: editar,
            removerItem: removerItem,
            novo: novo,
            alterar: alterar,
            renomear: renomear,
            obter: obter,
            isPresetDeAgencia: isPresetDeAgencia,
            salvar: salvar,
            remover: remover,
            obterMeus: obterMeus,
            saveMapPosition: saveMapPosition,
            stopAllShare: stopAllShare,
            setModuleRenderes: setModuleRenderes,
            setMainRenderes: setMainRenderes,
            rollBackEmptyModules: rollBackEmptyModules
        };

        var mainRenderes = [];
        var renderes = [];
        /**
         * @method stopAllShare
         */
        function stopAllShare() {

            for (var index in mainRenderes) {
                if (mainRenderes[index]) {
                    mainRenderes[index].closeApp(mainRenderes[index]);
                }
            }

            for (var index in renderes) {
                for (var index2 in renderes[index]) {
                    if (renderes[index][index2]) {
                        renderes[index][index2].closeApp(renderes[index][index2]);
                    }
                }
            }
        }

        /**
         * @method setModuleRenderes
         * @param {*} array 
         */
        function setModuleRenderes(array) {
            renderes = array;
        }

        /**
         * @method setMainRenderes
         * @param {*} array 
         */
        function setMainRenderes(array) {
            mainRenderes = array;
        }

        /**
         * @method saveMapPosition
         * @param {*} presetId 
         * @param {*} json 
         */
        function saveMapPosition(presetId, json) {
            return Base.atualizar('preset/mapa/' + presetId, json).then(function (presetRetorno) {
                if (service.config.preset.mapaPosInicial == null) {
                    service.config.preset.mapaPosInicial = {};
                    service.config.preset.mapaPosInicial.coordinates = {};
                    service.config.preset.mapaPosInicial.coordinates.coordinates = [];
                    service.config.preset.mapaPosInicial.coordinates.coordinates.push(presetRetorno.mapaPosInicial.lat);
                    service.config.preset.mapaPosInicial.coordinates.coordinates.push(presetRetorno.mapaPosInicial.lng);
                } else {
                    service.config.preset.mapaPosInicial.coordinates.coordinates[0] = presetRetorno.mapaPosInicial.lat;
                    service.config.preset.mapaPosInicial.coordinates.coordinates[1] = presetRetorno.mapaPosInicial.lng;
                }
                service.config.preset.mapaPosZoom = presetRetorno.mapaPosZoom;
            });
        }

        /**
         * @method salvar
         * @param {*} _preset 
         */
        function salvar(_preset) {
            var preset = _preset || service.config.preset;
            $timeout(MainState.menuButtonFunction, 1000);
            if (preset.id > 0) {

                // Clean null Faces on PresetModulos
                preset.PresetModulos = _.map(preset.PresetModulos, function (modulo) {
                    if (!_.has(modulo, 'FaceId') || _.isNull(modulo.FaceId)) {
                        modulo.closed = true;
                        modulo.template = 'app/components/modulos/face-fechada.html';
                    }
                    return modulo;
                });

                return Base.atualizar('preset/' + preset.id, preset);
            }

            return Base.salvar('preset', preset);
        }

        /**
         * @method remover
         * @param {*} _preset 
         */
        function remover(_preset) {
            if (_preset) {
                return Base.remover('preset/' + _preset.id)
            }
            return Base.remover('preset/' + service.config.preset.id)
        }

        /**
         * @method novo
         */
        function novo() {
            service.config.preset = {
                PresetModulos: []
            };

            return service.config.preset;
        }

        /**
         * @method obterMeus
         */
        function obterMeus() {
            return Base.obter('preset/me')
        }

        /**
         * @method alterar
         * @param {*} preset 
         */
        function alterar(preset) {
            service.config.preset = preset;

            for (var index in service.config.preset.PresetModulos) {
                service.config.preset.PresetModulos[index].usado = false;
            }

            editar();
        }

        /**
         * @method renomear
         * @param {*} nome 
         */
        function renomear(nome) {
            service.config.preset.nome = nome;
        }

        /**
         * @method obter
         */
        function obter() {
            return service.config.preset;
        }

        /**
         * @method isPresetDeAgencia
         */
        function isPresetDeAgencia() {
            var preset = service.config.preset;

            if (preset.DepartamentoId && preset.DepartamentoId !== null) {
                return true;
            }

            return false;
        }

        /**
         * @method editar
         */
        function editar() {

            if ((!MainState.getPermissoes().permissoesEdicao.presetPublico && service.config.preset.padrao != true)
                || (service.config.preset.padrao == true && !MainState.getPermissoes().permissoesExtras.alterarPresetAgencia)) {

                GRIDSTER_OPTIONS_EDICAO.resizable.enabled = false;
                GRIDSTER_OPTIONS_EDICAO.draggable.enabled = false;
            } else {
                GRIDSTER_OPTIONS_EDICAO.resizable.enabled = true;
                GRIDSTER_OPTIONS_EDICAO.draggable.enabled = true;
            }

            service.config.gridsterOpts = GRIDSTER_OPTIONS_EDICAO;
            service.config.gridsterOpts.draggable.stop = _findFillEmpty;
            service.config.gridsterOpts.draggable.start = _limparCuboVazio;
            service.config.gridsterOpts.resizable.stop = _findFillEmpty;
            service.config.gridsterOpts.resizable.start = _limparCuboVazio;

            service.config.edicao = true;
            setTimeout(function(){_findFillEmpty()}, 3000);

        }

        /**
         * @method removerItem
         * @param {*} item 
         * @param {*} camera 
         */
        function removerItem(item, camera) {

            if (!MainState.getPermissoes().permissoesEdicao.presetPublico) {
                return;
            }

            _fecharItem(item);
            _findFillEmpty();
            DetalhamentoManager.fechar();
            if (camera) {
                var videoId = document.getElementById(item.id).getElementsByTagName("video")[0].id
                VideoStreamService.close(videoId);
            }
            return item;
        }

        /**
         * @method _fecharItem
         * @param {*} item 
         */
        function _fecharItem(item) {

            // Busca item utilizando row e col, pois para POI não está retornando o item correto. (BUG Contornado)
            if (!item.hasOwnProperty("$$hashKey")) {
                for (var index in service.config.preset.PresetModulos) {
                    if (item.row == service.config.preset.PresetModulos[index].row && item.col == service.config.preset.PresetModulos[index].col) {
                        item = service.config.preset.PresetModulos[index];
                        break;
                    }
                }
            }

            var _item = service.config.preset.PresetModulos.indexOf(item);
            service.config.preset.PresetModulos.splice(_item, 1);
            if (item.name === 'Mapa' || item.name === 'Map' || (item.Face && (item.Face.name == 'Mapa' || item.Face.name == 'Map'))) {
                if (service.config.preset.PresetModulos.novasFaces) {
                    service.config.preset.PresetModulos.novasFaces.splice(service.config.preset.PresetModulos.novasFaces.indexOf(item.name || item.Face.name), 1)
                }
            }
            //Disparo um evento comunicando que o módulo MSI foi fechado.
            if ((item.Face && item.Face.template == "app/components/modulos/modulo-msi.html") || (item.template == "app/components/modulos/modulo-msi.html")) {
                MsiFilter.getInstance('filtro-msi').trigger('moduloMsiFechado', true);
            }
        }

        /**
         * @method _limparCuboVazio
         * @param {*} event 
         * @param {*} $element 
         * @param {*} widget 
         */
        function _limparCuboVazio(event, $element, widget) {

            $('.divWebviewStyle').css('z-index', '101');
            var itensFechados = _.filter(service.config.preset.PresetModulos, {
                closed: true
            });

            _.each(itensFechados, function (item) {
                if (!widget || item.id !== widget.id) {
                    _fecharItem(item);
                }
            });

            salvar();
            $('.divWebresize').show()
        }

        setTimeout(function () { MainState.resizeMenuMapa() }, 3000)

        var hasBuildEmptyModules = false;
        /**
         * @method _findFillEmpty
         * @param {*} event 
         * @param {*} $el 
         * @param {*} itemOptions 
         * @param {*} item 
         */
        function _findFillEmpty(event, $el, itemOptions, item) {

            $('.divWebviewStyle').css('z-index', '10');
            $('.divWebresize').hide()

            MainState.resizeMenuMapa();

            MainState.btnModuloReset(event, itemOptions)

            // Atualiza o sizeX, sizeY, row e col do itemOptions, pois apenas o item está sendo atualizado
            // ao redimensionar ou mover o módulo de POI. (BUG Contornado)
            if (item !== undefined) {
                for (var index in service.config.preset.PresetModulos) {
                    if (service.config.preset.PresetModulos[index].$$hashKey == itemOptions.$$hashKey) {
                        service.config.preset.PresetModulos[index].sizeX = item.sizeX;
                        service.config.preset.PresetModulos[index].sizeY = item.sizeY;
                        service.config.preset.PresetModulos[index].row = item.row;
                        service.config.preset.PresetModulos[index].col = item.col;
                        break;
                    }
                }
            }

            var maxRows = service.config.gridsterOpts.maxRows;
            var maxCols = service.config.gridsterOpts.columns;
            var screenItems = [];

            /*
             * Inicializa array com char '0'
             */
            for (var row = 0; row < maxRows; row++) {
                screenItems[row] = [];

                var col = 0;
                while (col < maxCols) {
                    screenItems[row][col++] = '0';
                }
            }

            service.config.preset.PresetModulos = _.filter(service.config.preset.PresetModulos, function(modulo){
                return modulo.Face != null || modulo.sizeX > 1 || modulo.sizeY > 1;
            })

            /*
             * Iterando screenItems linha por linha
             */
            for (var row = 0; row < maxRows; row++) {
                /*
                 * Iterando coluna por coluna da linha
                 * do scrollItem:
                 */
                for (var col = 0; col < maxCols; col++) {
                    /* Iterando sobre cada item da grid,
                     * verificando se ele está contido dentro
                     * do row e col do screenItems atual:
                     */
                    for (var index in service.config.preset.PresetModulos) {

                        if (service.config.preset.PresetModulos[index].col >= maxCols || service.config.preset.PresetModulos[index].row >= maxRows) {
                            service.config.preset.PresetModulos[index].invisivel = true;
                        }

                        // Item da grid está na mesma coluna e mesma linha:
                        if (service.config.preset.PresetModulos[index].col === col && service.config.preset.PresetModulos[index].row === row) {

                            // Lidando com itens maiores que 1x1:
                            for (var rowItem = row; rowItem < row + service.config.preset.PresetModulos[index].sizeY; rowItem++) {

                                for (var colItem = col; colItem < col + service.config.preset.PresetModulos[index].sizeX; colItem++) {

                                    if (screenItems[rowItem] === undefined) {
                                        screenItems[rowItem] = [];
                                    }

                                    screenItems[rowItem][colItem] = 'X';
                                }
                            }

                        }
                    }
                }
            }

            addClosedCells(screenItems, maxRows, maxCols);
            buildEmptyModules();

            //Executa o crop no modulo para cada multivis que tenha enviado screen share
            if ($el) {
                executeMultivisCrop($el);
            }

            salvar().then(function (preset) {
                service.config.preset.id = preset.id;
                MapaService.refreshMap();
            });
        }

        var closedCells = [];
        /**
         * @method addClosedCells
         * @param {*} screenItems 
         * @param {*} maxRows 
         * @param {*} maxCols 
         */
        function addClosedCells(screenItems, maxRows, maxCols) {
            closedCells = [];
            for (var row = 0; row < maxRows; row++) {
                for (var col = 0; col < maxCols; col++) {
                    if (screenItems[row][col] === '0') {
                        var id = _.uniqueId();
                        var item = {
                            'id': id,
                            'row': row,
                            'col': col,
                            'sizeX': 1,
                            'sizeY': 1,
                            'closed': true,
                            template: 'app/components/modulos/face-fechada.html'
                        };
                        closedCells.push(item);
                        service.config.preset.PresetModulos.push(item);
                    }
                }
            }
        }

        /**
         * @method executeMultivisCrop
         * @param {*} $el 
         */
        function executeMultivisCrop($el) {
            for (var index in $el[0].childNodes) {
                if ($el[0].childNodes[index].id && $el[0].childNodes[index].id.length > 0) {

                    var rect = $el[0].childNodes[index].getBoundingClientRect();
                    var constraint = {
                        x: rect.x,
                        y: rect.y,
                        dx: rect.width,
                        dy: rect.height
                    }

                    for (var index2 in renderes[$el[0].childNodes[index].id]) {
                        if (renderes[$el[0].childNodes[index].id][index2]) {
                            renderes[$el[0].childNodes[index].id][index2].cropper(constraint);
                        }
                    }
                    break;
                }
            }
        }

        /**
         * @method buildEmptyModules
         */
        function buildEmptyModules() {

            if(hasBuildEmptyModules){
                return;
            }

            removeOldEmptyModules();
            addNewEmptyModules();
        }

        /**
         * @method rollBackEmptyModules
         */
        function rollBackEmptyModules(){
            hasBuildEmptyModules = false;
        }

        /**
         * @method removeOldEmptyModules
         */
        function removeOldEmptyModules() {
            var emptyModules = _.filter(service.config.preset.PresetModulos, function (module) {
                return module.Face && module.Face.extras
                && module.Face.extras.length > 0
                && module.Face.extras[0].tipo == 'vazio';
            });

            _.each(emptyModules, function(item){
                item.Face = undefined;
                item.FaceId = undefined;
                item.closed = true;
                item.template = undefined;
            });
        }

        /**
         * @method addNewEmptyModules
         */
        function addNewEmptyModules() {
            CategoriaAplicacaoService.obter().then(function (categorias) {

                var emptyFace = getEmptyFace(categorias);

                _.each(ParametrosS4C.parametros.presetCellsConfig, function(cell){
                    if(cell.val == true){
                        var item = findItemInClosedCells(cell.row, cell.col);
                        updateItemInfo(item, emptyFace);
                    }
                })
            });
        }

        /**
         * @method findItemInClosedCells
         * @param {*} row 
         * @param {*} col 
         */
        function findItemInClosedCells(row, col){

            for(var index in closedCells){
                if(closedCells[index].row == row && closedCells[index].col == col){
                    return closedCells[index];
                }
            }
        }

        /**
         * @method updateItemInfo
         * @param {*} item 
         * @param {*} face 
         */
        function updateItemInfo(item, face) {

            if(!item){
                return;
            }

            item.FaceId = face.id;
            item.template = face.template;
            item.closed = false;
            item.name = face.name;
            item.Face = face;
            hasBuildEmptyModules = true;
        }

        /**
         * @method getEmptyFace
         * @param {*} categorias 
         */
        function getEmptyFace(categorias) {
            var eface;
            _.each(categorias, function (categoria) {
                _.each(categoria.aplicacoes, function (aplicacao) {
                    _.each(aplicacao.faces, function (face) {

                        if (face.extras && face.extras.length > 0 && face.extras[0].tipo == 'vazio') {
                            eface = face;
                            return;
                        }
                    })
                })
            });
            return eface;
        }

        return service;
    }
}());