angular.module('editableFieldModule', [])
    .directive('editableField', ['$rootScope', function ($rootScope) {
        return {
            restrict: 'A',
            scope: {
                model: '=',
                maxLength: '@',
                saveFunction: '&'
            },
            template: `<span class="editableField" ng-class="{clicked}">
                           <div ng-click="onClicked()" title="click to edit" ng-hide="clicked">{{ model }}</div>
                           <span class="editableField-form" ng-show="clicked">
                               <input title="" maxlength="{{ maxLength }}" type="text" ng-model="model" />
                               <button ng-click="save()"><i class="bi bi-check"></i></button>
                               <button ng-click="cancel()"><i class="bi bi-x"></i></button>
                           </span>
                       </span>`,
            link: function (scope, element, attrs) {
                scope.clicked = false;
                // decode special html chars as we encode them on the API level
                scope.model = htmlSpecialCharsDecode(scope.model);
                let initialFieldValue = null;

                scope.onClicked = function () {
                    scope.clicked = true;
                    setTimeout(() => element[0].querySelector('input').select(), 100)
                }

                scope.save = function () {
                    scope.saveFunction().then(() => {
                        initialFieldValue = scope.model;
                        eventCloseFn(scope);
                    }, error => {
                        eventCloseFn(scope);
                        notify.error(error);
                    });
                    scope.clicked = false
                }

                scope.cancel = function () {
                    scope.model = initialFieldValue;
                    scope.clicked = false;
                }

                // set initial title value to revert changes in case of cancel action
                scope.$watch('model', function (newValue) {
                    if (newValue && initialFieldValue === null) {
                        initialFieldValue = newValue;
                    }
                })

                const eventCloseFn = (scope) => {
                    scope.cancel();
                    scope.$apply();
                }

                document.addEventListener('click', function (event) {
                    // count click on the x button as an outside click, otherwise input area will not be closed
                    const outsideClick = !element[0].contains(event.target) || event.target.className.includes('bi-x');
                    // clicked the :after pencil icon, so edit
                    if (!outsideClick && scope.clicked == false) {
                        scope.clicked = true;
                        scope.$apply();
                        setTimeout(()=>element[0].querySelector('input').select(), 100)
                    }
                    if (outsideClick && scope.clicked) {
                        scope.save();
                    }
                });

                document.addEventListener('keyup', function (event) {
                    if (event.key === 'Escape') {
                        eventCloseFn(scope);
                    }
                });

                element[0].addEventListener('keyup', function (event) {
                    if (event.key === 'Enter') {
                        scope.save();
                    }
                });
            }
        };
    }]);
