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

import { useEditor } from "@/modules/editor";
import Select from "@queenjs-modules/queditor/components/FormUI/Items/Select";

import { queenApi } from "queenjs";
import {
  defineComponent,
  nextTick,
  onMounted,
  onUnmounted,
  reactive,
  toRaw,
  watch,
} from "vue";
import { any, bool, func, number, object, string } from "vue-types";
import NewColorPicker from "../../formItems/NewColorPicker";
import { isNumber } from "lodash";
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 }) {
    const state = reactive({
      color: props.value,
    });
    watch(
      () => props.value,
      () => {
        state.color = props.value;
      }
    );
    const colorChange = (value: string) => {
      emit("change", value);
      state.color = value;
    };

    return () => (
      <NewColorPicker
        value={state.color}
        onChange={colorChange}
        showGradient={false}
      />
    );
  },
});
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 () => {
      let value =
        typeof props.value === "string" ? parseInt(props.value) : props.value;
      value = isNumber(value) ? value : 0;

      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 () => {
      let value =
        typeof props.value === "string" ? parseFloat(props.value) : props.value;
      value = isNumber(value) ? value : 1.5;
      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 () => {
      let item = options.find((e) => {
        return e.value.indexOf(props.value) != -1;
      });
      const value = item ? item.value : "";
      return (
        <Select
          options={options}
          value={value || ""}
          onChange={(v) => {
            emit("change", v);
          }}
        ></Select>
      );
    };
  },
});
export const FontSize = defineComponent({
  props: {
    value: any().def("12px"),
  },
  emits: ["change"],
  setup(props, { emit }) {
    return () => {
      let value =
        typeof props.value === "string" ? parseInt(props.value) : props.value;
      value = isNumber(value) ? value : 12;
      return (
        <InputNumber
          prefix={<IconTextSize class="text-22px mr-6px" />}
          defaultValue={12}
          min={12}
          max={60}
          value={value}
          onChange={(value: any) => {
            if (!value) {
              emit("change", "12px");
              return;
            }
            emit("change", value + "px");
          }}
        />
      );
    };
  },
});

export const TextStroke = defineComponent({
  props: {
    value: any().def(undefined),
  },
  emits: ["change"],
  setup(props, { emit }) {
    const state = reactive({
      visible: props.value ? true : false,
      width: 1,
      color: "#666666",
    });
    watch(
      () => props.value,
      () => {
        formatVal(props.value);
      }
    );
    const formatVal = (value: any) => {
      if (!value) {
        state.visible = false;
        state.color = "#666666";
        state.width = 1;
        return;
      }
      state.visible = true;
      const colorReg = /#[a-zA-Z0-9]{6}/g;
      let color = value.match(colorReg);
      if (color) {
        color = color[0];
      } else {
        color = "#666666";
      }
      state.color = color;
      const widthReg = /\d+px/g;
      let width = value.match(widthReg);
      if (width) {
        width = width[0];
      } else {
        width = 1;
      }
      state.width = parseInt(width);
    };
    const colorChange = (v: string) => {
      state.color = v;
      buildValueSub();
    };
    const visibleChange = (e: any) => {
      const checked = e.target.checked;
      state.visible = checked;
      buildValueSub();
    };
    const widthChange = (e: any) => {
      state.width = e;
      buildValueSub();
    };
    const buildValueSub = () => {
      if (!state.visible) {
        return;
      }
      const value = `${state.width}px ${state.color}`;
      emit("change", value);
    };

    return () => {
      return (
        <div class={"flex-1"}>
          <div class={"flex justify-between items-center  w-full"}>
            <div class={"flex-1 flex items-center"}>
              <Checkbox checked={state.visible} onChange={visibleChange} />

              {state.visible && (
                <div class={"flex-1 px-20px"}>
                  <Tooltip title={"描边宽度"} placement="top">
                    <InputNumber
                      class={StrokeStyle}
                      min={1}
                      max={5}
                      step={1}
                      value={state.width}
                      onChange={widthChange}
                    />
                  </Tooltip>
                </div>
              )}
            </div>
            <Tooltip title={"描边颜色"} placement="top">
              <TextColor value={state.color} onChange={colorChange} />
            </Tooltip>
          </div>
        </div>
      );
    };
  },
});

// 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>
//     );
//   },
// });
const stylesKey: { [key: string]: any } = {
  fontSize: "font-size",
  fontFamily: "font-family",
  letterSpacing: "letter-spacing",
  lineHeight: "line-height",
  alignment: "text-align",
  fontColor: "color",
  textStroke: "-webkit-text-stroke",
};
const tagsKey: { [key: string]: any } = {
  bold: "<strong>",
  italic: "<i>",
  underline: "<u>",
  strikethrough: "<s>",
};
export const TextToolItem = defineComponent({
  props: {
    column: object<ColumnItem>(),
    index: number(),
    onChange: func(),
  },
  setup(props) {
    const state = reactive({
      value: undefined as any,
    });

    const { controls, store, actions, helper } = useEditor();
    let editor: any = null;
    watch(
      () => controls.textEditorCtrl.state.currEditor,
      () => {
        editor = toRaw(controls.textEditorCtrl.state.currEditor);
        initCommands();
      }
    );
    watch(
      () => store.currComp.value,
      () => {
        editor = toRaw(controls.textEditorCtrl.state.currEditor);
        if (!editor && store.currComp.compKey == "Text") {
          initCommands();
          nextTick(() => {
            const element: HTMLElement | null = document.querySelector(
              `#editor_${store.currComp.id}`
            );
            if (!element) {
              return;
            }
            const h = helper.pxToDesignSize(element.clientHeight);
            console.log(h);
            actions.updateCompData(store.currComp, "layout.size.1", h);
            helper.extendStreamCard(store.currStreamCardId);
            actions.selectObjs([]);
            setTimeout(() => {
              actions.selectObjs([store.currComp.id]);
            }, 0);
          });
        }
      }
    );
    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) {
        if (!column?.dataIndex) {
          return;
        }
        const compValue = store.currComp.value;
        if (tagsKey[column.dataIndex]) {
          const hasTag = compValue.indexOf(tagsKey[column.dataIndex]);
          if (hasTag != -1) {
            state.value = true;
          } else {
            state.value = false;
          }
          return;
        }
        const regString = `(${stylesKey[column.dataIndex]}:)([\\s\\S]*?)(\\;)`;
        const styleReg = new RegExp(regString, "ig");

        const values = compValue.match(styleReg);
        if (!values) {
          state.value = undefined;
          return;
        }
        let value = values[0];
        value = value.replace(styleReg, "$2");
        state.value = value;
        return;
      }
      const command = editor.commands.get(column?.dataIndex);
      if (command) {
        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 StrokeStyle = css`
  input {
    height: 28px;
  }
`;

const AlignCompWapper = css`
  display: flex;
  background-color: #303030;
  .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;
  background-color: #303030;
  & > 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;
  .ant-input-number-affix-wrapper,
  .ant-select {
    background-color: #303030;
  }

  border-radius: 2px;
  &:last-child {
    margin-right: 0;
  }
  &.disabled {
    cursor: not-allowed;
  }
`;
