import * as i0 from '@angular/core';
import { Component, ChangeDetectionStrategy, ChangeDetectorRef, Injectable, NgModule } from '@angular/core';
import { Validators, FormBuilder, FormGroup, FormControl } from '@angular/forms';
import * as i1 from '@angular/router';
import { Router, ActivatedRoute, RouterModule } from '@angular/router';
import { marker } from '@biesbjerg/ngx-translate-extract-marker';
import * as i2 from '@ishop/admin-ui/core';
import { BaseDetailComponent, encodeConfigArgValue, getConfigArgValue, getDefaultConfigArgValue, ServerConfigService, DataService, NotificationService, BaseListComponent, ModalService, BaseEntityResolver, createResolveData, CanDeactivateDetailGuard, detailBreadcrumb, SharedModule } from '@ishop/admin-ui/core';
import { take, mergeMap, debounceTime, takeUntil, switchMap } from 'rxjs/operators';
import { merge, EMPTY } from 'rxjs';

class PromotionDetailComponent extends BaseDetailComponent {
    constructor(router, route, serverConfigService, changeDetector, dataService, formBuilder, notificationService) {
        super(route, router, serverConfigService, dataService);
        this.changeDetector = changeDetector;
        this.dataService = dataService;
        this.formBuilder = formBuilder;
        this.notificationService = notificationService;
        this.conditions = [];
        this.actions = [];
        this.allConditions = [];
        this.allActions = [];
        this.detailForm = this.formBuilder.group({
            name: ['', Validators.required],
            enabled: true,
            couponCode: null,
            perCustomerUsageLimit: null,
            startsAt: null,
            endsAt: null,
            conditions: this.formBuilder.array([]),
            actions: this.formBuilder.array([]),
        });
    }
    ngOnInit() {
        this.init();
        this.promotion$ = this.entity$;
        this.dataService.promotion.getPromotionActionsAndConditions().single$.subscribe(data => {
            this.allActions = data.promotionActions;
            this.allConditions = data.promotionConditions;
            this.changeDetector.markForCheck();
        });
    }
    ngOnDestroy() {
        this.destroy();
    }
    getAvailableConditions() {
        return this.allConditions.filter(o => !this.conditions.find(c => c.code === o.code));
    }
    getConditionDefinition(condition) {
        return this.allConditions.find(c => c.code === condition.code);
    }
    getAvailableActions() {
        return this.allActions.filter(o => !this.actions.find(a => a.code === o.code));
    }
    getActionDefinition(action) {
        return this.allActions.find(c => c.code === action.code);
    }
    saveButtonEnabled() {
        return (this.detailForm.dirty &&
            this.detailForm.valid &&
            (this.conditions.length !== 0 || this.detailForm.value.couponCode) &&
            this.actions.length !== 0);
    }
    addCondition(condition) {
        this.addOperation('conditions', condition);
        this.detailForm.markAsDirty();
    }
    addAction(action) {
        this.addOperation('actions', action);
        this.detailForm.markAsDirty();
    }
    removeCondition(condition) {
        this.removeOperation('conditions', condition);
        this.detailForm.markAsDirty();
    }
    removeAction(action) {
        this.removeOperation('actions', action);
        this.detailForm.markAsDirty();
    }
    formArrayOf(key) {
        return this.detailForm.get(key);
    }
    create() {
        if (!this.detailForm.dirty) {
            return;
        }
        const formValue = this.detailForm.value;
        const input = {
            name: formValue.name,
            enabled: true,
            couponCode: formValue.couponCode,
            perCustomerUsageLimit: formValue.perCustomerUsageLimit,
            startsAt: formValue.startsAt,
            endsAt: formValue.endsAt,
            conditions: this.mapOperationsToInputs(this.conditions, formValue.conditions),
            actions: this.mapOperationsToInputs(this.actions, formValue.actions),
        };
        this.dataService.promotion.createPromotion(input).subscribe(({ createPromotion }) => {
            switch (createPromotion.__typename) {
                case 'Promotion':
                    this.notificationService.success(marker('common.notify-create-success'), {
                        entity: 'Promotion',
                    });
                    this.detailForm.markAsPristine();
                    this.changeDetector.markForCheck();
                    this.router.navigate(['../', createPromotion.id], { relativeTo: this.route });
                    break;
                case 'MissingConditionsError':
                    this.notificationService.error(createPromotion.message);
                    break;
            }
        }, err => {
            this.notificationService.error(marker('common.notify-create-error'), {
                entity: 'Promotion',
            });
        });
    }
    save() {
        if (!this.detailForm.dirty) {
            return;
        }
        const formValue = this.detailForm.value;
        this.promotion$
            .pipe(take(1), mergeMap(promotion => {
            const input = {
                id: promotion.id,
                name: formValue.name,
                enabled: formValue.enabled,
                couponCode: formValue.couponCode,
                perCustomerUsageLimit: formValue.perCustomerUsageLimit,
                startsAt: formValue.startsAt,
                endsAt: formValue.endsAt,
                conditions: this.mapOperationsToInputs(this.conditions, formValue.conditions),
                actions: this.mapOperationsToInputs(this.actions, formValue.actions),
            };
            return this.dataService.promotion.updatePromotion(input);
        }))
            .subscribe(data => {
            this.notificationService.success(marker('common.notify-update-success'), {
                entity: 'Promotion',
            });
            this.detailForm.markAsPristine();
            this.changeDetector.markForCheck();
        }, err => {
            this.notificationService.error(marker('common.notify-update-error'), {
                entity: 'Promotion',
            });
        });
    }
    /**
     * Update the form values when the entity changes.
     */
    setFormValues(entity, languageCode) {
        this.detailForm.patchValue({
            name: entity.name,
            enabled: entity.enabled,
            couponCode: entity.couponCode,
            perCustomerUsageLimit: entity.perCustomerUsageLimit,
            startsAt: entity.startsAt,
            endsAt: entity.endsAt,
        });
        entity.conditions.forEach(o => {
            this.addOperation('conditions', o);
        });
        entity.actions.forEach(o => this.addOperation('actions', o));
    }
    /**
     * Maps an array of conditions or actions to the input format expected by the GraphQL API.
     */
    mapOperationsToInputs(operations, formValueOperations) {
        return operations.map((o, i) => {
            return {
                code: o.code,
                arguments: Object.values(formValueOperations[i].args).map((value, j) => ({
                    name: o.args[j].name,
                    value: encodeConfigArgValue(value),
                })),
            };
        });
    }
    /**
     * Adds a new condition or action to the promotion.
     */
    addOperation(key, operation) {
        const operationsArray = this.formArrayOf(key);
        const collection = key === 'conditions' ? this.conditions : this.actions;
        const index = operationsArray.value.findIndex(o => o.code === operation.code);
        if (index === -1) {
            const argsHash = operation.args.reduce((output, arg) => {
                var _a;
                return (Object.assign(Object.assign({}, output), { [arg.name]: (_a = getConfigArgValue(arg.value)) !== null && _a !== void 0 ? _a : this.getDefaultArgValue(key, operation, arg.name) }));
            }, {});
            operationsArray.push(this.formBuilder.control({
                code: operation.code,
                args: argsHash,
            }));
            collection.push({
                code: operation.code,
                args: operation.args.map(a => ({ name: a.name, value: getConfigArgValue(a.value) })),
            });
        }
    }
    getDefaultArgValue(key, operation, argName) {
        const def = key === 'conditions'
            ? this.allConditions.find(c => c.code === operation.code)
            : this.allActions.find(a => a.code === operation.code);
        if (def) {
            const argDef = def.args.find(a => a.name === argName);
            if (argDef) {
                return getDefaultConfigArgValue(argDef);
            }
        }
        throw new Error(`Could not determine default value for "argName"`);
    }
    /**
     * Removes a condition or action from the promotion.
     */
    removeOperation(key, operation) {
        const operationsArray = this.formArrayOf(key);
        const collection = key === 'conditions' ? this.conditions : this.actions;
        const index = operationsArray.value.findIndex(o => o.code === operation.code);
        if (index !== -1) {
            operationsArray.removeAt(index);
            collection.splice(index, 1);
        }
    }
}
PromotionDetailComponent.decorators = [
    { type: Component, args: [{
                selector: 'vdr-promotion-detail',
                template: "<vdr-action-bar>\r\n    <vdr-ab-left>\r\n        <div class=\"flex clr-align-items-center\">\r\n            <vdr-entity-info [entity]=\"entity$ | async\"></vdr-entity-info>\r\n            <clr-toggle-wrapper *vdrIfPermissions=\"'UpdatePromotion'\">\r\n                <input type=\"checkbox\" clrToggle name=\"enabled\" [formControl]=\"detailForm.get(['enabled'])\" />\r\n                <label>{{ 'common.enabled' | translate }}</label>\r\n            </clr-toggle-wrapper>\r\n        </div>\r\n    </vdr-ab-left>\r\n\r\n    <vdr-ab-right>\r\n        <vdr-action-bar-items locationId=\"promotion-detail\"></vdr-action-bar-items>\r\n        <button\r\n            class=\"btn btn-primary\"\r\n            *ngIf=\"isNew$ | async; else updateButton\"\r\n            (click)=\"create()\"\r\n            [disabled]=\"!saveButtonEnabled()\"\r\n        >\r\n            {{ 'common.create' | translate }}\r\n        </button>\r\n        <ng-template #updateButton>\r\n            <button\r\n                class=\"btn btn-primary\"\r\n                (click)=\"save()\"\r\n                *vdrIfPermissions=\"'UpdatePromotion'\"\r\n                [disabled]=\"!saveButtonEnabled()\"\r\n            >\r\n                {{ 'common.update' | translate }}\r\n            </button>\r\n        </ng-template>\r\n    </vdr-ab-right>\r\n</vdr-action-bar>\r\n\r\n<form class=\"form\" [formGroup]=\"detailForm\">\r\n    <vdr-form-field [label]=\"'common.name' | translate\" for=\"name\">\r\n        <input\r\n            id=\"name\"\r\n            [readonly]=\"!('UpdatePromotion' | hasPermission)\"\r\n            type=\"text\"\r\n            formControlName=\"name\"\r\n        />\r\n    </vdr-form-field>\r\n    <vdr-form-field [label]=\"'marketing.starts-at' | translate\" for=\"startsAt\">\r\n        <vdr-datetime-picker formControlName=\"startsAt\"></vdr-datetime-picker>\r\n    </vdr-form-field>\r\n    <vdr-form-field [label]=\"'marketing.ends-at' | translate\" for=\"endsAt\">\r\n        <vdr-datetime-picker formControlName=\"endsAt\"></vdr-datetime-picker>\r\n    </vdr-form-field>\r\n    <vdr-form-field [label]=\"'marketing.coupon-code' | translate\" for=\"couponCode\">\r\n        <input\r\n            id=\"couponCode\"\r\n            [readonly]=\"!('UpdatePromotion' | hasPermission)\"\r\n            type=\"text\"\r\n            formControlName=\"couponCode\"\r\n        />\r\n    </vdr-form-field>\r\n    <vdr-form-field [label]=\"'marketing.per-customer-limit' | translate\" for=\"perCustomerUsageLimit\">\r\n        <input\r\n            id=\"perCustomerUsageLimit\"\r\n            [readonly]=\"!('UpdatePromotion' | hasPermission)\"\r\n            type=\"number\"\r\n            min=\"1\"\r\n            max=\"999\"\r\n            formControlName=\"perCustomerUsageLimit\"\r\n        />\r\n    </vdr-form-field>\r\n\r\n    <div class=\"clr-row\">\r\n        <div class=\"clr-col\" formArrayName=\"conditions\">\r\n            <label class=\"clr-control-label\">{{ 'marketing.conditions' | translate }}</label>\r\n            <ng-container *ngFor=\"let condition of conditions; index as i\">\r\n                <vdr-configurable-input\r\n                    (remove)=\"removeCondition($event)\"\r\n                    [readonly]=\"!('UpdatePromotion' | hasPermission)\"\r\n                    [operation]=\"condition\"\r\n                    [operationDefinition]=\"getConditionDefinition(condition)\"\r\n                    [formControlName]=\"i\"\r\n                ></vdr-configurable-input>\r\n            </ng-container>\r\n\r\n            <div>\r\n                <vdr-dropdown *vdrIfPermissions=\"'UpdatePromotion'\">\r\n                    <button class=\"btn btn-outline\" vdrDropdownTrigger>\r\n                        <clr-icon shape=\"plus\"></clr-icon>\r\n                        {{ 'marketing.add-condition' | translate }}\r\n                    </button>\r\n                    <vdr-dropdown-menu vdrPosition=\"bottom-left\">\r\n                        <button\r\n                            *ngFor=\"let condition of getAvailableConditions()\"\r\n                            type=\"button\"\r\n                            vdrDropdownItem\r\n                            (click)=\"addCondition(condition)\"\r\n                        >\r\n                            {{ condition.description }}\r\n                        </button>\r\n                    </vdr-dropdown-menu>\r\n                </vdr-dropdown>\r\n            </div>\r\n        </div>\r\n        <div class=\"clr-col\" formArrayName=\"actions\">\r\n            <label class=\"clr-control-label\">{{ 'marketing.actions' | translate }}</label>\r\n            <vdr-configurable-input\r\n                *ngFor=\"let action of actions; index as i\"\r\n                (remove)=\"removeAction($event)\"\r\n                [operation]=\"action\"\r\n                [readonly]=\"!('UpdatePromotion' | hasPermission)\"\r\n                [operationDefinition]=\"getActionDefinition(action)\"\r\n                [formControlName]=\"i\"\r\n            ></vdr-configurable-input>\r\n            <div>\r\n                <vdr-dropdown *vdrIfPermissions=\"'UpdatePromotion'\">\r\n                    <button class=\"btn btn-outline\" vdrDropdownTrigger>\r\n                        <clr-icon shape=\"plus\"></clr-icon>\r\n                        {{ 'marketing.add-action' | translate }}\r\n                    </button>\r\n                    <vdr-dropdown-menu vdrPosition=\"bottom-left\">\r\n                        <button\r\n                            *ngFor=\"let action of getAvailableActions()\"\r\n                            type=\"button\"\r\n                            vdrDropdownItem\r\n                            (click)=\"addAction(action)\"\r\n                        >\r\n                            {{ action.description }}\r\n                        </button>\r\n                    </vdr-dropdown-menu>\r\n                </vdr-dropdown>\r\n            </div>\r\n        </div>\r\n    </div>\r\n</form>\r\n",
                changeDetection: ChangeDetectionStrategy.OnPush,
                styles: [""]
            },] }
];
PromotionDetailComponent.ctorParameters = () => [
    { type: Router },
    { type: ActivatedRoute },
    { type: ServerConfigService },
    { type: ChangeDetectorRef },
    { type: DataService },
    { type: FormBuilder },
    { type: NotificationService }
];

