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 genGridViewCardTemplate(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-linear-layout gap="small">
                <u-text text="${title}:"></u-text><u-text :text="${expression}"></u-text>
            </u-linear-layout>`;
}

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

    return `<u-grid-view ref="gridView" :data-source="${nameGroup.load}" data-schema="${nameGroup.structure}"
        value-field="${nameGroup.lowerEntity}.id"
        :page-size="20"
        :pageable="true"
        :remote-paging="true"
        :show-sizer="true"
        :repeat="4"
        :border="false"
        :readonly="true"
        :show-foot="true"
        style="height:auto">
        <template #item="scope">
            <u-card title="">
                <u-linear-layout direction="vertical" gap="small">
                    ${propertyList.map((property) => genGridViewCardTemplate(property) + '\n').join('')}
                    <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>
                </u-linear-layout>
            </u-card>
        </template>
</u-grid-view>
`;
}

/**
 * 生成表格 load 逻辑
 * @param entity 实体
 */
export function genGridViewLoadLogic(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 genGridViewRemoveLogic(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('gridView', '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 genGridViewBlock(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, 'gridView');
    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>
    ${genGridViewTemplate(entity, nameGroup)}
</template>
<definition>
{
    "logics": [
        ${JSON.stringify(genGridViewLoadLogic(entity, nameGroup, newStructures, newInterfaces, false))},
        ${JSON.stringify(genGridViewRemoveLogic(entity, nameGroup))}
    ],
    "interfaces": ${JSON.stringify(newInterfaces)},
    "structures": ${JSON.stringify(newStructures)}
}
</definition>
`;
}

export function genGridViewCardBlock(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, 'gridView');
    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>
        ${genGridViewTemplate(entity, nameGroup)}
    </template>
    <definition>
    {
        "logics": [
            ${JSON.stringify(genGridViewLoadLogic(entity, nameGroup, newStructures, newInterfaces, false))},
            ${JSON.stringify(genGridViewRemoveLogic(entity, nameGroup))}
        ],
        "interfaces": ${JSON.stringify(newInterfaces)},
        "structures": ${JSON.stringify(newStructures)}
    }
    </definition>
    `;
}

export default genGridViewBlock;
