<template>
  <div class="search-portal">
    <div class="mask"></div>
    <div class="close"><Icon name="handle" @click="onClose" /></div>
    <div class="card">
      <div class="search">
        <div class="label" v-show="mode === 'tag'" @click="changeMode('post')">
          <Icon name="tag" />&nbsp;&nbsp;Tags
        </div>
        <div class="label" v-show="mode === 'category'" @click="changeMode('post')">
          <Icon name="folder" />&nbsp;&nbsp;Categories
        </div>
        <input type="text" class="search-inp" v-model="query" />
      </div>
      <div class="result">
        <SearchOption
          :is-active="selectIndex === index"
          :key="item.key"
          v-for="(item, index) of result"
          :item="item"
          @click="onSelect"
        >
        </SearchOption>
      </div>

      <div class="guide">
        <div class="item"><kbd>Enter</kbd> to select</div>

        <div class="item"><kbd>Up</kbd><kbd>Down</kbd> to navigate</div>

        <div class="item"><kbd>Esc</kbd> to close</div>
      </div>
    </div>
  </div>
</template>

<script>
import { useClickOutside } from '@theme/hooks';
import { debounce } from 'lodash-es';
import { ref, watch, inject, computed, onMounted, onUnmounted } from '@vue/composition-api';
import store from '@theme/store';
import { useSearch } from './hooks';
import SearchOption from './SearchOption';

export default {
  name: 'Search',
  components: {
    SearchOption,
  },
  setup(props, { emit }) {
    const $posts = inject('$posts');
    const $category = inject('$category');
    const $tag = inject('$tag');
    const $router = inject('$router');
    const mode = ref('post');

    const tags = Object.keys($tag._metaMap);
    const categories = Object.keys($category._metaMap);

    const onSearch = q => {
      const isAll = q === 'All';

      if (isAll) {
        q = '';
      }

      const reg = new RegExp(q, 'i');
      let result = [];

      if (q || isAll) {
        if (mode.value === 'tag') {
          result = tags
            .filter(tag => reg.test(tag))
            .map(item => ({
              name: item,
              key: item,
              path: `/tag/${item}`,
              type: 'option',
              icon: 'tag',
              count: $tag._metaMap[item].pages.length,
            }));
        } else if (mode.value === 'category') {
          result = categories
            .filter(tag => reg.test(tag))
            .map(item => ({
              name: item,
              key: item,
              path: `/category/${item}`,
              type: 'option',
              icon: 'category',
              count: $category._metaMap[item].pages.length,
            }));
        } else {
          result = $posts
            .filter(post => reg.test(post.title))
            .map(item => {
              return {
                name: item.title,
                key: item.key,
                path: item.path,
                type: 'option',
              };
            });
        }
      }

      const commands = {
        all: {
          type: 'command',
          name: 'All',
          desc: 'to search all',
          icon: '',
          key: 'command:all',
        },
        tags: {
          type: 'command',
          name: 'Tag',
          desc: 'to search tags',
          icon: 'tag',
          key: 'command:tag',
        },
        categories: {
          type: 'command',
          name: 'Category',
          desc: 'to search categories',
          icon: 'folder',
          key: 'command:category',
        },
      };

      if (mode.value === 'post' && !result.length) {
        result.push(commands.all, commands.tags, commands.categories);
      } else if (!result.length) {
        result.push(commands.all);
      }

      if (!isAll) {
        result = result.slice(0, 8);
      }
      return result;
    };

    const onClose = () => (store.showSearch = false);

    const onSelect = item => {
      if (item.type === 'option') {
        $router.push({ path: item.path });
      } else if (item.type === 'command') {
        switch (item.name) {
          case 'All':
            query.value = 'All';
            break;
          case 'Tag':
            changeMode('tag');
            break;
          case 'Category':
            changeMode('category');
            break;
          default:
            break;
        }
      }
    };

    const onBackSpace = () => {
      if (!query.value && mode.value !== 'post') {
        mode.value = 'post';
        search('');
      }
    };

    const { query, result, selectIndex, search } = useSearch({
      onSearch,
      onSelect,
      onClose,
      onBackSpace,
    });

    const changeMode = m => {
      mode.value = m;
      query.value = '';
      search('');
    };

    return {
      mode,
      query,
      result,
      selectIndex,
      onSelect,
      onClose,
      changeMode,
    };
  },
};
</script>

<style lang="stylus" scoped>
@import '~@theme/styles/_mixins.styl';
.search-portal {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 30;
  width: 100%;
  height: 100%;
  padding: 0 space(2);

  .mask {
    position: fixed;
    z-index: 1;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    // background: rgba(54, 64, 73, 0.6);
    background: var(--bg-color-overlay);
    backdrop-filter: blur(15px) saturate(125%);
  }

  .close {
    position relative;
    z-index: 2;
    display: flex;
    justify-content: center;
    font-size: 36px;
    margin: space() space(2);
    cursor: pointer;
  }

  .card {
    rounded(4);
    position: relative;
    z-index: 3;
    max-width: $appWidth;
    margin: 0 auto;
    overflow: hidden;
    background: var(--bg-color-1);
    box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
  }

  .search {
    display: flex;
    align-items: center;
    padding: 0 space(2);

    .search-inp {
      font('xl')
      flex: 1;
      min-width: 0;
      height: 64px;
      line-height: 64px;
      background-color: transparent;
      outline: none;
      border: none;
    }

    border-bottom: 1px solid var(--separator-color);
  }

  .label {
    font('base');
    line-height: 2em;
    display: inline-block;
    padding: 0 space();
    margin-right: space();
    border-radius 4px;
    cursor pointer;
    background: var(--bg-color-2);
  }

  .result {
    flex-direction: column;
    padding: space(2);
    font('lg');
    max-height: 554px;
    overflow-y: auto;
  }

  .guide {
    display: flex;
    flex-flow: row wrap;
    padding: 0 space(2) space(2);
    font('sm');

    +mobile() {
      display: none;
    }

    .item {
      flex: 0 0 auto;
      margin-right: space(2);
    }

    kbd {
      font('xs');
      display: inline-block;
      padding: 0 space();
      border: 1px solid var(--separator-color);
      margin-top: 4px;
      margin-right: 4px;
      border-radius 4px;
    }
  }




}
</style>
