(function () {
    'use strict';

    angular
        .module('editorRotas')
        .directive('formValidationDirective', formValidationDirective);

    formValidationDirective.$inject = ['$timeout', 'ngNotify', '$q'];

    /* @ngInject */
    function formValidationDirective($timeout, ngNotify, $q) {
        var directive = {
            restrict: 'A',
            scope: false,
            link: linkFunc
        };

        return directive;

        function linkFunc(scope, element, attrs) {

            //exports
            angular.extend(scope.vm, {
                checkEmpty: checkEmpty,
                setFormStatus: setFormStatus,
                checkShapeFile: checkShapeFile,
                validateTimeInterval: validateTimeInterval,
                validateSequencia: validateSequencia
            });

            scope.vm[attrs.name] = scope[attrs.name];

            function checkEmpty(formObj) {
                if (scope.vm.filtro === undefined) return;
                scope.vm.filtrarHabilitado = false;
                angular.forEach(scope.vm.filtro, (item) => {
                    if (item !== '') scope.vm.filtrarHabilitado = true;
                });
            }

            function checkViewPending(formObj) {
                formObj.form.$$controls.some((item) => {
                    scope.vm.viewIsPending = false;
                    if (item.$viewValue !== item.originalValue && item.$viewValue !== '') {
                        scope.vm.viewIsPending = true;
                        return true;
                    }
                });
            }

            // Validação para intervalo de data
            function validateTimeInterval(formObj) {
                let modalNotification = document.getElementById('modalNotificationOuter');

                let inputsInterval = formObj.form.$$controls.filter((item) => {
                    if (item.$$attr.interval) return item;
                });
                let inputDateStartInterval = inputsInterval.find((item) => {
                    return item.$$attr.interval === 'day-start'
                });
                let inputDateEndInterval = inputsInterval.find((item) => {
                    return item.$$attr.interval === 'day-end'
                });
                let inputTimeStartInterval = inputsInterval.find((item) => {
                    return item.$$attr.interval === 'time-start'
                });
                let inputTimeEndInterval = inputsInterval.find((item) => {
                    return item.$$attr.interval === 'time-end'
                });

                let dateStart, dateEnd, timeStart, timeEnd;
                if (inputDateStartInterval) dateStart = new Date(inputDateStartInterval.$modelValue);
                if (inputDateEndInterval) dateEnd = new Date(inputDateEndInterval.$modelValue);
                if (inputTimeStartInterval) timeStart = inputTimeStartInterval.$modelValue;
                if (inputTimeEndInterval) timeEnd = inputTimeEndInterval.$modelValue;

                if (dateStart && timeStart) {
                    dateStart.setHours(timeStart.split(':')[0]);
                    dateStart.setMinutes(timeStart.split(':')[1]);
                    dateStart.setSeconds(0);

                    inputDateStartInterval.$modelValue = dateStart;
                    inputTimeStartInterval.$viewValue = timeStart;
                }

                if (dateEnd && timeEnd) {
                    dateEnd.setHours(timeEnd.split(':')[0]);
                    dateEnd.setMinutes(timeEnd.split(':')[1]);
                    dateEnd.setSeconds(0);

                    inputDateEndInterval.$modelValue = dateEnd;
                    inputTimeEndInterval.$viewValue = timeEnd;
                }

                if (dateStart && timeStart && dateEnd && timeEnd) {
                    if (dateStart > dateEnd) {
                        formObj.form.$valid = false;
                        ngNotify.set('A data inicial deve ser anterior a data final', {
                            target: '#modalNotificationOuter',
                            type: 'error',
                            sticky: true,
                            button: false
                        });
                    } else if ((Math.round(((dateEnd - dateStart) / 1000 / 60 / 60) * 100) / 100) > 24) {
                        ngNotify.set('O intervalo máximo para pesquisa é de 24hrs', {
                            target: '#modalNotificationOuter',
                            type: 'error',
                            sticky: true,
                            button: false
                        });
                        formObj.form.$valid = false;
                    } else {
                        modalNotification.innerText = '';
                        inputDateStartInterval.customValidation = true;
                        inputDateEndInterval.customValidation = true;
                    }
                }
            }

            function checkShapeFile(formObj) {
                ngNotify.dismiss();
                let selectedFiles = Array.from(formObj.form.$$controls[0].$$element[0].files).map(file => file);

                if (selectedFiles.length > 2) {
                    showError('Por favor, selecione apenas um arquivo .shp e um .dbf');
                    return;
                }

                let invalid = selectedFiles.some(value => {
                    let extension = value.name.substr((value.name.lastIndexOf('.') + 1));
                    return (!/(shp|dbf)$/ig.test(extension));
                });

                if (invalid) {
                    showError('Por favor, selecione apenas um arquivo .shp e um .dbf');
                    return;
                }

                selectedFiles.forEach(newFile => {
                    let extension = newFile.name.substr((newFile.name.lastIndexOf('.') + 1));

                    // verifica se já existe um arquivo com essa mesma extensão
                    let duplicated = scope.vm.shapeFiles.filter(oldFile => {
                        return oldFile.name.toLowerCase().substr((oldFile.name.lastIndexOf('.') + 1)) === extension.toLowerCase();
                    })[0];

                    // substitui pelo novo arquivo de mesma extensão
                    if (duplicated) {
                        scope.vm.shapeFiles = scope.vm.shapeFiles.filter(item => {
                            return item !== duplicated;
                        });
                    }

                    scope.vm.shapeFiles.push(newFile);
                });


                function showError(msg) {
                    scope.vm.shapeFiles = [];
                    setFormError(msg);
                }
            }

            function setFormError(msg) {
                ngNotify.set(msg, {
                    target: '#modalNotificationOuter',
                    type: 'error',
                    sticky: true,
                    button: false
                });
            }

            function setFormStatus(form, status, buttonStatus = {}) {
                let formElement = form.$$element;

                form.custom_status = status;

                switch (status) {
                    case 'SENDING':
                        formElement.addClass('sending');
                        break;

                    case 'SEND_SUCCESS':
                        formElement.removeClass('sending');
                        formElement.addClass('successful');
                        break;

                    case 'SEND_FAIL':
                        formElement.removeClass('sending');
                        formElement.addClass('failure');
                        break;

                    default:
                        formElement.removeClass('sending');
                        formElement.removeClass('successful');
                        formElement.removeClass('failure');
                        break;
                }

                return $timeout(function () {
                    return $q.resolve()
                }, 1000);
            }

            function onlyUnique(value, index, self) {
                return self.indexOf(value) === index;
            }

            function validateSequencia(formObj) {
                if (scope.vm.novaRota.Sequencia) {
                    const sequenciaField = formObj.form.$$controls.find(x => x.$name === "sequencia");
                    const sequencias = scope.vm.dadosArquivo.geojson.features
                        .map(record => parseInt(record.properties[scope.vm.novaRota.Sequencia]));

                    let campoSequenciaValido = !sequencias.some((sequencia) => !Number.isInteger(sequencia)) &&
                        sequencias.filter(onlyUnique).length === sequencias.length;

                    sequenciaField.customValidation = campoSequenciaValido;

                    if (!campoSequenciaValido)
                        formObj.form.$valid = false;
                }
            }
        }
    }

})();
