<template>
    <l-left-middle-right :class="$style.leftMiddleRight">
        <template #left>
            <f-scroll-view :class="$style.leftPanel">
                <u-tree-view :class="$style.treeView" :data-source="conceptTree" expand-trigger="click-expander" text-field="title" value-field="name" :moreChildrenFields="['actions']" @select="onSelect">
                    <template #text="{ node }">
                        <span :class="$style.sidebarNode" :title="node.name + ' ' + node.title" :highlighted="node.highlighted">
                            <i-icon define :class="$style.icon" :name="ICON_TYPE[node.type]" :color="ICON_COLOR[node.type]" :super="node.super"></i-icon> {{ node.name + ' ' + node.title }}
                        </span>
                    </template>
                </u-tree-view>
            </f-scroll-view>
        </template>
        <template #right>
            <u-article :class="$style.rightPanel">
                <h3>图例</h3>
                <ul>
                    <li>
                        <i-icon define :class="$style.icon" :name="ICON_TYPE['concept']" :color="ICON_COLOR['concept']"></i-icon>
                        Concept 概念
                    </li>
                    <li>
                        <i-icon define :class="$style.icon" :name="ICON_TYPE['concept']" :color="ICON_COLOR['concept']" super></i-icon>
                        Abstract Concept 抽象概念(基类)
                    </li>
                    <li>
                        <i-icon define :class="$style.icon" :name="ICON_TYPE['action']" :color="ICON_COLOR['action']"></i-icon>
                        Action 用户操作
                    </li>
                    <li>
                        <i-icon define :class="$style.icon" :name="ICON_TYPE['innerAction']" :color="ICON_COLOR['innerAction']"></i-icon>
                        Event 事件(或内部操作)
                    </li>
                </ul>
                <h3>说明</h3>
                <ul>
                    <li>各个概念的字段定义以前后端接口 JSON 的格式为准</li>
                    <li>每个用户操作对应用户在 UI 界面上的一个确认提交的行为(即可撤销、重做)(如果不考虑多种情况，可以认为是一个核心用例)</li>
                    <li>内部操作/事件用于帮助 Review 功能链路是否有遗漏</li>
                </ul>
            </u-article>
        </template>
        <div>
            <u-article :class="$style.article" v-if="selectedNode">
                <h1>
                    <i-icon define :class="$style.icon" :name="ICON_TYPE[selectedNode.type]" :color="ICON_COLOR[selectedNode.type]" :super="selectedNode.super"></i-icon> {{ selectedNode.name + ' ' + selectedNode.title }}
                </h1>
                <template v-if="selectedNode.type === 'concept'">
                    <template v-if="selectedNode.icon">
                        <h3 style="margin-bottom: 60px;">
                            IDE 中的图标 &nbsp;
                            &nbsp;
                            <i-icon define :name="selectedNode.icon" style="font-size: 12px;"></i-icon>
                            &nbsp;
                            <i-icon define :name="selectedNode.icon" style="font-size: 16px;"></i-icon>
                            &nbsp;
                            <i-icon define :name="selectedNode.icon" style="font-size: 24px;"></i-icon>
                        </h3>
                    </template>
                    <u-tabs :class="$style.tabs" v-model="selectedTab">
                        <u-tab title="字段定义" value="definition">
                            <u-table :class="$style.table">
                                <thead>
                                    <tr>
                                        <th width="15%">名称</th>
                                        <th width="15%">类型</th>
                                        <th width="15%">默认值</th>
                                        <th>描述</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr v-for="property in selectedNode.propertyList" :key="property.name">
                                        <td>{{ property.name }}</td>
                                        <td>{{ property.type }}</td>
                                        <td>{{ property.value }}</td>
                                        <td>{{ property.description }}</td>
                                    </tr>
                                </tbody>
                            </u-table>
                        </u-tab>
                        <u-tab title="JSON 示例" value="json-example"></u-tab>
                        <u-tab title="TypeScript" value="typescript"></u-tab>
                    </u-tabs>
                </template>
                <template v-else-if="selectedNode.type === 'action'">
                    <h2>触发的内部操作/事件</h2>
                    <u-tree-view v-if="selectedNode.innerActions" :data-source="selectedNode.innerActions" expand-trigger="click-expander"
                        text-field="title" value-field="name" children-field="innerActions"
                        readonly readonly-mode="initial"
                        style="border: none; color: #b5b8c3; overflow: hidden;">
                        <template #text="{ node }">
                            <span :title="node.name + ' ' + node.title">
                                <i-icon define :name="ICON_TYPE[node.type]" :color="ICON_COLOR[node.type]"></i-icon> {{ node.name + ' ' + node.title }}
                            </span>
                            &nbsp;
                            <i-icon define :class="$style.search" hover name="search" title="标亮所有包含此内部操作的用户操作" @click="highlightAllActions(node)"></i-icon>
                        </template>
                    </u-tree-view>
                    <span v-else>无</span>
                </template>
            </u-article>
            <x-monaco-editor :class="$style.monacoEditor"
                v-if="selectedTab === 'typescript' && selectedNode && selectedNode.type === 'concept'"
                :value="selectedNodeTypeScript" lang="typescript" theme="vs-dark" readonly></x-monaco-editor>
        </div>
    </l-left-middle-right>
