import {
  IconStrikethrough,
  IconTextBold,
  IconTextCenter,
  IconTextItalic,
  IconTextJustify,
  IconTextLeft,
  IconTextLetterSpacing,
  IconTextLineHeight,
  IconTextRight,
  IconTextSize,
  IconTextUnderline,
} from "@/assets/icons";
import { css } from "@linaria/core";
import { Button, InputNumber, Tooltip } from "ant-design-vue";

import { useEditor } from "@/modules/editor";
import Select from "@queenjs-modules/queditor/components/FormUI/Items/Select";
import "@simonwep/pickr/dist/themes/nano.min.css";
import _ from "lodash";
import { queenApi } from "queenjs";
import {
  defineComponent,
  onMounted,
  onUnmounted,
  reactive,
  ref,
  toRaw,
  watch,
} from "vue";
import { any, bool, func, number, object, string } from "vue-types";
interface ColumnItem {
  label?: string;
  component?: ((...args: any[]) => any) | Record<string, any>;
  dataIndex?: string;
  props?: { [name: string]: any };
  itemProps?: { [name: string]: any };
  changeExtra?: (data: any) => any;
}

export const TextColor = defineComponent({
  props: {
    value: string().def("#666666"),
  },
  emits: ["change"],
  setup(props, { emit }) {
    let pickerRef = ref();

    const state = reactive({
      color: props.value,
    });
    watch(
      () => props.value,
      () => {
        state.color = props.value;
      }
    );
    const colorChange = (e: any) => {
      const hexa = e.target.value;
      emit("change", hexa);
      state.color = hexa;
    };

    return () => (
      <div
        class={ColorPicker}
        onClick={() => {
          pickerRef?.value.click();
        }}
      >
        <div class="color_picker" style={{ backgroundColor: state.color }}>
          <input
            type="color"
            class="color_input"
            ref={pickerRef}
            value={state.color}
            onInput={_.debounce(colorChange, 300)}
          />
        </div>
      </div>
    );
  },
});
export const AlignComp = defineComponent({
  props: {
    value: string<"left" | "right" | "center" | "justify">().def("left"),
  },
  emits: ["change"],
  setup(props, { emit }) {
    const aligns = [
      {
        label: "左对齐",
        key: "left",
        icon: <IconTextLeft />,
      },
      {
        label: "居中对齐",
        key: "center",
        icon: <IconTextCenter />,
      },
      {
        label: "右对齐",
        key: "right",
        icon: <IconTextRight />,
      },
      {
        label: "两端对齐",
        key: "justify",
        icon: <IconTextJustify />,
      },
    ];
    return () => (
      <div class={AlignCompWapper}>
        {aligns.map((e: any) => {
          return (
            <Tooltip title={e.label} placement="top">
              <Button
                class={props.value == e.key ? currStyle : null}
                icon={e.icon}
                type="text"
                onClick={() => {
                  emit("change", e.key);
                }}
              ></Button>
            </Tooltip>
          );
        })}
      </div>
    );
  },
});
export const LetterSpacingComp = defineComponent({
  props: {
    value: any<string | number>().def(0),
  },
  emits: ["change"],
  setup(props, { emit }) {
    return () => {
      const value =
        typeof props.value === "string" ? parseInt(props.value) : props.value;

      return (
        <InputNumber
          prefix={<IconTextLetterSpacing class="text-22px mr-6px" />}
          defaultValue={0}
          min={0}
          max={100}
          step={1}
          value={value}
          onChange={(value: any) => {
            if (!value) {
              emit("change", "0px");
              return;
            }
            emit("change", value + "px");
          }}
        />
      );
    };
  },
});

export const LineHeightComp = defineComponent({
  props: {
    value: any<string | number>().def(1.5),
  },
  emits: ["change"],
  setup(props, { emit }) {
    return () => {
      const value =
        typeof props.value === "string" ? parseFloat(props.value) : props.value;
      return (
        <InputNumber
          prefix={<IconTextLineHeight class="text-22px mr-6px" />}
          defaultValue={1.5}
          min={0.5}
          max={3}
          step={0.5}
          value={value || 1.5}
          onChange={(value: any) => {
            if (!value) {
              emit("change", 1.5);
              return;
            }
            emit("change", value);
          }}
        />
      );
    };
  },
});
export const FontStyleWapper = defineComponent({
  emits: ["change"],
  setup(props, { emit }) {
    const fontStyleColumns = [
      {
        label: "加粗",
        dataIndex: "bold",
        icon: <IconTextBold />,
      },
      {
        label: "斜体",
        dataIndex: "italic",
        icon: <IconTextItalic />,
      },
      {
        label: "下划线",
        dataIndex: "underline",
        icon: <IconTextUnderline />,
      },
      {
        label: "删除线",
        dataIndex: "strikethrough",
        icon: <IconStrikethrough />,
      },
    ];
    const changeVal = (e: any) => {
      emit("change", e);
    };
    return () => (
      <div class={[FontStyleCompWapper]}>
        {fontStyleColumns.map((e: any) => {
          return (
            <TextToolItem
              key={e.dataIndex}
              class={"!mr-0"}
              column={{
                label: e.label,
                dataIndex: e.dataIndex,
                component: (props) => {
                  return <FontStyleComp icon={e.icon} {...props} />;
                },
              }}
              onChange={changeVal}
            />
          );
        })}
      </div>
    );
  },
});
export const FontStyleComp = defineComponent({
  props: {
    icon: any(),
    value: bool().def(false),
  },
  emits: ["change"],
  setup(props, { emit }) {
    return () => {
      return (
        <Button
          type="text"
          class={props.value ? currStyle : null}
          icon={props.icon}
          onClick={() => {
            emit("change", !props.value);
          }}
        ></Button>
      );
    };
  },
});

