import {
    dataTypesMap, vertexsMap, Entity, EntityProperty, View,
    LEVEL_ENUM, utils,
} from '../..';
import {
    getExpression, filterProperty, NameGroup, genUniqueQueryNameGroup,
    getFirstDisplayedProperty, getParamFromResolver,
    genGenericTypeSchema, genVariable, genInterParam, genCallComponentLogic,
    genCallInterface, genQueryInterface, genQueryStructure,
    genCallInterfaceFromTempInterface,
} from '.';

/**
 * 根据实体属性生成表格列模板
 * @param property 实体属性
 */
export function genTableColumnTemplate(property: EntityProperty) {
    const lowerEntityName = utils.firstLowerCase(property.root.name);
    let expression = `scope.item.${lowerEntityName}.${property.name}`;
    const title = property.label || property.name;

    if (dataTypesMap[property.typeKey].type === 'enum')
        expression = getExpression(property, `scope.item.${lowerEntityName}.${property.name}`);
    else if (property.$relationEntity) { // 有外键关联
        const relationEntity = vertexsMap.get(property.$relationEntity) as Entity;
        if (relationEntity) {
            const displayedProperty = getFirstDisplayedProperty(relationEntity);
            if (displayedProperty) {
                expression = getExpression(property, `scope.item.${utils.firstLowerCase(relationEntity.name)}.${displayedProperty.name}`);
            } else
                return '';
        } else
            return '';
    } else
        expression = getExpression(property, `scope.item.${lowerEntityName}.${property.name}`);

    return `<u-table-view-column title="${title}">
    <template #cell="scope">
        <u-linear-layout gap="small">
            <u-text :text="${expression}"></u-text>
        </u-linear-layout>
    </template>
</u-table-view-column>`;
}

/**
 * 生成表格模板
 * @param entity 实体
 * @param nameGroup 命名组
 */
export function genTableTemplate(entity: Entity, nameGroup: NameGroup) {
    const propertyList = entity.propertyList
        .filter(filterProperty('inTable'));

    return `<u-table-view ref="tableView" :data-source="${nameGroup.load}" data-schema="${nameGroup.structure}"
        value-field="${nameGroup.lowerEntity}.id"
        pageable remote-paging>
    <u-table-view-column type="index" width="60" title="序号"></u-table-view-column>

    ${propertyList.map((property) => genTableColumnTemplate(property) + '\n').join('')}

    <u-table-view-column title="操作">
        <template #cell="scope">
            <u-linear-layout gap="small">
                <u-link @click="${nameGroup.modify || 'modify'}($event, scope)">修改</u-link>
                <u-link @click="${nameGroup.remove}($event, scope)">删除</u-link>
            </u-linear-layout>
        </template>
    </u-table-view-column>
</u-table-view>
`;
}

/**
 * 生成表格 load 逻辑
 * @param entity 实体
 */
export function genTableLoadLogic(entity: Entity, nameGroup: NameGroup,
    newStructures: Array<any>, newInterfaces: Array<any>, supportFilter: boolean) {
    const paramsSchema = {
        $ref: '#/systemTypes/DataSourceParams',
    };
    const resultSchema = genGenericTypeSchema('PageOf', { T: { $ref: nameGroup.structure } });
    const params = [
        genInterParam(
            `${newInterfaces[0].name}.${newInterfaces[0].logic.params[0].name}`,
            'params.page',
            [undefined, undefined],
        ),
        genInterParam(
            `${newInterfaces[0].name}.${newInterfaces[0].logic.params[1].name}`,
            'params.size',
            [undefined, undefined],
        ),
        genInterParam(
            `${newInterfaces[0].name}.${newInterfaces[0].logic.params[2].name}`,
            'params.sort',
            [undefined, undefined],
        ),
        genInterParam(
            `${newInterfaces[0].name}.${newInterfaces[0].logic.params[3].name}`,
            'params.order',
            [undefined, undefined],
        ),
    ];

    if (supportFilter)
        params.push(
            genInterParam(
                `${newInterfaces[0].name}.${newInterfaces[0].logic.params[4].name}`,
                'filter',
                [undefined],
            ),
        );

    return {
        level: 'logic',
        name: nameGroup.load,
        params: [{
            level: 'param',
            type: 'Identifier',
            name: 'params',
            schema: paramsSchema,
        }],
        returns: [
            genVariable('result', resultSchema, LEVEL_ENUM.return),
        ],
        variables: [] as Array<any>,
        body: [{
            level: 'logicNode',
            type: 'Start',
            label: '开始',
        }, {
            level: 'logicNode',
            type: 'AssignmentExpression',
            label: '赋值',
            operator: '=',
            left: {
                level: 'expressionNode',
                type: 'Identifier',
                name: 'result',
            },
            right: genCallInterfaceFromTempInterface(newInterfaces[0], params),
        }, {
            level: 'logicNode',
            type: 'End',
            label: '结束',
        }],
    };
}

/**
 * 生成表格 remove 逻辑
 * @param entity 实体
 */
