(function () {
    'use strict';

    angular
        .module('setoresApp')
        .directive('modalWindow', modalWindow);

    modalWindow.$inject = ['$timeout', '__env', '$q'];

    /* @ngInject */
    function modalWindow($timeout, __env, $q) {
        return {
            restrict: 'E',
            replace: true,
            templateUrl: __env.appPath + 'scripts/components/modal-window/modal-window.directive.html',
            link: link,
            scope: false
        };

        function link(scope, element) {
            //exports
            angular.extend(scope.vm, {
                openModal: openModal,
                closeModal: closeModal
            });

            scope.vm.modalComponent = {};

            const modal = element[0];
            const parent = modal.parentElement;
            const handler = modal.querySelector('.modal-header');
            const topDistance = 80;

            let modalIsDraggable = false;
            let modalIsOpen = false;

            $timeout(resetPosition, 500);

            function openModal(headerText, innerContent, closeAction, draggable = false) {
                if (!draggable) {
                    scope.vm.showOverlay();
                }

                return modalIsOpen ?
                    swapModal(headerText, innerContent, closeAction, draggable) :
                    showModal(headerText, innerContent, closeAction, draggable);
            }


            function swapModal(headerText, innerContent, closeAction, draggable) {
                return addContent(headerText, innerContent, closeAction, draggable).then(() => {
                    let posX = modal.style.transform.split(' ')[0].match(/\(([^)]+)\)/)[1].replace('px', '');
                    let posY = modal.style.transform.split(' ')[1].match(/\(([^)]+)\)/)[1].replace('px', '');
                    let newPosY = modal.offsetTop + modal.offsetHeight + parseInt(posY);

                    modal.style.top = `-${modal.offsetHeight}px`;
                    modal.style.transform = `translateX(${posX}px) translateY(${newPosY}px)`;
                    scope.vm.resetPositions(parseInt(posX), parseInt(newPosY));

                    return $q.resolve();
                });
            }

            function showModal(headerText, innerContent, closeAction, draggable) {
                return addContent(headerText, innerContent, closeAction, draggable).then(() => {
                    resetPosition();

                    return $timeout(() => {
                        animate(modal.offsetHeight + topDistance, 'in');
                        if (modalIsDraggable) {
                            scope.vm.setDraggable(modal, parent, topDistance, handler);
                        }
                        modalIsOpen = true;
                        return $q.resolve();
                    }, 500);
                });
            }

            function closeModal() {
                animate(0, 'out');
                if (modalIsDraggable) {
                    scope.vm.resetDraggable(parent);
                }

                return $timeout(() => {
                    return addContent(null, null, null, false).then(() => {
                        resetPosition();

                        if (!modalIsDraggable) {
                            scope.vm.hideOverlay();
                        }

                        modalIsOpen = false;
                        return $q.resolve();
                    });
                }, 500);
            }

            function addContent(headerText, innerContent, closeAction, draggable) {
                scope.vm.modalComponent.headerText = headerText;
                scope.vm.modalComponent.innerContent = innerContent;
                scope.vm.modalComponent.closeAction = closeAction;
                modalIsDraggable = draggable;

                modalIsDraggable ? modal.classList.add('not-selectable') :
                    modal.classList.remove('not-selectable');

                if (!scope.$$phase) {
                    scope.$apply();
                }

                return $timeout(() => $q.resolve(), 300);
            }

            function resetPosition() {
                modal.style.left = `${(parent.offsetWidth / 2) - (modal.offsetWidth / 2)}px`;
                modal.style.transform = `translateX(0) translateY(0)`;
                modal.style.bottom = '100%';
            }

            function animate(value, direction) {
                let posX = modal.style.transform.split(' ')[0].match(/\(([^)]+)\)/)[1];
                let posY = `${value}px`;

                modal.style.transition = `transform 0.4s ease-in-out`;
                modal.style.transform = `translateX(${posX}) translateY(${posY})`;

                $timeout(() => {
                    modal.style.transition = `none`;

                    if (direction === 'in') {
                        modal.style.top = `-${modal.offsetHeight}px`;
                        modal.style.bottom = 'inherit';
                    } else {
                        modal.style.bottom = '100%';
                        modal.style.top = 'inherit';
                    }
                }, 400);
            }
        }
    }
})();
