<template>
  <div
    v-if="isDisplay"
    class="c-dynamic-item"
  >
    <span class="c-dynamic-item__name">{{ attrName }}</span>
    <el-input-number
      v-if="isNumber"
      v-model="node[attrKey]"
      class="c-dynamic-item__value number"
      size="mini"
      controls-position="right"
      :min="min"
      :max="max"
      :step="step"
      step-strictly
      @change="onChange"
    />
    <el-input
      v-if="isText"
      v-model.trim="node[attrKey]"
      class="c-dynamic-item__value"
      type="text"
      size="mini"
      placeholder="请填写内容"
      clearable
    />
    <el-input
      v-if="isTextArea"
      v-model="inputValue"
      class="c-dynamic-item__value"
      type="textarea"
      size="mini"
      placeholder="请填写内容"
      :rows="5"
      @keydown.enter.native="onKeyEnter($event)"
      @change="onTextAreaChange"
    />
    <el-select
      v-if="isSelect"
      v-model="node[attrKey]"
      class="c-dynamic-item__value"
      size="mini"
    >
      <el-option
        v-for="item in selectOptions"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      />
    </el-select>
    <el-color-picker
      v-if="isColor"
      v-model="node[attrKey]"
      size="mini"
      show-alpha
      @change="onChangeColor"
    />
    <el-switch
      v-if="isBoolean"
      v-model="node[attrKey]"
      class="c-dynamic-item__value"
      :active-value="active"
      :inactive-value="inactive"
      active-color="#13ce66"
      inactive-color="#ff4949"
      size="mini"
      @change="onChange"
    />
    <div
      v-if="isSoloData"
      class="c-dynamic-item__value solo el-input el-input--mini"
      :class="{ 'el-input--suffix': attrValue.length }"
    >
      <input
        class="el-input__inner"
        :value="attrValue[0] && attrValue[0].name"
        placeholder="请选择"
        readonly
        @click="onChoose"
      >
      <span
        v-if="attrValue"
        class="el-input__suffix"
      >
        <span class="el-input__suffix-inner">
          <i
            class="el-input__icon el-icon-circle-close el-input__clear"
            @mousedown.prevent
            @click="onClearAssets"
          />
        </span>
      </span>
    </div>
    <el-button
      v-if="isListData"
      type="primary"
      size="mini"
      @click="onChoose"
    >
      设置
    </el-button>
    <div
      v-if="isFit"
      class="l-flex__auto c-fit-grid"
    >
      <el-button
        v-for="(strat, index) in strats"
        :key="index"
        class="c-fit-grid__item"
        type="primary"
        size="mini"
        @click="onFit(strat)"
      >
        {{ strat.label }}
      </el-button>
    </div>
  </div>
</template>

<script>
export default {
  name: 'DynamicItem',
  props: {
    root: {
      type: Object,
      default: null
    },
    node: {
      type: Object,
      default: null
    },
    attr: {
      type: Object,
      default: null
    }
  },
  data () {
    return {
      inputValue: ''
    }
  },
  computed: {
    attrKey () {
      return this.attr?.key
    },
    attrType () {
      return this.attr?.type
    },
    attrName () {
      return this.attr?.label
    },
    attrOptions () {
      return this.attr?.options || {}
    },
    attrValue () {
      return this.node[this.attrKey]
    },
    isDisplay () {
      const { display } = this.attrOptions
      return display ? display.call(this.node, this.root) : true
    },
    isNumber () {
      return this.attrType === 'number'
    },
    min () {
      return this.isNumber && this.attr.options?.min || 0
    },
    max () {
      const max = this.isNumber && this.attr.options?.max
      if (max) {
        switch (max) {
          case 'width':
            return this.root.width
          case 'height':
            return this.root.height
          default:
            return max
        }
      }
      return Infinity
    },
    step () {
      return this.isNumber && this.attr.options?.step || 1
    },
    isText () {
      return this.attrType === 'text'
    },
    isTextArea () {
      return this.attrType === 'textarea'
    },
    isSelect () {
      return this.attrType === 'select'
    },
    selectOptions () {
      return this.attrOptions.options || []
    },
    isColor () {
      return this.attrType === 'color'
    },
    isBoolean () {
      return this.attrType === 'boolean'
    },
    active () {
      return this.attrOptions.active ?? true
    },
    inactive () {
      return this.attrOptions.inactive ?? false
    },
    isData () {
      return this.attrType === 'data'
    },
    isSoloData () {
      return this.isData && this.attrOptions.solo === true
    },
    isListData () {
      return this.isData && !this.attrOptions.solo
    },
    isFit () {
      return this.attrType === 'fit'
    },
    strats () {
      return this.attrOptions.strats ?? []
    }
  },
  watch: {
    node: {
      handler () {
        if (this.$valWatch) {
          this.$valWatch()
          this.$valWatch = null
        }
        if (this.isTextArea) {
          this.$valWatch = this.$watch(`node.${[this.attrKey]}`, this.onValChanged)
          this.inputValue = this.node[this.attrKey]
        }
      },
      immediate: true
    }
  },
  methods: {
    onChange () {
      this.attrOptions.callback?.call(this.node, this.root)
    },
    onChangeColor (color) {
      if (!color) {
        this.node[this.attrKey] = 'rgba(0, 0, 0, 0)'
      }
      this.onChange()
    },
    onClearAssets () {
      this.node[this.attrKey] = []
      this.onChange()
    },
    onChoose () {
      this.$emit('choose', this.attr)
    },
    onFit (strat) {
      strat.callback?.(this.node, this.root)
    },
    onKeyEnter (e) {
      if (this.isTextArea && this.attrOptions.singleLine) {
        e.stopPropagation()
        e.preventDefault()
        this.onTextAreaChange()
      }
    },
    onTextAreaChange () {
      this.node[this.attrKey] = this.inputValue
      this.onChange()
    },
    onValChanged () {
      this.inputValue = this.node[this.attrKey]
    }
  }
}
</script>

<style lang="scss" scoped>
.c-dynamic-item {
  display: flex;

  & + & {
    margin-top: $spacing;
  }

  &__name {
    flex: none;
    width: 60px;
    color: #bfcbd9;
    font-size: 12px;
  }

  &__value {
    flex: 0 1 auto;
    align-self: center;
    min-width: 0;

    ::v-deep .el-input__inner,
    ::v-deep .el-textarea__inner {
      color: #a8e3ff;
      border: 1px solid #3f5673;
      background-color: #263445;
    }

    &.number {
      ::v-deep span {
        color: #a8e3ff;
        border-color: #3f5673;
        background-color: #5e6b82;
      }

      ::v-deep .el-input__inner {
        padding-left: 6px;
        padding-right: 34px;
      }
    }

    &.solo {
      cursor: pointer;

      .el-input__inner {
        cursor: pointer;
      }

      .el-input__suffix {
        display: none;
      }

      &:hover {
        .el-input__suffix {
          display: block;
        }
      }
    }
  }
}

.c-fit-grid {
  display: grid;
  grid-template-columns: 1fr;
  grid-gap: 8px;

  &__item {
    margin: 0;
  }
}
</style>
