import { action, circular, immutable } from '../decorators';
import { config, history, Vertex, Enum, utils, LEVEL_ENUM, ActionOptions } from '..';
import { enumPropertyService } from '../../service/data';

/**
 * 枚举项
 */
export class EnumItem extends Vertex {
    /**
     * 概念类型
     */
    @immutable()
    public readonly level: LEVEL_ENUM = LEVEL_ENUM.enumItem;
    /**
     * Id
     */
    @immutable()
    public readonly id: string = undefined;
    /**
     * 值
     */
    @immutable()
    public readonly value: string = undefined;
    /**
     * 名称
     */
    @immutable()
    public readonly label: string = undefined;
    /**
     * 枚举 Id
     */
    @immutable()
    public readonly enumId: string = undefined;
    /**
     * 父级引用
     */
    @circular()
    @immutable()
    public root: Enum = undefined;
    /**
     * @param source 需要合并的部分参数
     */
    constructor(source?: Partial<EnumItem>) {
        super();
        source && this.assign(source);
    }
    /**
     * 添加枚举项
     */
    @action('添加枚举项')
    async create(none?: void, actionOptions?: ActionOptions) {
        config.defaultApp?.emit('saving');

        const body = this.toJSON();
        utils.logger.debug('添加枚举项', body);

        const result: EnumItem = await enumPropertyService.create({
            headers: {
                appId: config.defaultApp?.id,
                operationAction: actionOptions?.actionName || 'EnumItem.create',
                operationDesc: actionOptions?.actionDesc || `添加枚举项"${this.label}"`,
            },
            body,
        });
        this.deepPick(result, ['id']);

        this.root.dataNode.service.emit('dataTypesChange');
        this.root.dataNode.service.emit('enumsChange');
        this.root.dataNode.service.emit('vertexIdToNameChange', this.id, this.label);

        await config.defaultApp?.history.load();
        config.defaultApp?.emit('saved');
        return this;
    }
    /**
     * 删除枚举项
     */
    @action('删除枚举项')
    async delete(none?: void, actionOptions?: ActionOptions) {
        config.defaultApp?.emit('saving');

        if (this.id) {
            await enumPropertyService.delete({
                headers: {
                    appId: config.defaultApp?.id,
                    operationAction: actionOptions?.actionName || 'EnumItem.delete',
                    operationDesc: actionOptions?.actionDesc || `删除枚举项"${this.label}"`,
                },
                query: {
                    id: this.id,
                },
            });
        }

        const index = this.root.enumItemList.indexOf(this);
        ~index && this.root.enumItemList.splice(index, 1);
        this.destroy();
        this.root.dataNode.service.emit('dataTypesChange');
        this.root.dataNode.service.emit('enumsChange');

        await config.defaultApp?.history.load();
        config.defaultApp?.emit('saved');
    }
    /**
     * 修改枚举项
     */
    async update(none?: void, actionOptions?: ActionOptions, then?: () => Promise<any>) {
        config.defaultApp?.emit('saving');
        const body = this.toJSON();

        body._posIndex = this.root.enumItemList.indexOf(this);
        await enumPropertyService.update({
            headers: {
                appId: config.defaultApp?.id,
                operationAction: actionOptions?.actionName || 'EnumItem.update',
                operationDesc: actionOptions?.actionDesc || `修改枚举项"${this.name}"`,
            },
            body,
        });

        await then?.();
        await config.defaultApp?.history.load();
        config.defaultApp?.emit('saved');
        return this;
    }
    /**
     * 设置枚举项值
     * @param value
     */
    async setValue(value: string) {
        this.assign({ value });
        await this.update(undefined, {
            actionDesc: '设置枚举项值',
        });

        this.root.dataNode.service.emit('dataTypesChange');
        this.root.dataNode.service.emit('enumsChange');
        this.root.dataNode.service.emit('vertexIdToNameChange', this.id, this.value);
    }
    /**
     * 设置枚举项标题
     * @param value
     */
    async setLabel(label: string) {
        this.assign({ label });
        await this.update(undefined, {
            actionDesc: '设置枚举项标题',
        });

        this.root.dataNode.service.emit('dataTypesChange');
        this.root.dataNode.service.emit('enumsChange');
        this.root.dataNode.service.emit('vertexIdToNameChange', this.id, this.value);
    }
}

export default EnumItem;