</template>

<script>
import conceptTree from './conceptTree';
import conceptMap from '../../../spec/conceptMap.json';
import XMonacoEditor from '@cloud-ui/x-monaco-editor.vue';
import { utils } from '../../types';

export default {
    components: {
        XMonacoEditor,
    },
    data() {
        return {
            conceptTree,
            conceptMap,
            selectedNode: undefined,
            selectedNodeJSON: '',
            selectedNodeTypeScript: '',
            selectedTab: 'definition',
            ICON_TYPE: {
                concept: 'symbol-method',
                action: 'logic',
                innerAction: 'symbol-event',
            },
            ICON_COLOR: {
                concept: 'primary',
                action: 'success',
                innerAction: 'assist',
            },
        };
    },
    watch: {
        selectedNode(selectedNode) {
            if (!selectedNode)
                return;
            if (selectedNode.type === 'concept') {
                this.selectedNodeJSON = this.concept2JSON(selectedNode);
                this.selectedNodeTypeScript = this.concept2TypeScript(selectedNode);
            } else {
                this.selectedNodeJSON = '';
                this.selectedNodeTypeScript = '';
            }
        },
    },
    created() {
        const root = { type: 'root', children: this.conceptTree };
        utils.traverse((current) => {
            if (current.node.type === 'concept') {
                if (conceptMap[current.node.name]) {
                    Object.assign(current.node, conceptMap[current.node.name]);
                }
            }
        }, { node: root }, { mode: 'onlyChildren' });
    },
    methods: {
        onSelect($event) {
            this.selectedNode = $event.node;
        },
        concept2JSON(concept) {
            return JSON.stringify(concept, null, 4);
        },
        concept2TypeScript(concept) {
            return `class ${concept.name} {
${concept.propertyList.filter((property) => property.immutable)
            .map((property) => `    ${property.name}: ${property.type};`).join('\n')}
}`;
        },
        highlightAllActions(innerAction) {
            const root = { type: 'root', children: this.conceptTree };
            utils.traverse((current) => {
                this.$set(current.node, 'highlighted', false);
            }, { node: root }, { mode: 'onlyArray', depthFirst: true });

            utils.traverse((current) => {
                if (current.node.type === 'innerAction' && current.node.name === innerAction.name) {
                    const stack = current.stack.reverse();
                    for (const item of stack) {
                        this.$set(item, 'expanded', true);
                    }
                    for (const item of stack) {
                        if (item.type === 'action') {
                            this.$set(item, 'highlighted', true);
                            break;
                        }
                    }
                }
            }, { node: root }, { mode: 'onlyArray', depthFirst: true });
        },
    },
};
</script>

<style module>
.leftMiddleRight {
    height: calc(100vh - 60px);
}

.leftPanel {
    width: var(--sidebar-width);
    height: calc(100vh - 60px);
}

.treeView {
    background: var(--designer-panel-background);
    border: none;
    padding: 10px 0;
}

.rightPanel {
    float: left;
    border: none;
    top: 0;
    width: var(--designer-panel-width);
    height: calc(100vh - 60px);
    padding: 0 20px;
    background: var(--designer-panel-background);
}

.search {
    color: var(--color-lighter);
}

.sidebarNode[highlighted] {
    background: rgb(255 255 0 / 80%); /* yellow; */
    color: var(--color-dark);
}

.icon[super] {
    opacity: 0.5;
}

.monacoEditor {
    margin-top: 15px;
}

.tabs[appear="square"] [class^="u-tabs_item__"][selected] {
    background: var(--background-color-default);
}

.table {
    margin-top: 15px;
}

.table tbody > tr:hover > td::before,
.table tbody > tr:hover > td::after {
    display: none;
}
</style>
