
import { register } from "@antv/x6-react-shape";
import { Graph, Node } from "@antv/x6";
import { useSizeHook } from "../../hooks";
import { rosePineDawn } from "thememirror";
import CodeMirror from "@uiw/react-codemirror";

import { javascript } from "@codemirror/lang-javascript";
import { css } from "@codemirror/lang-css";
import { go } from "@codemirror/lang-go";
import { html } from "@codemirror/lang-html";
import { java } from "@codemirror/lang-java";
import { php } from "@codemirror/lang-php";
import { python } from "@codemirror/lang-python";
import { rust } from "@codemirror/lang-rust";
import { sql } from "@codemirror/lang-sql";
import { vue } from "@codemirror/lang-vue";
import { xml } from "@codemirror/lang-xml";
import { yaml } from "@codemirror/lang-yaml";
import { Button, message, Select, Tooltip } from "antd";
import { useState } from "react";

const langMap = {
  javascript: javascript(),
  css: css(),
  go: go(),
  html: html(),
  java: java(),
  php: php(),
  python: python(),
  rust: rust(),
  sql: sql(),
  vue: vue(),
  xml: xml(),
  yaml: yaml(),
};

const component = ({ node, graph }: { node: Node, graph: Graph }) => {
  const { code, language } = node.getData<{
    language:
      | "javascript"
      | "css"
      | "go"
      | "html"
      | "java"
      | "php"
      | "python"
      | "rust"
      | "sql"
      | "vue"
      | "xml"
      | "yaml";
    code: string;
  }>();

  const { size, ref } = useSizeHook();
  const [showSetting, setShowSetting] = useState(false);

  const languageOptions = [
    { value: "javascript", label: "JavaScript" },
    { value: "css", label: "CSS" },
    { value: "go", label: "Go" },
    { value: "html", label: "HTML" },
    { value: "java", label: "Java" },
    { value: "php", label: "PHP" },
    { value: "python", label: "Python" },
    { value: "rust", label: "Rust" },
    { value: "sql", label: "SQL" },
    { value: "typescript", label: "TypeScript" },
    { value: "xml", label: "XML" },
    { value: "yaml", label: "YAML" },
  ]

  const handleCopy = () => {
    navigator.clipboard.writeText(code).then(() => {
      message.success("复制成功");
    })
  }

  graph.on("node:selected", (args) => {
    setShowSetting(graph.getSelectedCells().length === 1 && node.id === args.node.id);
  });
  graph.on("node:unselected", () => {
    setShowSetting(false);
  });

  return (
    <>
      <div className="relative w-full h-full" ref={ref} autoFocus onFocus={() => setShowSetting(true)}>
        {
          showSetting && (
            <div className="absolute" style={{ left: 0, top: -35, zIndex: 1 }}>
              <Tooltip title="切换代码语言">
                <Select style={{ width: 120 }} value={language} options={languageOptions} onChange={(l) => node.setData({ language: l})}/>
              </Tooltip>
              <Tooltip title="复制内容">
                <Button icon={<i className="iconfont icon-fuzhi"/>} onClick={handleCopy}></Button>
              </Tooltip>
            </div>
          )
        }
        <CodeMirror
          value={code}
          height={size.height + "px"}
          width={size.width + "px"}
          extensions={[rosePineDawn, langMap[language]]}
          onChange={(val) => {
            node.setData({ code: val });
          }}
        />
      </div>
    </>
  );
};

register({
  shape: "custom-react-codeBlock",
  width: 420,
  height: 355,
  effect: ["data"],
  component: component,
});

const codeBlock = {
  name: "代码块",
  icon: require("./image/code.svg").default,
  node: {
    shape: "custom-react-codeBlock",
    data: {
      isCode: true,
      code: ``,
      language: "javascript",
    },
  },
};

export default codeBlock;
