<template>
  <div id="cred-search-component">
    <div class="cred-search_modal">
      <div class="cred-cred-form-inline-wrap">
        <div class="cred-form-inline">
          <v-select
            class="cred-search-bar blue-s"
            placeholder="Search"
            ref="select"
            :filterable="false"
            :options="paginated"
            :loading="loading"
            :clearable="false"
            @search="searching"
            @input="redirectToSelectedApp"
            v-model="selectedValue"
            :label="appNameKey"
            :reduce="(item) => item"
          >
            <template #option="data">
              <div v-if="!data[appNameKey]" class="option-tag">
                <span>{{ data[descriptionKey] }}</span>
              </div>
              <div v-else class="option-tag">
                <span>{{ data[descriptionKey] }}</span>
                &nbsp;<span>({{ data[appNameKey] }})</span>
              </div>
            </template>

            <template #spinner="{ loading }">
              <div
                v-if="loading"
                style="border-left-color: rgba(88, 151, 251, 0.71)"
                class="vs__spinner"
              >
                The .vs__spinner class will hide the text for me.
              </div>
            </template>

            <template #no-options="{ search, loading }">
              {{
                !search
                  ? `Enter text to search all available apps`
                  : loading
                  ? `Searching all available apps for your entered query`
                  : `Sorry unable to find any available apps for your entered query "${search}"`
              }}
            </template>

            <template #open-indicator>
              <!-- <div style="position: absolute; display: none; top: -1000px"></div> -->
              <span class="searchbar-icon" v-if="!loading"></span>
            </template>
          </v-select>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import vSelect from "vue-select";
import Fuse from "fuse.js";
import {
  isPromise,
  isFunction,
  isPlainArray,
  debounce,
} from "@credenceanalytics/utilities";

const changeRoute = function(params, urlKey) {
  if(params[urlKey]) {
    window.location.href = params[urlKey]
  } else console.log("Invalid route");
}

