<script lang="tsx">
import {
  defineComponent, type PropType, ref, type Ref, onMounted, nextTick,
} from 'vue'
import useEndlessScrollApi, { type paramsSerializationOptions } from '../../composables/use-endless-scroll-api'
import useScrollPagination from '../../composables/use-scroll-pagination'
import useClickOutside from '../../composables/use-click-outside'
import type ApiInterface from '../../types/api-interface'
import LineLoader from '../line-loader/ARKLineLoader.vue'

/**
 * Данное отображение используется для сокращения отображаемой инофрмации. Используется, когда текст - это перечисление (например, клиенты, тороговая точка, ску).<br><br>
 * При нажатии на еще, открывается список(максимальное число показываемых элементов 5, если больше, то добавляется скролл). Закрыть окно можно, повторным нажатием на еще или нажать на область вне окна.
 * <ul>
 * <li><a href="https://www.figma.com/file/Q4Z4CnFx4i0qhD5fbgnPpf/%F0%9F%92%BB-%D0%94%D0%B8%D0%B7%D0%B0%D0%B9%D0%BD-%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0-ARK-SPACE?type=design&node-id=5255-73495&mode=design&t=5LOBA5zTzEZr6q7a-4" target="_blank">дизайн</a></li>
 * </ul>
 */
export default defineComponent({
  props: {
    api: {
      type: Object as PropType<ApiInterface>,
    },
    /**
     * Количество всех элементов в списке
     */
    count: {
      type: Number,
      default: 0,
    },
    /**
     * Текст для кнопки открытия/закрытия выпадашки
     */
    dropdownText: {
      type: String,
      default: 'Еще',
    },
    /**
     * Эндпоинд по которому тянется список элементов
     */
    endpoint: {
      type: String,
      required: true,
    },
    /**
     * Функция, которой можно привести массив файлов к нужному формату
     */
    itemConverter: {
      type: Function as PropType<(item: any) => { id: string, name: string }>,
    },
    /**
     * Тип пагинации скроллом или постраничная
     */
    paginationType: {
      type: String,
    },
    /**
     * Дефолтные квери параметры
     */
    params: {
      type: Object as PropType<{ [code: string] : string|string[] }>,
      default: () => ({}),
    },
    /**
     * Количество элементов запрашиваемое в запросе к бэку на одной странице пагинации
     */
    perPage: {
      type: Number,
      default: 10,
    },
    /**
     * Ключ пагинации текущей страницы
     */
    requestPageKey: {
      type: String,
    },
    /**
     * Ключ пагинации куда указывать количество элементов запрашиваемое в запросе к бэку на одной странице пагинации
     */
    requestPerPageKey: {
      type: String,
    },
    /**
     * Ключ массива из которого брать элементы списка
     */
    responseItemsKey: {
      type: String,
    },
    /**
     * Ключ количества всех элементов
     */
    responseTotalKey: {
      type: String,
    },
    /**
     * Тип сериализации квери параметров: 'default' | 'custom' | 'comma'
     */
    paramsSerialization: {
      type: String as PropType<paramsSerializationOptions>,
      default: 'default',
    },
  },
  setup(props) {
    const isOpened = ref(false)
    const triggerDown = ref(null) as unknown as Ref<HTMLElement>
    const triggerUp = ref(null) as unknown as Ref<HTMLElement>
    const canBeLoaded = ref(false)
    const root = ref(null) as unknown as Ref<HTMLElement>
    const select = ref(null) as unknown as Ref<HTMLElement>
    const isLoadingPrev = ref(false)
    const isLoadingNext = ref(false)

    const {
      items, loadNext, loadPrev, initialLoad, reload, offset, clear,
    } = useEndlessScrollApi<{ id: string, name: string }>({
      endpoint: props.endpoint,
      params: ref(props.params),
      itemConverter: props.itemConverter,
      paginationType: props.paginationType,
      requestPageKey: props.requestPageKey,
      requestPerPageKey: props.requestPerPageKey,
      api: props.api,
      paramsSerialization: props.paramsSerialization,
      autoReload: false,
      requestSize: ref(props.perPage),
    })

    useClickOutside(select, () => { isOpened.value = false })

    useScrollPagination({
      callback: async () => {
        if (canBeLoaded.value) {
          const lastChild = root.value.children[root.value.children.length - 2] as HTMLElement
          isLoadingNext.value = true
          const flag = await loadNext()
          isLoadingNext.value = false
          if (flag) root.value.scrollTo({ top: lastChild.offsetTop + lastChild.clientHeight - root.value.clientHeight })
        }
      },
      trigger: triggerDown,
      root,
    })

    useScrollPagination({
      callback: async () => {
        if (canBeLoaded.value) {
          const firstChild = root.value.children[1] as HTMLElement
          isLoadingPrev.value = true
          const flag = await loadPrev()
          isLoadingPrev.value = false
          if (flag) root.value.scrollTo({ top: firstChild.offsetTop })
        }
      },
      trigger: triggerUp,
      root,
    })

    const toggleOpened = () => {
      isOpened.value = !isOpened.value

      nextTick(async () => {
        if (items.value.length === 0) await initialLoad()
        canBeLoaded.value = isOpened.value
      })
    }

    return () => (
      <div>
        <div class={{ 'is-opened': isOpened.value, 'ark-ui-dropdown-list': true }}
          ref={select}
        >
          <div class="ark-ui-dropdown-list-text" onClick={toggleOpened}>
            {props.dropdownText} {props.count > 0 ? props.count : ''}
          </div>
          <div class="ark-ui-dropdown-list-dropdown" style={isOpened.value ? 'display: block;' : 'display: none;'}>
            <div class="ark-ui-dropdown-list-items-list-wrapper">
              { isLoadingPrev.value && <LineLoader/> }
              <div class="ark-ui-dropdown-list-items-list" ref={root}>
                <div class="ark-ui-pagination-trigger ark-ui-pagination-trigger-up" ref={triggerUp}/>
                { items.value.map((item) => (
                  <div key={item.id} class='ark-ui-dropdown-list-item'>
                    <span>{ item.name }</span>
                  </div>
                )) }
                <div class="ark-ui-pagination-trigger ark-ui-pagination-trigger-down" ref={triggerDown}/>
              </div>
              { isLoadingNext.value && <LineLoader/> }
            </div>
          </div>
        </div>
      </div>
    )
  },
})
</script>

