<template>
  <view
    @click="modalClick"
    :class="[value ? 'show' : '', type === 'bottom' ? 'bottom-modal' : '', className]"
    :style="style"
    class="cu-modal"
  >
    <!-- 图片弹出窗口 -->
    <view v-if="type === 'img'" class="cu-dialog">
      <view
        :style="{ backgroundImage: 'url(' + img + ')', height: '200px' }"
        class="bg-img"
        style="position: relative;"
      >
        <view @tap="close" class="action text-white" style="position: absolute;top: 10px;right: 10px;">
          <l-icon type="close" />
        </view>
      </view>
      <view class="cu-bar bg-white"><view @tap="close" class="action margin-0 flex-sub solid-left">关闭</view></view>
    </view>

    <!-- 单选弹出窗口 -->
    <view v-else-if="type === 'radio'" @tap.stop class="cu-dialog">
      <radio-group @change="radioChange" class="block">
        <view class="cu-list menu text-left">
          <view v-for="(item, index) of range" :key="index" class="cu-item">
            <label class="flex justify-between align-center flex-sub">
              <view class="flex-sub">{{ objectMode ? item[textField] : item }}</view>
              <radio
                :checked="radioIndex === index ? true : false"
                :value="objectMode ? item[valueField] : item"
                :class="radioIndex === index ? 'checked' : ''"
                class="round"
              ></radio>
            </label>
          </view>
        </view>
      </radio-group>
    </view>

    <!-- 多选弹出窗口 -->
    <view v-else-if="type === 'checkbox'" @tap.stop class="cu-dialog">
      <view class="cu-bar bg-white">
        <view @tap="close(0)" class="action text-blue">取消</view>
        <view v-if="!readonly" @tap="close(1)" class="action text-green">确定</view>
      </view>
      <view class="grid col-3 padding-sm">
        <view v-for="(item, index) in range" :key="index" class="padding-xs">
          <button
            @tap="chooseCheckbox(index)"
            :class="checkboxIndex.includes(index) ? 'bg-orange' : 'line-orange'"
            class="cu-btn orange lg block"
          >
            {{ objectMode ? item[textField] : item }}
          </button>
        </view>
      </view>
    </view>

    <!-- 普通/对话/底部弹出窗口 -->
    <view v-else class="cu-dialog">
      <view :class="[type === 'bottom' ? '' : 'justify-end pading-left']" class="cu-bar bg-white">
        <!-- 普通/对话弹出窗口 -->
        <template v-if="type === 'default' || type === 'confirm'">
          <view class="content">
            <slot name="title">{{ title }}</slot>
          </view>
          <view @tap="close" class="action"><l-icon type="close" color="red" /></view>
        </template>

        <!-- 底部弹出窗口 -->
        <template v-if="type === 'bottom'">
          <slot name="action">
            <l-button @click="close" class="action padding-lr" line="red">取消</l-button>
            <view class="action padding-lr">{{ title }}</view>
          </slot>
        </template>
      </view>

      <view class="padding">
        <slot>{{ content }}</slot>
      </view>

      <!-- 对话弹出窗口的操作区 -->
      <template v-if="type === 'confirm'">
        <view class="cu-bar bg-white justify-end padding-right">
          <view class="action">
            <button @tap="close(0)" class="cu-btn line-green text-green">取消</button>
            <button @tap="close(1)" class="cu-btn bg-green margin-left">确定</button>
          </view>
        </view>
      </template>
    </view>
  </view>
</template>

<script>
export default {
  name: 'l-modal',

  props: {
    title: {},
    content: {},
    value: {},
    type: { default: 'default' },
    img: {},
    range: { default: () => [] },
    radio: {},
    checkbox: {},
    readonly: {},
    textField: { default: 'text' },
    valueField: { default: 'value' }
  },

  data() {
    return {
      radioIndex: undefined,
      checkboxIndex: []
    }
  },

  created() {
    this.init()
  },

  methods: {
    init() {
      if (this.type === 'radio') {
        this.radioIndex = this.objectMode
          ? this.range.findIndex(t => t[this.valueField] === this.radio)
          : this.range.indexOf(this.radio)
      } else if (this.type === 'checkbox' && Array.isArray(this.checkbox)) {
        this.checkboxIndex = this.checkbox.reduce(
          (a, b) =>
            a.concat(this.objectMode ? this.range.findIndex(t => t[this.valueField] === b) : this.range.indexOf(b)),
          []
        )
      }
    },

    close(arg) {
      this.$emit('input', false)
      this.$emit('close', false)

      if (typeof arg === 'number') {
        this.$emit(['cancel', 'ok'][arg])
      }

      if (this.type === 'checkbox') {
        if (arg === 0) {
          this.checkboxIndex = this.checkbox
        } else {
          const checkboxValue = this.checkboxIndex.reduce(
            (a, b) => a.concat(this.objectMode ? this.range[b][this.valueField] : this.range[b]),
            []
          )

          this.$emit('checkboxChange', checkboxValue)
          this.$emit('checkboxIndex', this.checkboxIndex)
        }
      }

      if (typeof arg === 'number') {
        this.$emit(['cancel', 'ok'][arg])
      }
    },

    modalClick() {
      if (this.type === 'radio' || this.type === 'checkbox') {
        this.close()
      }
    },

    radioChange(e) {
      if (this.readonly) {
        return
      }

      this.radioIndex = this.objectMode
        ? this.range.findIndex(t => t[this.valueField] === e.detail.value)
        : this.range.indexOf(e.detail.value)
      this.$emit(
        'radioChange',
        this.objectMode ? this.range[this.radioIndex][this.valueField] : this.range[this.radioIndex]
      )
      this.$emit('radioIndex', this.radioIndex)
    },

    chooseCheckbox(index) {
      if (this.readonly) {
        return
      }

      if (this.checkboxIndex.includes(index)) {
        this.checkboxIndex = this.checkboxIndex.filter(t => t !== index)
      } else {
        this.checkboxIndex.push(index)
      }

      const checkboxValue = this.checkboxIndex.reduce(
        (a, b) => a.concat(this.objectMode ? this.range[b][this.valueField] : this.range[b]),
        []
      )
    }
  },

  watch: {
    value(newVal) {
      if (newVal) {
        this.init()
      }
    }
  },

  computed: {
    objectMode() {
      return typeof this.range[0] === 'object'
    }
  }
}
</script>
