<template>
  <div :class="parentWrapperClass" v-if="vshow">
    <div class="select">
      <slot name="before:label"></slot>
      <slot name="label">
        <blabel :label="label" :disabled="vdisabled"></blabel>
      </slot>
      <slot name="after:label"></slot>
      <v-select
        :disabled="vdisabled"
        :label="optionValue"
        :value="mainSelect2Model"
        @input="updateValue"
        placeholder="Select"
        :options="localOptions"
        v-bind="props"
        :name="id"
        :id="id"
        ref="vue-select"
        v-on="vueSelectListeners"
        :selectable="selectable"
        @option:selected="(obj)=>{$emit('selected:option', obj);$emit('change', internalValue)}"
        @option:selecting="(obj) => $emit('option:selecting', obj)"
        @option:deselected="() => $emit('change', internalValue)"
        @search:blur="() => $emit('search:blur', internalValue)"
        append-to-body
        :calculate-position="withPopper"
      ></v-select>
      <slot name="after:input"></slot>
      <span class="select-highlight"></span>
      <span class="bar"></span>
      <slot name="after:input:bar"></slot>
    </div>
  </div>
</template>

<script>
 /* eslint-disable */ 
import vSelect from "vue-select";
import Blabel from "./Blabel.vue";
import { createPopper } from "@popperjs/core";
import {
  isUndef,
  isPlainArray,
  isPlainObject,
  isString
} from "@credenceanalytics/utilities";

var sortArray = (label) => (arr) => {
  return arr
  .sort((a, b) => {
    return (a[label] !== b[label]) ? (a[label] < b[label]) ? -1 : 1 : 0
  });
};

export default {
  props: {
    value: null,
    id: {
      type: String,
    },
    selectable: {
      type: Function,
      default: function() {
        return () => true
      }
    },
    vueSelectListeners: {
      type: Object,
      default: function () {
        return {};
      },
    },
    parentWrapperClass: {
      type: String,
      default: "form-group",
    },
    label: {
      type: String,
      default: "",
    },
    options: {
      type: Array,
      default: function () {
        return [];
      },
    },
    disabled: {
      type: [String, Boolean, Object],
      default: false,
    },
    hide: {
      type: [String, Boolean, Object],
      default: true,
    },
    optionValue: {
      type: String,
      default: "DESCR",
    },
    optionCode: {
      type: String,
      default: "CODE",
    },
  },
  data() {
    return {
      internalValue: [],
      localOptions: [],
    };
  },
  components: {
    vSelect,
    Blabel,
  },

  watch: {
    value: {
      handler(val) {
        this.setInternalValueFromOptions(val);
      },
      immediate: true,
    },
    options: {
      handler(array) {
        this.localOptions = this.sortArray(
          isPlainArray(array) ? JSON.parse(JSON.stringify(array)) : []
        );
      },
      immediate: true,
    },
  },

  methods: {
    sortArray(array) {
      const sortWithLabel = sortArray(this.optionValue);
      return sortWithLabel([...array]);
    },
    withPopper(dropdownList, component, { width }) {
      dropdownList.style.width = width;
      dropdownList.classList.remove("form-select-box");
      dropdownList.classList.add("form-select-box");
      const popper = createPopper(component.$refs.toggle, dropdownList, {
        placement: "bottom",
        modifiers: [
          {
            name: "offset",
            options: {
              offset: [0, -1],
            },
          },
          {
            name: "toggleClass",
            enabled: true,
            phase: "write",
            fn({ state }) {
              component.$el.classList.toggle(
                "drop-up",
                state.placement === "top"
              );
            },
          },
        ],
      });

      return () => popper.destroy();
    },
    setInternalValueFromOptions(value) {
      if (this.isMultiSelect === true) {
        value = value == null || value === "" ? null : value.split(",");
        this.internalValue = value;
      } else {
        this.internalValue = value;
      }
    },

    updateValue(value) {
      if (value !== null) {
        if (isPlainArray(value)) {
          value = value.join(",");
        }
      }

      this.$emit("input", value == null ? "" : value);
    },

    defaultReducer() {
      const vm = this;
      return function a(obj) {
        if(isString(obj)) return obj;
        obj[vm.optionCode] = "" + obj[vm.optionCode];
        if (vm.isTaggable === true) return obj;
        return obj[vm.optionCode];
      };
    },
  },
  computed: {
    props() {
      return Object.assign(
        {},
        { reduce: this.defaultReducer(), taggable: false },
        this.$attrs
      );
    },
    isMultiSelect() {
      return this.props.multiple === true;
    },
    isTaggable() {
      return this.props.taggable === true;
    },
    mainSelect2Model() {
      let value = this.internalValue;

      if (value) {
        return [].concat(("" + value).split(","));
      }

      return [];
    },

    vshow() {
      return isUndef(this.hide)
        ? true
        : isPlainObject(this.hide)
        ? this.hide[this.id]
        : this.hide;
    },
    vdisabled() {
      return isUndef(this.disabled)
        ? false
        : isPlainObject(this.disabled)
        ? this.disabled[this.id]
        : this.disabled;
    },
  },
};
</script>