<style lang="scss" scoped>
@import '../../styles/variables.scss';

.ark-ui-dropdown-list {
  position: relative;
  &.is-opened {
    .ark-ui-dropdown-list-dropdown {
      background: white;
      display: block;
      position: absolute;
      width: 200px;
      z-index: $dropdown;
    }
  }
}

.ark-ui-dropdown-list-text {
  color: $blue;
  cursor: pointer;
  font-size: 14px;
  line-height: 16px;
}

.ark-ui-dropdown-list-dropdown {
  box-shadow: 0 8px 16px rgba(75, 77, 89, 0.08) !important;
  display: none;
}

.ark-ui-dropdown-list-items-list {
  position: relative;
  background-color: white;
  overflow-y: auto;
  border-radius: 4px;
  border: 1px solid #fff;
  max-height: 200px;
  &::-webkit-scrollbar {
    width: 4px;
    height: 4px;
  }

  &::-webkit-scrollbar-thumb {
    background-color: $gray-400;
    border-radius: 6px;
    width: 4px;
  }

  &::-webkit-scrollbar-track {
    background-color: #F6F6FA;
    border-radius: 6px;
  }
}

.ark-ui-dropdown-list-item {
  font-size: 14px;
  line-height: 16px;
  padding: 12px 16px 12px 16px;
}

.ark-ui-pagination-trigger {
  height: 2px;
  min-height: 2px;
}
</style>