export default {
  props: {
    appList: {
      type: [Array, Promise, Function],
      default() {
        return [];
      },
    },

    appNameKey: {
      type: String,
      default: "APP_NAME",
    },

    routeKey: {
      type: String,
      default: "ROUTE",
    },

    descriptionKey: {
      type: String,
      default: "DESCRIPTION",
    },

    afterRouteChange: {
      type: Function,
    },

    changeRoute: {
      type: Function,
      default: changeRoute,
    },
  },

  components: {
    "v-select": vSelect,
  },

  data() {
    return {
      options: [],
      selectedValue: null,
      searchText: "",
      loading: false,

      paginated: [],
    };
  },

  computed: {
    paginate: {
      get() {
        return this.paginated;
      },
      set({ search, loading }) {
        // Adding some delay effects.
        const { options, descriptionKey, routeKey } = this;
        new Promise(function (resolve) {
          setTimeout(() => {
            const fuse = new Fuse(options, {
              keys: [descriptionKey],
              shouldSort: true,
            });
            resolve(
              search.length
                ? fuse
                    .search(search)
                    .map(({ item }, idx) => ({ ...item, id: idx + item[routeKey] }))
                : fuse.list
            );
          }, 500);
        })
          .then((paginated) => {
            this.paginated = paginated;
            loading(false);
          })
          .catch(() => loading(false));
      },
    },
  },

  watch: {
    appList: {
      handler: debounce(function (newVal) {
        this.setOptionsList(newVal);
      }, 500),
      immediate: true,
    },
  },

  methods: {
    setOptionsList(newVal) {
      this.loading = true;
      if (isPromise(newVal)) {
        return newVal.then(
          ((response) => this.assignArray(response)).bind(this),
          (() => this.assignArray([])).bind(this)
        );
      }
      if (isFunction(newVal)) {
        const RESULT = newVal();
        if (isPromise(RESULT)) {
          return RESULT.then(
            ((response) => this.assignArray(response)).bind(this),
            (() => this.assignArray([])).bind(this)
          );
        }
        return this.assignArray(RESULT);
      }
      return this.assignArray(newVal);
    },

    assignArray(options) {
      this.loading = false;
      if (!isPlainArray(options))
        throw new Error(
          "Oops `appsList` must be Array or Can be a Promise and Function which returns a array"
        );
      this.options = [];
      this.options.length = 0;
      this.options = options;
    },

    searching: debounce(function (search, loading) {
      loading(true);
      this.paginate = { search, loading };
    }, 500),

    redirectToSelectedApp(config) {
      isFunction(this.changeRoute) && this.changeRoute(config, this.routeKey);
      isFunction(this.afterRouteChange) && this.afterRouteChange(config);
    },
  },

  mounted() {
    // this.$refs.select.open = true
  },
};
</script>
<style lang="scss">
#cred-search-component {
  @import "../../../node_modules/vue-select/src/scss/vue-select.scss";

  .cred-search_modal {
    background: transparent;
    position: relative;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    color: #000;

    .option-tag {
      span:nth-child(1) {
        font-weight: bold;
      }
      span:nth-child(2) {
        font-weight: small;
      }
    }

    .searchbar-icon {
      background: url(./img/search-w.svg) center 100% no-repeat;
      padding: 8px;
      // margin: 5px;
    }

    .cred-search-bar {
      display: inline-block;
      max-width: 400px;
      min-width: 320px;
      text-align: left;
    }

    .cred-search-bar .vs__dropdown-menu::-webkit-scrollbar {
      width: 5px;
      height: 5px;
      max-height: 50vh;
    }

    .cred-search-bar .vs__dropdown-menu::-webkit-scrollbar-track {
      border-radius: 50px;
      background: #ccc;
    }

    .cred-search-bar .vs__dropdown-menu::-webkit-scrollbar-thumb {
      border-radius: 50px;
      background: #000;
    }

    .cred-search-bar .vs__dropdown-menu::-webkit-scrollbar-thumb:window-inactive {
      border-radius: 20px;
      background: #eee;
    }

    .cred-search-bar .vs__clear {
      margin-right: 1rem;
    }

    .cred-search-bar .vs__dropdown-toggle {
      padding: 0;
    }

    .cred-search-bar .vs__dropdown-menu {
      padding: 0;
      max-height: 40vh;
    }

    .cred-search-bar .vs__spinner,
    .cred-search-bar .vs__spinner:after {
      border-radius: 50%;
      width: 15px;
      height: 15px;
      border: 2px solid rgba(100, 100, 100, 0.1);
      position: absolute;
      left: 86%;
    }

    .cred-search-bar .vs__dropdown-option {
      padding: 0.3rem 1rem;
      background: #fff;
      white-space: normal;
    }

    .cred-search-bar .vs__selected-options {
      width: calc(100% - 4rem);
      -ms-flex-wrap: nowrap;
      flex-wrap: nowrap;
    }

    .cred-search-bar .vs__selected {
      white-space: nowrap;
      text-overflow: ellipsis;
      width: 100%;
      overflow: hidden;
      display: inline-block;
    }

    .cred-search-bar .vs__dropdown-option--highlight {
      color: #070f63;
      background: #eee !important;
    }

    .cred-search-bar .vs__search,
    .cred-search-bar .vs__search:focus,
    .cred-search-bar .vs__selected {
      padding: 0.6rem 0.5rem !important;
      margin: 0 !important;
    }

    .cred-search-bar .vs__search::-webkit-input-placeholder {
      color: #999;
    }

    .cred-search-bar .vs__search:-ms-input-placeholder {
      color: #999;
    }

    .cred-search-bar .vs__search::-ms-input-placeholder {
      color: #999;
    }

    .cred-search-bar .vs__search::placeholder {
      color: #999;
    }

    .cred-search-bar .vs__no-options {
      color: #000 !important;
      padding: 1rem;
      text-align: left;
    }

    .cred-search-bar.blue-s .vs__dropdown-toggle {
      background: #070f63;
      color: #fff;
      border: 1px solid rgb(80 100 161 / 96%);
      box-shadow: 2px 1px 7px 2px rgb(47 67 128 / 50%);
    }

    .cred-search-bar.blue-s .vs__search,
    .cred-search-bar.blue-s .vs__search:focus,
    .cred-search-bar.blue-s .vs__selected {
      color: #fff;
    }

    .cred-search-bar.blue-s .vs__clear,
    .cred-search-bar.blue-s .vs__open-indicator {
      fill: #fff;
      opacity: 0.8;
    }

    .cred-search-bar.red .vs__dropdown-toggle,
    .cred-search-bar.red .vs__dropdown-menu {
      background: #fbdfdf;
      color: #663939;
    }

    .cred-search-bar.green .vs__dropdown-toggle,
    .cred-search-bar.green .vs__dropdown-menu {
      background: #dffbdf;
      color: #426639;
    }

    /* theme end */
    /*# sourceMappingURL=style.css.map */
  }

  #search-input {
    background: #091762 !important;
    color: #fff;
    border: 1px solid #393f82;
  }
  .pd-10 {
    padding: 10px;
  }
  .selected {
    background: rgb(240, 238, 238) !important;
  }
  .search-suggestions {
    z-index: 10;
    width: 300px;
    background-color: white;
    position: absolute;
    left: 76rem;
    z-index: 9999;
    top: 45px;
    display: none;
    border: 1px solid gray;
    box-shadow: 0px 5px 8px #eeeeee;
    list-style: none;
    padding: 0px 0px;
    cursor: pointer;

    li {
      cursor: pointer;

      &:hover {
        background-color: #eeeeee;
      }
    }
  }
}
</style>
