/*-
 * ~~~~~~licensing~~~~~~
 * entaxy-management-plugin
 * ==========
 * Copyright (C) 2020 - 2025 EmDev LLC
 * ==========
 * You may not use this file except in accordance with the License Terms of the Copyright
 * Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
 * rights to the Software and any copies are the property of the Copyright Holder. Unless
 * it is explicitly allowed the Copyright Holder, the User is prohibited from using the
 * Software for commercial purposes to provide services to third parties.
 * 
 * The Copyright Holder hereby declares that the Software is provided on an "AS IS".
 * Under no circumstances does the Copyright Holder guarantee or promise that the
 * Software provided by him will be suitable or not suitable for the specific purposes
 * of the User, that the Software will meet all commercial and personal subjective
 * expectations of the User, that the Software will work properly, without technical
 * errors, quickly and uninterruptedly.
 * 
 * Under no circumstances shall the Copyright Holder or its Affiliates is not liable
 * to the User for any direct or indirect losses of the User, his expenses or actual
 * damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
 * or damage to data, property, etc.
 * ~~~~~~/licensing~~~~~~
 */
var Entaxy;
(function (Entaxy) {
    Entaxy._module.component('entaxyListInput', {
        bindings: {
            items: '=',
            itemTitleTemplate: '<',
            creationEnabled: '<',
            creationTypes: '<',
            itemFactoryFilter: '<',
            readonly: '<',
            validation: '<',
            mode: '<',
            errors: '<',
            formController: '<'
        },
        template:
        `
            <div class="entaxy-empty-state" ng-if="$ctrl.showEmptyState">
              <span>{{$ctrl.emptyStateMessage}}</span>
            </div>
            <div class="add-item-to-list-block" ng-click="$ctrl.showModal()"
                  ng-if="$ctrl.creationEnabled && !$ctrl.readonly">
              <span class="pficon pficon-add-circle-o"></span>
              <span>{{$ctrl.addItemTitle}}</span>
            </div>
            <div as-sortable="$ctrl.dragControlListeners" ng-model="$ctrl.items"
                    ng-if="$ctrl.items && $ctrl.items.length > 0">
              <div ng-repeat="item in $ctrl.items"
                    ng-class="{'list-input-item-has-error': item.errors && !item.toDeletion}" as-sortable-item>
                <div class="list-input-item" ng-class="{'disabled': item.toDeletion}">
                  <div class="list-input-item-heading" ng-click="$ctrl.open(item)">
                    <span class="fa fa-angle-right" ng-if="!item.open"></span>
                    <span class="fa fa-angle-down" ng-if="item.open"></span>
                    <label ng-class="{'new-item': item.new}">
                      {{$ctrl.getItemName(item.formFields)}}
                    </label>
                  </div>
                  <div class="list-input-item-controls" ng-if="!$ctrl.readonly">
                    <span class="pficon pficon-delete remove-icon"
                            ng-click="$ctrl.removeItem(item)" ng-if="!item.toDeletion"
                            data-toggle="tooltip" title="Remove"></span>
                    <span class="pficon pficon-history restore-icon"
                            ng-click="$ctrl.restoreItem(item)" ng-if="item.toDeletion"
                            data-toggle="tooltip" title="Restore"></span>
                    <span class="glyphicon glyphicon-move move-icon" as-sortable-item-handle
                            data-toggle="tooltip" title="Move" ng-if="!item.toDeletion"></span>
                  </div>
                </div>
                <div class="list-input-item-content" ng-show="item.open">
                  <entaxy-list-item-content form-fields="item.formFields" errors="item.errors" mode="$ctrl.mode">
                  </entaxy-list-item-content>
                </div>
              </div>
            </div>
        `,
        controller: entaxyListInputController
    })
    .name;

    function entaxyListInputController(workspace, $q, $uibModal, entaxyService) {
        'ngInject';

        let ctrl = this;

        ctrl.dragControlListeners = {
            itemMoved: function (event) {
                event.source.itemScope.modelValue.status = event.dest.sortableScope.$parent.column.name;
            },
            orderChanged: function (event) {
                setDirty();
            },
            containment: '#board'
        };

        ctrl.$onInit = function() {
            ctrl.itemTypes = ctrl.creationTypes.map(type => type.displayName);
            ctrl.addItemTitle = 'Add ' + ctrl.itemTypes.join(' or ');

            ctrl.showEmptyState = (ctrl.mode === Entaxy.MODAL_MODES.VIEW || !ctrl.creationEnabled || ctrl.readOnly)
                && !ctrl.items || (ctrl.items && ctrl.items.length == 0);
            ctrl.emptyStateMessage = 'No Items Available';
        }

        ctrl.getItemName = function (formFields) {
            let values = [];
            ctrl.itemTitleTemplate.fields.forEach(fieldName => {
                let formField = formFields.find(formField => formField.name === fieldName);
                values.push(formField.value);
            });
            return values.join(ctrl.itemTitleTemplate.delimiter);
        }

        function setDirty() {
            if (ctrl.formController && !ctrl.formController.$dirty) {
                ctrl.formController.$setDirty();
            }
        }

        ctrl.$onChanges = function (changes) {
            if (changes.errors) {
                if (ctrl.items && !changes.errors.currentValue
                    && (!changes.errors.previousValue || Object.keys(changes.errors.previousValue).length === 0)) {
                    ctrl.items.forEach(item => item.errors = undefined);
                }
                if (changes.errors.currentValue) {
                    let errors = changes.errors.currentValue;
                    if (typeof errors !== 'string') {
                        let errorKeys = Object.keys(errors);
                        errorKeys.forEach(errorKey => {
                            ctrl.items.filter(item => !item.toDeletion).forEach(item => {
                                let formField = item.formFields.find(formField => formField.name === errorKey);
                                if (formField) {
                                    if (errors[errorKey].values) {
                                        if (errors[errorKey].values.includes(formField.value)) {
                                            setError(item, formField.name, errors[errorKey].message);
                                        }
                                    } else {
                                        setError(item, formField.name, errors[errorKey].message);
                                    }
                                }
                            });
                        });
                    }
                }
            }
        }

        function setError(item, formFieldName, message) {
            if (!item.errors) {
                item.errors = {};
            }
            item.errors[formFieldName] = message;
        }

        ctrl.open = function (item) {
            if (!item.toDeletion) {
                item.open = !item.open;
            }
        }

        ctrl.removeItem = function (item) {
            item.toDeletion = true;
            item.open = false;

            setDirty();
        }

        ctrl.restoreItem = function (item) {
            item.toDeletion = false;
        }

        ctrl.showModal = function () {

            let allFactories = [];
            let promises = [];

            if (ctrl.itemFactoryFilter) {
                promises.push(
                    entaxyService.getFactoriesByFilterSearch(ctrl.itemFactoryFilter)
                        .then(factories => allFactories = factories));
            } else {
                ctrl.creationTypes.forEach(type => {
                    promises.push(
                        entaxyService.getFactoriesByType(type.name)
                            .then(factories => allFactories = allFactories.concat(factories)));
                });
            }

            if (promises.length > 0) {

                let checkUniqueness = ctrl.validation && ctrl.validation.rules ?
                    ctrl.validation.rules.checkChildrenUniqueness : undefined;
                let checkUniquenessFields = {};
                if (checkUniqueness) {
                    checkUniqueness.fields.forEach(field => {
                        checkUniquenessFields[field] = [];
                        if (ctrl.items) {
                            ctrl.items.forEach(item => {
                                let formField = item.formFields.find(formField => formField.name === field);
                                checkUniquenessFields[field].push(formField.value);
                            });
                        }
                    });
                }

                $uibModal.open({
                    component: 'entaxyModal',
                    resolve: {
                        mode: () => Entaxy.MODAL_MODES.ADD,
                        itemType: () => ctrl.itemTypes.join(' or '),
                        factories: $q.all(promises).then(() => allFactories),
                        returnFormFields: () => true,
                        checkUniquenessParentFields: () => checkUniquenessFields
                    },
                    size: 'xl',
                    backdrop: 'static',
                    windowTopClass: 'modal-top-margin-override'
                })
                .result.then(formFields => {
                    addItem(formFields);
                },
                reason => {
                    if (reason) {
                        Entaxy.notificationError(reason);
                    }
                });
            }
        }

        function addItem(formFields) {

            if (!ctrl.items) {
                ctrl.items = [];
            }

            ctrl.items.push({
                new: true,
                formFields: formFields
            });

            setDirty();
        }
    }
    entaxyListInputController.$inject = ['workspace', '$q', '$uibModal', 'entaxyService'];

})(Entaxy || (Entaxy = {}));
