<template>
    <component :is="nodesComp" />
    <component v-if="leftNodesComp" :is="leftNodesComp" />
    <component v-if="rightNodesComp" :is="rightNodesComp" />
    <Links v-if="branches" :links="unref(branches)" />
</template>

<script lang="tsx">
import "components/common/table.css";
import { jsx } from "features/feature";
import Links from "features/links/Links.vue";
import type { GenericTreeNode, TreeBranch } from "features/trees/tree";
import { coerceComponent, processedPropType, renderJSX, unwrapRef } from "util/vue";
import type { Component } from "vue";
import { defineComponent, shallowRef, toRefs, unref, watchEffect } from "vue";

export default defineComponent({
    props: {
        nodes: {
            type: processedPropType<GenericTreeNode[][]>(Array),
            required: true
        },
        leftSideNodes: processedPropType<GenericTreeNode[]>(Array),
        rightSideNodes: processedPropType<GenericTreeNode[]>(Array),
        branches: processedPropType<TreeBranch[]>(Array)
    },
    components: { Links },
    setup(props) {
        const { nodes, leftSideNodes, rightSideNodes } = toRefs(props);

        const nodesComp = shallowRef<Component | "">();
        watchEffect(() => {
            const currNodes = unwrapRef(nodes);
            nodesComp.value = coerceComponent(
                jsx(() => (
                    <>
                        {currNodes.map(row => (
                            <span class="row tree-row" style="margin: 50px auto;">
                                {row.map(renderJSX)}
                            </span>
                        ))}
                    </>
                ))
            );
        });

        const leftNodesComp = shallowRef<Component | "">();
        watchEffect(() => {
            const currNodes = unwrapRef(leftSideNodes);
            leftNodesComp.value = currNodes
                ? coerceComponent(
                      jsx(() => (
                          <span class="left-side-nodes small">{currNodes.map(renderJSX)}</span>
                      ))
                  )
                : "";
        });

        const rightNodesComp = shallowRef<Component | "">();
        watchEffect(() => {
            const currNodes = unwrapRef(rightSideNodes);
            rightNodesComp.value = currNodes
                ? coerceComponent(
                      jsx(() => <span class="side-nodes small">{currNodes.map(renderJSX)}</span>)
                  )
                : "";
        });

        return {
            unref,
            nodesComp,
            leftNodesComp,
            rightNodesComp
        };
    }
});
</script>

<style scoped>
.left-side-nodes {
    position: absolute;
    left: 15px;
    top: 65px;
}

.side-nodes {
    position: absolute;
    right: 15px;
    top: 65px;
}

.left-side-nodes :deep(.treeNode),
.side-nodes :deep(.treeNode) {
    margin: 20px auto;
}

.small :deep(.treeNode) {
    height: 60px;
    width: 60px;
}

.small :deep(.treeNode) > *:first-child {
    font-size: 30px;
}
</style>