<template>
  <div ref="focusElement">
    <FormWrapper
      class="select-component select-wrapper"
      v-bind="props.formProps"
      :active="active"
    >
      <div
        class="input-wrapper"
        tabindex="0"
        @keypress.enter="setActive(true)"
        @keypress.esc="setActive(false)"
        @click="wrapperClickHandler"
      >
        <input
          :placeholder="props.selectedItem ? '' : props.placeholder"
          class="h600"
          :class="{ disabled: props.disabled, active }"
          v-model="keyword"
          type="text"
          tabindex="-1"
          :readonly="!props.search"
          :disabled="!props.search"
          @input="changeHandler"
        />
      </div>

      <slot name="placeholder" />
      <div class="icon arrow" :class="{ active }">
        <SpIcon name="sp-dropdown" />
      </div>

      <div
        class="selected-item"
        v-if="!(props.search && active) && props.selectedItem"
      >
        <img
          class="mr-4"
          v-if="props.selectedItem.imgUrl"
          :src="props.selectedItem.imgUrl"
        />
        <p class="h600">{{ props.selectedItem.title }}</p>
      </div>

      <AccordionSheet
        :active="active"
        @close="setActive(false)"
        :stretch="props.search"
      >
        <slot />
      </AccordionSheet>
    </FormWrapper>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, PropType, watch } from "vue";
import FormMixin from "@/mixins/FormMixin";
import { useFocusOut } from "@/hooks";

export default defineComponent({
  mixins: [FormMixin],
  props: {
    selectedItem: {
      type: Object as PropType<{ title: string; imgUrl: string }>,
      default: () => {},
    },
    closeOnChange: {
      type: Boolean,
      default: true,
    },
  },
  setup(props: any, { emit }) {
    const keyword = ref<string>("");

    const { focusOutElement, active, focusElement } = useFocusOut();
    focusOutElement.value = ".input-container";

    const setActive = (status: boolean): void => {
      if (props.disabled) {
        return;
      }

      if (!status) {
        emit("close");
        keyword.value = "";
      } else {
        emit("open");
      }
      active.value = status;
    };

    const wrapperClickHandler = (): void => {
      if (active.value && !props.search) {
        setActive(false);
      } else {
        setActive(true);
      }
    };

    const changeHandler = (event: any): void => {
      emit("input", event.target.value);
    };

    watch(
      () => props.selectedItem,
      (): void => {
        if (props.closeOnChange) {
          setActive(false);
        }
      }
    );

    return {
      active,
      focusElement,
      setActive,
      wrapperClickHandler,
      changeHandler,
      props,
      keyword,
    };
  },
});
</script>

<style lang="scss">
.select-wrapper {
  --list-item-margin: -16px;
  --list-item-padding: 16px;
  --list-item-extra-padding: 16px;

  .input-wrapper {
    outline: none;

    input {
      width: 100%;
      height: var(--height);
      background: var(--background);
      padding: 0 var(--form-side-padding);
      border: 1px solid var(--border-color);
      border-radius: var(--form-border-radius);
      box-shadow: var(--box-shadow);
      transition: box-shadow 0.3s ease, border 0.3s ease;
      cursor: pointer;

      &:focus {
        --border-color: var(--form-border-color-focus);
        box-shadow: 0 4px 10px var(--blue-10);
        cursor: initial;
      }

      &.disabled {
        cursor: default;
      }

      &.active {
        --border-color: var(--form-border-color-active);
        box-shadow: 0 4px 10px var(--blue-10);
      }

      @include screen-sm-below() {
        pointer-events: none;
      }
    }
  }

  .icon.arrow {
    position: absolute;
    top: 50%;
    right: 16px;
    transform: translateY(-50%);
    pointer-events: none;
    transition: transform 0.3s ease;

    path {
      transition: fill 0.3s ease;
    }

    &.active {
      transform: translateY(-50%) rotate(-180deg);

      path {
        fill: var(--blue);
      }
    }
  }

  .selected-item {
    position: absolute;
    top: 50%;
    left: 0;
    transform: translateY(-50%);
    padding-left: var(--form-side-padding);
    padding-right: calc(var(--form-side-padding) * 2);
    pointer-events: none;
    width: 100%;
    display: flex;
    align-items: center;

    .value {
      color: var(--text-color);
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
      width: 100%;
      flex-grow: 1;
    }

    img {
      width: 24px;
      margin-right: 8px;
    }
  }

  .accordion-sheet {
    --scroll-max-height: 270px;
    --scroll-min-height: 72px;
  }

  ul.main {
    & > li {
      .item {
        display: flex;
        align-items: center;
        cursor: pointer;
        padding: var(--list-item-padding);
        margin: 0 var(--list-item-margin);
      }

      &:first-child {
        .item {
          padding-top: var(--list-item-extra-padding);
        }
      }

      &:last-child {
        .item {
          padding-bottom: var(--list-item-extra-padding);
        }
      }

      &:hover:not(.search) {
        .item {
          background-color: var(--fill-quaternary);
        }
      }

      &.selected {
        color: var(--blue);
      }

      &.search {
        padding-top: 2px !important;
        padding-bottom: 8px !important;
        background: var(--background-primary);
        position: sticky;
        top: 0;
        z-index: 2;

        .space-input {
          width: 100%;
        }

        svg {
          display: block;
          font-size: 0;
        }

        @include screen-sm() {
          display: none !important;
          visibility: hidden !important;
        }
      }

      .icon {
        width: 20px;
        height: 20px;

        @include screen-lg() {
          width: 24px;
          height: 24px;
        }
      }
    }
  }

  @include screen-sm() {
    --list-item-margin: 0px;
    --list-item-padding: 12px 16px;
    --list-item-extra-padding: 16px;
  }

  @include screen-lg() {
    --list-item-padding: 16px 24px;
    --list-item-extra-padding: 23px;

    .accordion-sheet {
      --scroll-max-height: 320px;
    }
  }
}
</style>
