import { CompObject } from "@/modules/editor/controllers/SelectCtrl/compObj";
import { TreeToolbars } from "@/modules/editor/objects/Toolbars";
import { css } from "@linaria/core";
import { Image } from "@queenjs/ui";
import { useReactive } from "@queenjs/use";
import { Tree } from "ant-design-vue";
import { defineComponent, watch } from "vue";
import { string } from "vue-types";
import { useEditor } from "../../../..";
import { DesignComp } from "../../../../objects/DesignTemp/DesignComp";

type TreeItem = {
  key: string;
  title: string;
  value: string;
  children: TreeItem[];
};

export const CompTree = defineComponent({
  setup() {
    const { store, actions, helper, controls } = useEditor();
    const { compUICtrl } = controls;

    const state = useReactive(() => ({
      expandedKeys: [] as string[],
      treeData() {
        const rootComp = helper.findRootComp();

        function getCompChildren(ids: string[]): TreeItem[] {
          return ids.map((id) => {
            const comp = helper.findComp(id) as DesignComp;
            return {
              key: comp.id,
              title:
                comp.title ||
                compUICtrl.state.components.get(comp.compKey)?.name ||
                "未命名",
              value: comp.id,
              children: getCompChildren(comp.getChildIds()),
            };
          });
        }
        return getCompChildren(rootComp?.id ? [rootComp.id] : []);
      },
    }));

    watch(
      () => store.currCompId,
      () => {
        state.expandedKeys = store.currCompId
          ? helper.getCompTrees(store.currCompId).map((comp) => comp.id)
          : [];
      }
    );

    return () => {
      return (
        <Tree
          class={treeStyle}
          treeData={state.treeData}
          v-model={[state.expandedKeys, "expandedKeys"]}
          selectedKeys={[store.currCompId]}
          blockNode={true}
          onSelect={(ids) => {
            const id =
              (ids[0] as string) || state.expandedKeys.at(-2) || "root";
            if (helper.isStreamCardChild(id)) {
              controls.selectCtrl.selecteObjs([
                new CompObject(store.compMap[id]),
              ]);
              return;
            }
            actions.pickComp(id);
          }}
        >
          {{
            title: (data: any) => {
              return <CompNode title={data.title} id={data.key} />;
            },
          }}
        </Tree>
      );
    };
  },
});

const CompNode = defineComponent({
  props: {
    id: string().isRequired,
    title: string().isRequired,
  },
  setup(props) {
    const editor = useEditor();
    const comp = editor.helper.findComp(props.id);
    return () => {
      if (!comp) return;
      const compOpts = editor.controls.compUICtrl.state.components.get(
        comp.compKey
      );
      const actions = TreeToolbars[comp.compKey] || TreeToolbars.default;
      const thumbnail =
        comp.compKey === "Image"
          ? comp.value.url
          : comp.thumbnail || compOpts?.thumbnail;
      return (
        <div class={nodeStyle}>
          <Image src={thumbnail} size={240} />
          <span class="w-0 flex-1 truncate">{props.title}</span>
          <span class="space-x-4px">
            {actions.map((action) =>
              action.getVisible.call(editor, comp) ? (
                <action.component
                  class="p-4px"
                  key={comp.id}
                  value={action.getValue?.(comp)}
                  onClick={(e: MouseEvent) => {
                    e.stopPropagation();
                    action.onClick.call(editor, comp);
                  }}
                />
              ) : null
            )}
          </span>
        </div>
      );
    };
  },
});

const treeStyle = css`
  .ant-tree-switcher {
    display: flex;
    justify-content: center;
    align-items: center;
  }
`;

const nodeStyle = css`
  display: flex;
  align-items: center;
  padding: 6px;
  @apply rounded;

  > img {
    width: 24px;
    height: 24px;
    margin-right: 6px;
    object-fit: contain;
  }
`;