export const FontFamily = defineComponent({
  props: {
    value: string().def(""),
  },
  emits: ["change"],
  setup(props, { emit }) {
    const options = [
      { label: "默认字体", value: "" },
      { label: "宋体", value: "宋体,Songti,STSong,serif" },
      { label: "黑体", value: "黑体,Heiti,STHeiti,sans-serif" },
      { label: "仿宋", value: "仿宋,FangSong,STFangsong,serif" },
      { label: "楷体", value: "楷体,KaiTi,STKaiti,sans-serif" },
    ];
    return () => {
      return (
        <Select
          options={options}
          value={props.value || ""}
          onChange={(v) => {
            emit("change", v);
          }}
        ></Select>
      );
    };
  },
});
export const FontSize = defineComponent({
  props: {
    value: any().def("12px"),
  },
  emits: ["change"],
  setup(props, { emit }) {
    return () => {
      return (
        <InputNumber
          prefix={<IconTextSize class="text-22px mr-6px" />}
          defaultValue={12}
          min={12}
          max={60}
          value={parseInt(props.value) || 12}
          onChange={(value: any) => {
            if (!value) {
              emit("change", "12px");
              return;
            }
            emit("change", value + "px");
          }}
        />
      );
    };
  },
});
export const LinkButton = defineComponent({
  props: {
    icon: any(),
    value: any(),
  },
  emits: ["change"],
  setup(props, { emit }) {
    const showLinkInput = async () => {
      const res = await queenApi.showInput({
        title: "请输入链接地址",
        defaultValue: "http://",
      });
      emit("change", res);
    };
    return () => (
      <Button type="text" icon={props.icon} onClick={showLinkInput}></Button>
    );
  },
});

export const TextToolItem = defineComponent({
  props: {
    column: object<ColumnItem>(),
    index: number(),
    onChange: func(),
  },
  setup(props) {
    const state = reactive({
      value: undefined,
    });

    const { controls } = useEditor();
    let editor: any = null;
    watch(
      () => controls.textEditorCtrl.state.currEditor,
      () => {
        editor = toRaw(controls.textEditorCtrl.state.currEditor);
        initCommands();
      }
    );
    function handleValueChange() {
      const { column } = props;
      if (!editor) {
        return;
      }
      const command = editor.commands.get(column?.dataIndex);
      if (command) {
        state.value = command.value;
      }
    }
    const initCommands = () => {
      const { column } = props;
      if (!editor) {
        return;
      }
      const command = editor.commands.get(column?.dataIndex);
      if (command) {
        console.log("init", column?.dataIndex, command.value);
        state.value = command.value;
        command.on("change:value", handleValueChange);
      }
    };
    onMounted(() => {
      initCommands();
    });
    onUnmounted(() => {
      const { column } = props;
      if (!editor) {
        return;
      }
      const command = editor.commands.get(column?.dataIndex);
      if (command) {
        command.off("change:value", handleValueChange);
      }
    });

    const changeVal = (value: any, ...args: any[]) => {
      const { column } = props;
      let params = {
        dataIndex: column?.dataIndex,
        value: { value },
        ...args,
      };
      if (column?.changeExtra) params = column.changeExtra?.(params);
      props.onChange?.(params);
      return params;
    };

    const component = props.column?.component || null;
    return () => {
      const { column, index } = props;
      return (
        <div
          key={column?.dataIndex || "" + index}
          class={formItemStyles}
          {...column?.itemProps}
          onClick={(e) => e.stopPropagation()}
        >
          {column?.label ? (
            <Tooltip title={column.label} placement="top">
              <component
                value={state.value}
                {...column.props}
                onChange={changeVal}
              />
            </Tooltip>
          ) : (
            <component
              value={state.value}
              {...column?.props}
              onChange={changeVal}
            />
          )}
        </div>
      );
    };
  },
});

const currStyle = css`
  color: @inf-primary-color;
  &:hover,
  &:focus {
    color: @inf-primary-color;
  }
`;
const ColorPicker = css`
  position: relative;
  width: 32px;
  height: 32px;
  border-radius: 2px;
  cursor: pointer;
  .color_picker {
    width: 100%;
    height: 100%;
    border-radius: 2px;
    border: 1px solid transparent;
    &:focus,
    &:hover {
      border-color: @inf-primary-color;
      box-shadow: 0 0 0 2px rgba(232, 139, 0, 0.2);
    }
  }
  .color_input {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 0;
    padding: 0;
    border: none;
    visibility: hidden;
  }
`;

const AlignCompWapper = css`
  display: flex;
  .ant-btn {
    flex: 1;
    width: 100%;
    line-height: 1;
    .inficon {
      font-size: 22px;
    }
  }
`;
const FontStyleCompWapper = css`
  flex: 1;
  display: flex;
  align-items: center;
  margin-right: 12px;
  border-radius: 2px;
  & > div {
    flex: 1;
    border-radius: 0;
    .ant-btn {
      width: 100%;
      line-height: 1;
      .inficon {
        font-size: 22px;
      }
    }
  }
`;

const formItemStyles = css`
  height: 100%;
  flex: 1;
  margin-right: 12px;
  background-color: #303030;
  border-radius: 2px;
  &:last-child {
    margin-right: 0;
  }
  &.disabled {
    cursor: not-allowed;
  }
`;
