<template>
  <div>
    <VBtnToggle
      ref="buttonGroup"
      class="dynamic-button-group"
      :class="{ grow: grow }"
      v-bind="$attrs"
      :max="max"
      :multiple="multiple"
    >
      <!-- Slot support -->
      <template v-if="hasSlot.default">
        <slot />
      </template>

      <!-- Default -->
      <template v-else>
        <VBtn
          v-for="(b, index) in mapButtons"
          :key="index"
          v-bind="b.buttonProps"
          :inputValue="b.value"
          :color="b.buttonColor"
          :class="{ grow: grow }"
          @click="emitValue(b.value)"
        >
          <!-- add icon if on left side -->
          <VIcon v-if="b.hasLeftIcon" v-bind="b.iconProps" left>{{ b.icon }}</VIcon>
          <!-- add only icon -->
          <template v-if="b.isIconOnly">
            <VIcon v-bind="b.iconProps">{{ b.icon }}</VIcon>
          </template>
          <!-- button text -->
          <template v-else>
            {{ b.text }}
          </template>
          <!-- add icon if on right side -->
          <VIcon v-if="b.hasRightIcon" v-bind="b.iconProps" right>{{ b.icon }}</VIcon>
        </VBtn>
      </template>
    </VBtnToggle>
    <slot name="error" :hasError="hasError" :errors="validationTarget" />
  </div>
</template>

<script>
/* eslint-disable vue/no-deprecated-props-default-this */
import VInput from 'vuetify/lib/components/VInput'
import { computed, defineComponent } from '@vue/composition-api'
import { vuetifyColorMapper } from '../../utils'

/** 
|--------------------------------------------------
|	buttons property example model:
|--------------------------------------------------
check all props for this component here: https://vuetifyjs.com/en/api/v-btn-toggle/#props

// buttons definition
buttons: {
  // Text to show in button
  text: [String, Number]
  // Value to determine whats selected
  value: any
  // To highlight if this button was selected last time
  isSelectedBefore: Boolean
  // v-btn props
  buttonProps: {
    ...all v-btn props can be applied here
  }
  // font awesome icon e.g. fa-users
  icon: String
  // v-icon props
  iconProps: {
    ...all v-icon props can be applied here
  }
}
**/

/**
 * Pitcher Dynamic Button Group component
 * @inherits v-btn-toggle
 */

export default defineComponent({
  name: 'PDynamicButtonGroup',
  extends: VInput,
  inheritAttrs: false,
  props: {
    value: {
      type: [String, Number, Boolean, Array],
      default: '',
    },
    buttons: {
      type: Array,
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    max: {
      type: [String, Number],
      default: undefined,
    },
    mandatory: {
      type: Boolean,
      default() {
        return this.multiple ? false : true
      },
    },
    grow: {
      type: Boolean,
      default: false,
    },
  },
  emits: ['input', 'button-clicked'],
  setup(props, ctx) {
    const hasSlot = computed(() => ({
      default: !!ctx.slots.default,
    }))

    const isSelected = (button) => {
      if (props.multiple) {
        return props.value?.includes(button.value)
      }

      return props.value === button.value
    }

    const mapButtons = computed(() => {
      if (!props.buttons || !props.buttons.length === 0) {
        return []
      }

      return props.buttons.map((b) => {
        // if button has no text & has icon only
        if ((!b.text || b.text === '') && b.icon) {
          b.isIconOnly = true

          // set left/right props to false
          if (b.iconProps) {
            b.iconProps.left = false
            b.iconProps.right = false
          }
        }

        // if button has icon & text but no props, by default its left icon
        if (b.text && b.icon && !b.iconProps) {
          b.hasLeftIcon = true
        }

        // if button has icon & text, also iconProps.right its right icon
        if (b.text && b.icon && b.iconProps && b.iconProps.right) {
          b.hasRightIcon = true
        }

        b.buttonProps = b.buttonProps ?? {}

        // add styles/classes if exist, create otherwise
        b.buttonProps.class = b.buttonProps.class ? b.buttonProps.class : {}
        b.buttonProps.style = b.buttonProps.style ? b.buttonProps.style : {}

        if (!isSelected(b)) {
          // not selected, remove colors
          b.buttonColor = undefined
          b.buttonProps.style.color = undefined
        } else {
          // button is selected, set colors
          b.buttonProps.style.color = b.buttonProps.color ? '#fff' : undefined
          b.buttonColor = b.buttonProps.color
        }

        // if button has isSelectedBefore: true & not selected
        if (b.isSelectedBefore && !isSelected(b)) {
          const vuetifyColor = b.buttonProps.color || ctx.attrs.color
          // set shadow
          const color = vuetifyColorMapper(vuetifyColor, ctx.root.$vuetify)

          b.buttonProps.style.boxShadow = `0px 5px 8px -5px ${color}`
        } else {
          // no selected before, set none
          b.buttonProps.style.boxShadow = 'none'
        }

        return b
      })
    })

    const emitValue = (buttonValue) => {
      // single select logic
      if (!props.multiple) {
        let value = buttonValue

        if (!props.mandatory) {
          value = props.value === buttonValue ? undefined : buttonValue
        }

        ctx.emit('input', value)

        return
      }

      // Multiple logic
      let value = props.value.constructor.name === 'Array' ? props.value : []

      // push button into the value
      // if button is not selected
      // props.max is not defined
      // OR max is defined and current selection count is less then max
      if (!value.includes(buttonValue) && (!props.max || (props.max && value.length < Number(props.max)))) {
        value = value.concat(buttonValue)
      } else if (value.includes(buttonValue) && !props.mandatory) {
        // Remove value, button is selected & it is not mandatory to select
        value = value.filter((v) => v !== buttonValue)
      }

      ctx.emit('input', value)

      return
    }

    return { mapButtons, hasSlot, emitValue }
  },
})
</script>

<style lang="scss" scoped>
.dynamic-button-group {
  &.grow {
    display: flex;
    width: 100;
  }

  i {
    color: inherit !important;
  }

  .grow {
    flex: 1;
    flex-wrap: nowrap;
  }
}
</style>
