<template>
  <div :class="[prefixCls + '-picker']">
    <div :class="[prefixCls + '-picker-wrapper']">
      <div :class="[prefixCls + '-picker-panel']">
        <Saturation
          ref="saturation"
          :value="saturationColors"
          @input="colorChange($event, 'input')"
          @change="colorChange"
        ></Saturation>
      </div>
      <div :class="[prefixCls + '-picker-hue-slider']">
        <Hue :value="saturationColors" @change="colorChange" @input="colorChange($event, 'input')"></Hue>
      </div>
      <div v-if="alpha" :class="[prefixCls + '-picker-alpha-slider']">
        <Alpha :value="saturationColors" @change="colorChange" @input="colorChange($event, 'input')"></Alpha>
      </div>
      <div :class="[prefixCls + '-picker-color-active']" :style="`background-color: ${formatColor};`"></div>
    </div>
    <div :class="[prefixCls + '-confirm']">
      <div class="th-tabs">
        <div :class="['th-tab', 'inline', {active: mode === colorMode}]" v-for="(value, mode) in displayColors" :key="mode" @click="changeColorMode(mode)">{{ mode }}</div>
      </div>
      <i-input class="color-input" :modelValue="saturationColors[colorMode==='RGB'?'rgba':'hsv'][item.toLowerCase()]" size="small"  v-for="item in displayColors[colorMode]" :key="item" @on-change="colorChildChange($event, item)">
        <template #prepend>
          <span>{{ item }}</span>
        </template>
      </i-input>
      <i-input :modelValue="formatColor" size="small"  @on-enter="handleEditColor" @on-blur="handleEditColor"></i-input>
    </div>
  </div>
</template>
<script>
import { getCurrentInstance } from "vue";
import tinycolor from "tinycolor2";
import Saturation from "./saturation.vue";
import Hue from "./hue.vue";
import Alpha from "./alpha.vue";
import util from '../../libs/util';
import Prefixes from "./prefixMixin";
import { changeColor, toRGBAString } from "./utils";

export default {
  name: "ColorPanel",
  components: { Saturation, Hue, Alpha },
  mixins: [Prefixes],
  inject: {
    FormInstance: {
      default: "",
    },
    FormItemInstance: {
      default: null,
    },
  },
  provide() {
    return {
      ColorPanelInstance: this
    };
  },
  emits: [
    "on-input",
    "on-change",
    "update:modelValue",
  ],
  props: {
    modelValue: {
      type: String,
      default: undefined,
    },
    alpha: {
      type: Boolean,
      default: true,
    },
    format: {
      type: String,
      validator(value) {
        return util.oneOf(value, ["hsl", "hsv", "hex", "rgb"]);
      },
      default: undefined,
    },
    disabled: {
      type: Boolean,
      default: false,
    }
  },
  created() {
    const instance = getCurrentInstance();
    this.globalConfig = instance.appContext.config.globalProperties.$VIEWUI;
  },
  data() {
    return {
      globalConfig: {},
      val: changeColor(this.modelValue || ""),
      currentValue: this.modelValue || "",
      dragging: false,
      colorMode: 'RGB',   // RGB or HSV
      displayColors: {
        RGB: ['R', 'G', 'B', 'A'],
        HSV: ['H', 'S', 'V', 'A']
      }
    };
  },
  computed: {
    arrowClasses() {
      return [
        `${this.inputPrefixCls}-icon`,
        `${this.inputPrefixCls}-icon-normal`,
      ];
    },
    saturationColors: {
      get() {
        return this.val;
      },
      set(newVal) {
        this.val = newVal;
      },
    },
    formatColor() {
      const { format, saturationColors } = this;

      if (format) {
        if (format === "hsl") {
          return tinycolor(saturationColors.hsl).toHslString();
        }

        if (format === "hsv") {
          return tinycolor(saturationColors.hsv).toHsvString();
        }

        if (format === "hex") {
          return saturationColors.hex;
        }

        if (format === "rgb") {
          return toRGBAString(saturationColors.rgba);
        }
      } else if (this.alpha) {
        return toRGBAString(saturationColors.rgba);
      }

      return saturationColors.hex;
    },
    confirmColorClasses() {
      return [
        `${this.prefixCls}-confirm-color`,`${this.prefixCls}-confirm-color-editable`
      ];
    },
    itemDisabled() {
      let state = this.disabled;
      if (!state && this.FormInstance) state = this.FormInstance.disabled;
      return state ? true : null; // todo <a> can not set disabled: false
    },
  },
  watch: {
    modelValue(newVal) {
      this.val = changeColor(newVal || "");
    }
  },
  methods: {
    changeColorMode(mode) {
      this.colorMode = mode
    },
    colorChildChange(event, childLetter) {
      let value = Number(event.target.value)
      let newVal = ''
      if (this.colorMode === 'RGB') {
        this.saturationColors.rgba[childLetter.toLowerCase()] = value
        newVal = toRGBAString(this.saturationColors.rgba);
      } else {
        this.saturationColors.hsv[childLetter.toLowerCase()] = value
        newVal = tinycolor(this.saturationColors.hsv).toHsvString()
      }
      this.colorChange(newVal)
    },
    handleFormItemChange(type, data) {
      if (this.FormItemInstance) {
        if (type === "blur") this.FormItemInstance.formBlur(data);
        else if (type === "change") this.FormItemInstance.formChange(data);
      }
    },
    setDragging(value) {
      this.dragging = value;
    },
    colorChange(data, mode = 'change') {
      this.oldHue = this.saturationColors.hsl.h;
      this.saturationColors = changeColor(data, this.oldHue);
      this.currentValue = this.formatColor;
      this.$emit("update:modelValue", this.formatColor);
      this.$emit(`on-${mode}`, this.formatColor);
      this.handleFormItemChange("change", this.formatColor);
    },
    handleEditColor(event) {
      const value = event.target.value;
      this.colorChange(value)
    },
    handleOnDragging(value) {
      this.setDragging(value);
    },
  },
};
</script>
