text: /* eslint-disable camelcase */
  import Component from '@glimmer/component';
  import RSVP from 'rsvp';
  import {action} from '@ember/object';
  import {isBlank, isEmpty} from '@ember/utils';
  import {pluralize} from 'ember-inflector';
  import {run} from '@ember/runloop';
  import {inject as service} from '@ember/service';
  import {task, timeout, waitForProperty} from 'ember-concurrency';
  
  export default class GhSearchInputComponent extends Component {
      @service ajax;
      @service notifications;
      @service router;
      @service store;
  
      content = [];
      contentExpiresAt = false;
      contentExpiry = 30000;
  
      searchables = [{
          name: 'Posts',
          model: 'post',
          fields: ['id', 'title'],
          idField: 'id',
          titleField: 'title'
      }, {
          name: 'Pages',
          model: 'page',
          fields: ['id', 'title'],
          idField: 'id',
          titleField: 'title'
      }, {
          name: 'Users',
          model: 'user',
          fields: ['slug', 'name'],
          idField: 'slug',
          titleField: 'name'
      }, {
          name: 'Tags',
          model: 'tag',
          fields: ['slug', 'name'],
          idField: 'slug',
          titleField: 'name'
      }];
  
      @action
      openSelected(selected) {
          if (!selected) {
              return;
          }
  
          this.args.onSelected?.(selected);
  
          if (selected.searchable === 'Posts') {
              let id = selected.id.replace('post.', '');
              this.router.transitionTo('editor.edit', 'post', id);
          }
  
          if (selected.searchable === 'Pages') {
              let id = selected.id.replace('page.', '');
              this.router.transitionTo('editor.edit', 'page', id);
          }
  
          if (selected.searchable === 'Users') {
              let id = selected.id.replace('user.', '');
              this.router.transitionTo('settings.staff.user', id);
          }
  
          if (selected.searchable === 'Tags') {
              let id = selected.id.replace('tag.', '');
              this.router.transitionTo('tag', id);
          }
      }
  
      @action
      onClose(select, keyboardEvent) {
          // refocus search input after dropdown is closed (eg, by pressing Escape)
          run.later(() => {
              keyboardEvent?.target.focus();
          });
      }
  
      @task({restartable: true})
      *searchTask(term) {
          if (isBlank(term)) {
              return [];
          }
  
          // start loading immediately in the background
          this.refreshContentTask.perform();
  
          // debounce searches to 200ms to avoid thrashing CPU
          yield timeout(200);
  
          // wait for any on-going refresh to finish
          if (this.refreshContentTask.isRunning) {
              yield waitForProperty(this, 'refreshContentTask.isIdle');
          }
  
          const searchResult = this._searchContent(term);
  
          return searchResult;
      }
  
      _searchContent(term) {
          const normalizedTerm = term.toString().toLowerCase();
          const results = [];
  
          this.searchables.forEach((searchable) => {
              const matchedContent = this.content.filter((item) => {
                  const normalizedTitle = item.title.toString().toLowerCase();
                  return (item.searchable === searchable.name) && (normalizedTitle.indexOf(normalizedTerm) >= 0);
              });
  
              if (!isEmpty(matchedContent)) {
                  results.push({
                      groupName: searchable.name,
                      options: matchedContent
                  });
              }
          });
  
          return results;
      }
  
      @task({drop: true})
      *refreshContentTask() {
          let now = new Date();
          let contentExpiresAt = this.contentExpiresAt;
  
          if (contentExpiresAt > now) {
              return true;
          }
  
          const content = [];
          const promises = this.searchables.map(searchable => this._loadSearchable(searchable, content));
  
          try {
              yield RSVP.all(promises);
              this.content = content;
          } catch (error) {
              // eslint-disable-next-line
              console.error(error);
          }
  
          let contentExpiry = this.contentExpiry;
          this.contentExpiresAt = new Date(now.getTime() + contentExpiry);
      }
  
      _loadSearchable(searchable, content) {
          let url = `${this.store.adapterFor(searchable.model).urlForQuery({}, searchable.model)}/`;
          let query = {fields: searchable.fields, limit: 'all'};
  
          return this.ajax.request(url, {data: query}).then((response) => {
              const items = response[pluralize(searchable.model)].map(item => ({
                  id: `${searchable.model}.${item[searchable.idField]}`,
                  title: item[searchable.titleField],
                  searchable: searchable.name
              }));
  
              content.push(...items);
          }).catch((error) => {
              this.notifications.showAPIError(error, {key: `search.load${searchable.name}.error`});
          });
      }
  }
  