export function genTableRemoveLogic(entity: Entity, nameGroup: NameGroup) {
    const scopeStructureSchema = genGenericTypeSchema('ScopeOf', { T: { $ref: nameGroup.structure } });
    const deleteResolver = entity.resolvers.find((resolver) => resolver.name === 'delete');
    const deleteInterface = deleteResolver.interface;
    const idParam = getParamFromResolver(deleteResolver, 'id');
    const idProperty = entity.propertyList.find((property) => property.primaryKey || property.name === 'id');

    return {
        level: 'logic',
        name: nameGroup.remove,
        params: [{
            level: 'param',
            type: 'Identifier',
            name: 'event',
            schema: { $ref: '#/basicTypes/String' },
        }, {
            level: 'param',
            name: 'scope',
            schema: scopeStructureSchema,
        }],
        returns: [] as Array<any>,
        variables: [] as Array<any>,
        body: [{
            level: 'logicNode',
            type: 'Start',
            label: '开始',
        },
        genCallInterface(deleteInterface, [
            genInterParam(
                idParam.id,
                `scope.item.${nameGroup.lowerEntity}.id`,
                ['', '', `${nameGroup.structure}.${nameGroup.lowerEntity}`, idProperty.id],
            ),
        ]),
        genCallComponentLogic('tableView', 'reload'),
        {
            level: 'logicNode',
            label: '结束',
            type: 'End',
        }],
    };
}

/**
 * 生成表格区块
 * @param entity 实体
 * @param view 所插入的页面，用于生成逻辑名字，去重等
 * @notice 目前 logic 名去重做成前置处理了，与 mergeBlock 的后置处理不冲突
 *        (页面 load 名) -产生-> (interface 名) -产生-> (structure 名)
 *        load -> load_someView_tableView
 *        load_select_student -> load_someView_select_student
 */
export function genTableBlock(entity: Entity, view: View) {
    const existingNameSets = {
        viewLogic: new Set(view.$def.logics.map((logic) => logic.name)),
        interface: new Set(entity.dataNode.service.interfaces.map((itface) => itface.name)),
        structure: new Set(entity.dataNode.structures.map((structure) => structure.name)),
    };

    const nameGroup = genUniqueQueryNameGroup(existingNameSets, view.name, 'tableView');
    nameGroup.remove = utils.unique('remove', existingNameSets.viewLogic);
    nameGroup.lowerEntity = utils.firstLowerCase(entity.name);

    // 收集所有和本实体关联的实体
    const allEntities = [entity];
    entity.propertyList.forEach((property) => {
        if (property.$relationEntity) { // 有外键关联
            const relationEntity = vertexsMap.get(property.$relationEntity) as Entity;
            if (relationEntity) {
                const displayedProperty = getFirstDisplayedProperty(relationEntity);
                if (displayedProperty)
                    allEntities.push(relationEntity);
            }
        }
    });

    const newStructures: Array<any> = [genQueryStructure(allEntities, nameGroup)];
    const newInterfaces: Array<any> = [genQueryInterface(allEntities, nameGroup, false, true)];

    return `
<template>
    ${genTableTemplate(entity, nameGroup)}
</template>
<definition>
{
    "logics": [
        ${JSON.stringify(genTableLoadLogic(entity, nameGroup, newStructures, newInterfaces, false))},
        ${JSON.stringify(genTableRemoveLogic(entity, nameGroup))}
    ],
    "interfaces": ${JSON.stringify(newInterfaces)},
    "structures": ${JSON.stringify(newStructures)}
}
</definition>
`;
}

export function genTableColumnBlock(property: EntityProperty, view: View) {
    const entity = property.root;

    const existingNameSets = {
        viewLogic: new Set(view.$def.logics.map((logic) => logic.name)),
        interface: new Set(entity.dataNode.service.interfaces.map((itface) => itface.name)),
        structure: new Set(entity.dataNode.structures.map((structure) => structure.name)),
    };

    const nameGroup = genUniqueQueryNameGroup(existingNameSets, view.name, 'tableView');
    nameGroup.remove = utils.unique('remove', existingNameSets.viewLogic);
    nameGroup.lowerEntity = utils.firstLowerCase(entity.name);

    // 收集所有和本实体关联的实体
    const allEntities = [entity];
    const propertyList = [property];
    propertyList.forEach((property) => {
        if (property.$relationEntity) { // 有外键关联
            const relationEntity = vertexsMap.get(property.$relationEntity) as Entity;
            if (relationEntity) {
                const displayedProperty = getFirstDisplayedProperty(relationEntity);
                if (displayedProperty)
                    allEntities.push(relationEntity);
            }
        }
    });

    const newStructures: Array<any> = [genQueryStructure(allEntities, nameGroup)];
    const newInterfaces: Array<any> = [genQueryInterface(allEntities, nameGroup, false, true)];

    return `
<template>
    <u-table-view ref="tableView" :data-source="${nameGroup.load}" pageable remote-paging data-schema="${nameGroup.structure}">
        ${propertyList.map((property) => genTableColumnTemplate(property) + '\n').join('')}
    </u-table-view>
</template>
<definition>
{
    "logics": [
        ${JSON.stringify(genTableLoadLogic(entity, nameGroup, newStructures, newInterfaces, false))}
    ],
    "interfaces": ${JSON.stringify(newInterfaces)},
    "structures": ${JSON.stringify(newStructures)}
}
</definition>
`;
}

export default genTableBlock;