class PromotionListComponent extends BaseListComponent {
    constructor(dataService, router, route, notificationService, modalService) {
        super(router, route);
        this.dataService = dataService;
        this.notificationService = notificationService;
        this.modalService = modalService;
        this.searchForm = new FormGroup({
            name: new FormControl(''),
            couponCode: new FormControl(''),
        });
        super.setQueryFn((...args) => this.dataService.promotion.getPromotions(...args).refetchOnChannelChange(), data => data.promotions, (skip, take) => this.createQueryOptions(skip, take, this.searchForm.value));
    }
    ngOnInit() {
        super.ngOnInit();
        merge(this.searchForm.valueChanges.pipe(debounceTime(250)), this.route.queryParamMap)
            .pipe(takeUntil(this.destroy$))
            .subscribe(val => {
            if (!val.params) {
                this.setPageNumber(1);
            }
            this.refresh();
        });
    }
    deletePromotion(promotionId) {
        this.modalService
            .dialog({
            title: marker('catalog.confirm-delete-promotion'),
            buttons: [
                { type: 'secondary', label: marker('common.cancel') },
                { type: 'danger', label: marker('common.delete'), returnValue: true },
            ],
        })
            .pipe(switchMap(response => response ? this.dataService.promotion.deletePromotion(promotionId) : EMPTY))
            .subscribe(() => {
            this.notificationService.success(marker('common.notify-delete-success'), {
                entity: 'Promotion',
            });
            this.refresh();
        }, err => {
            this.notificationService.error(marker('common.notify-delete-error'), {
                entity: 'Promotion',
            });
        });
    }
    createQueryOptions(skip, take, searchForm) {
        const filter = {};
        if (searchForm.couponCode) {
            filter.couponCode = { contains: searchForm.couponCode };
        }
        if (searchForm.name) {
            filter.name = { contains: searchForm.name };
        }
        return {
            options: {
                skip,
                take,
                filter,
            },
        };
    }
}
PromotionListComponent.decorators = [
    { type: Component, args: [{
                selector: 'vdr-promotion-list',
                template: "<vdr-action-bar>\r\n    <vdr-ab-left>\r\n        <form class=\"search-form\" [formGroup]=\"searchForm\">\r\n            <input\r\n                type=\"text\"\r\n                formControlName=\"name\"\r\n                [placeholder]=\"'marketing.search-by-name' | translate\"\r\n                class=\"search-input\"\r\n            />\r\n            <input\r\n                type=\"text\"\r\n                formControlName=\"couponCode\"\r\n                [placeholder]=\"'marketing.search-by-coupon-code' | translate\"\r\n                class=\"search-input\"\r\n            />\r\n        </form>\r\n    </vdr-ab-left>\r\n    <vdr-ab-right>\r\n        <vdr-action-bar-items locationId=\"promotion-list\"></vdr-action-bar-items>\r\n        <a class=\"btn btn-primary\"\r\n           *vdrIfPermissions=\"'CreatePromotion'\"\r\n           [routerLink]=\"['./create']\">\r\n            <clr-icon shape=\"plus\"></clr-icon>\r\n            {{ 'marketing.create-new-promotion' | translate }}\r\n        </a>\r\n    </vdr-ab-right>\r\n</vdr-action-bar>\r\n\r\n<vdr-data-table\r\n    [items]=\"items$ | async\"\r\n    [itemsPerPage]=\"itemsPerPage$ | async\"\r\n    [totalItems]=\"totalItems$ | async\"\r\n    [currentPage]=\"currentPage$ | async\"\r\n    (pageChange)=\"setPageNumber($event)\"\r\n    (itemsPerPageChange)=\"setItemsPerPage($event)\"\r\n>\r\n    <vdr-dt-column>{{ 'common.name' | translate }}</vdr-dt-column>\r\n    <vdr-dt-column>{{ 'marketing.coupon-code' | translate }}</vdr-dt-column>\r\n    <vdr-dt-column>{{ 'marketing.starts-at' | translate }}</vdr-dt-column>\r\n    <vdr-dt-column>{{ 'marketing.ends-at' | translate }}</vdr-dt-column>\r\n    <vdr-dt-column></vdr-dt-column>\r\n    <vdr-dt-column></vdr-dt-column>\r\n    <vdr-dt-column></vdr-dt-column>\r\n    <ng-template let-promotion=\"item\">\r\n        <td class=\"left align-middle\">{{ promotion.name }}</td>\r\n        <td class=\"left align-middle\">\r\n            <vdr-chip *ngIf=\"promotion.couponCode\">\r\n                {{ promotion.couponCode }}\r\n            </vdr-chip>\r\n        </td>\r\n        <td class=\"left align-middle\">{{ promotion.startsAt | localeDate: 'longDate' }}</td>\r\n        <td class=\"left align-middle\">{{ promotion.endsAt | localeDate: 'longDate' }}</td>\r\n        <td class=\"align-middle\">\r\n            <vdr-chip *ngIf=\"!promotion.enabled\">{{ 'common.disabled' | translate }}</vdr-chip>\r\n        </td>\r\n        <td class=\"right align-middle\">\r\n            <vdr-table-row-action\r\n                iconShape=\"edit\"\r\n                [label]=\"'common.edit' | translate\"\r\n                [linkTo]=\"['./', promotion.id]\"\r\n            ></vdr-table-row-action>\r\n        </td>\r\n        <td class=\"right align-middle\">\r\n            <vdr-dropdown>\r\n                <button type=\"button\" class=\"btn btn-link btn-sm\" vdrDropdownTrigger>\r\n                    {{ 'common.actions' | translate }}\r\n                    <clr-icon shape=\"caret down\"></clr-icon>\r\n                </button>\r\n                <vdr-dropdown-menu vdrPosition=\"bottom-right\">\r\n                    <button\r\n                        type=\"button\"\r\n                        class=\"delete-button\"\r\n                        (click)=\"deletePromotion(promotion.id)\"\r\n                        [disabled]=\"!('DeletePromotion' | hasPermission)\"\r\n                        vdrDropdownItem\r\n                    >\r\n                        <clr-icon shape=\"trash\" class=\"is-danger\"></clr-icon>\r\n                        {{ 'common.delete' | translate }}\r\n                    </button>\r\n                </vdr-dropdown-menu>\r\n            </vdr-dropdown>\r\n        </td>\r\n    </ng-template>\r\n</vdr-data-table>\r\n",
                changeDetection: ChangeDetectionStrategy.OnPush,
                styles: [".search-form{padding:0}.search-input{margin:6px 8px 0 0;min-width:200px}"]
            },] }
];
PromotionListComponent.ctorParameters = () => [
    { type: DataService },
    { type: Router },
    { type: ActivatedRoute },
    { type: NotificationService },
    { type: ModalService }
];

/**
 * Resolves the id from the path into a Customer entity.
 */
class PromotionResolver extends BaseEntityResolver {
    constructor(router, dataService) {
        super(router, {
            __typename: 'Promotion',
            id: '',
            createdAt: '',
            updatedAt: '',
            name: '',
            enabled: false,
            conditions: [],
            actions: [],
        }, id => dataService.promotion.getPromotion(id).mapStream(data => data.promotion));
    }
}
PromotionResolver.ɵprov = i0.ɵɵdefineInjectable({ factory: function PromotionResolver_Factory() { return new PromotionResolver(i0.ɵɵinject(i1.Router), i0.ɵɵinject(i2.DataService)); }, token: PromotionResolver, providedIn: "root" });
PromotionResolver.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root',
            },] }
];
PromotionResolver.ctorParameters = () => [
    { type: Router },
    { type: DataService }
];

const ɵ0 = {
    breadcrumb: marker('breadcrumb.promotions'),
}, ɵ1 = {
    breadcrumb: promotionBreadcrumb,
};
const marketingRoutes = [
    {
        path: 'promotions',
        component: PromotionListComponent,
        data: ɵ0,
    },
    {
        path: 'promotions/:id',
        component: PromotionDetailComponent,
        resolve: createResolveData(PromotionResolver),
        canDeactivate: [CanDeactivateDetailGuard],
        data: ɵ1,
    },
];
function promotionBreadcrumb(data, params) {
    return detailBreadcrumb({
        entity: data.entity,
        id: params.id,
        breadcrumbKey: 'breadcrumb.promotions',
        getName: promotion => promotion.name,
        route: 'promotions',
    });
}

class MarketingModule {
}
MarketingModule.decorators = [
    { type: NgModule, args: [{
                imports: [SharedModule, RouterModule.forChild(marketingRoutes)],
                declarations: [PromotionListComponent, PromotionDetailComponent],
            },] }
];

// This file was generated by the build-public-api.ts script

/**
 * Generated bundle index. Do not edit.
 */

export { MarketingModule, PromotionDetailComponent, PromotionListComponent, PromotionResolver, marketingRoutes, promotionBreadcrumb, ɵ0, ɵ1 };
//# sourceMappingURL=ishop-admin-ui-marketing.js.map
