<div class="compose-autosuggest {{shown ? 'shown' : ''}} {{realm === 'dialog' ? 'is-dialog' : ''}}"
       aria-hidden="true" >
  <ComposeAutosuggestionList
    items="{{searchResults}}"
    on:click="onClick(event)"
    :type
    :selected
  />
</div>
<style>
  .compose-autosuggest {
    position: absolute;
    left: 5px;
    top: 0;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.1s linear;
    min-width: 400px;
    max-width: calc(100vw - 20px);
    z-index: 7000;
  }
  .compose-autosuggest.is-dialog {
    z-index: 11000;
  }
  .compose-autosuggest.shown {
    pointer-events: auto;
    opacity: 1;
  }

  @media (max-width: 479px) {
    .compose-autosuggest {
      /* hack: move this over to the left on mobile so it's easier to see */
      transform: translateX(-58px); /* avatar size 48px + 10px padding */
      min-width: 0;
      width: calc(100vw - 20px);
    }
  }

</style>
<script>
  import { store } from '../../_store/store'
  import { database } from '../../_database/database'
  import { insertUsername } from '../../_actions/compose'
  import { insertEmojiAtPosition } from '../../_actions/emoji'
  import { scheduleIdleTask } from '../../_utils/scheduleIdleTask'
  import { once } from '../../_utils/once'
  import ComposeAutosuggestionList from './ComposeAutosuggestionList.html'

  const SEARCH_RESULTS_LIMIT = 4
  const DATABASE_SEARCH_RESULTS_LIMIT = 30
  const MIN_PREFIX_LENGTH = 1
  const ACCOUNT_SEARCH_REGEX = new RegExp(`(?:\\s|^)(@\\S{${MIN_PREFIX_LENGTH},})$`)
  const EMOJI_SEARCH_REGEX = new RegExp(`(?:\\s|^)(:[^:]{${MIN_PREFIX_LENGTH},})$`)

  export default {
    oncreate() {
      // perf improves for input responsiveness
      this.observe('composeSelectionStart', () => {
        scheduleIdleTask(() => {
          this.set({composeSelectionStartDeferred: this.get('composeSelectionStart')})
        })
      })
      this.observe('composeFocused', (composeFocused) => {
        let updateFocusedState = () => {
          scheduleIdleTask(() => {
            this.set({composeFocusedDeferred: this.get('composeFocused')})
          })
        }

        // TODO: hack so that when the user clicks the button, and the textarea blurs,
        // we don't immediately hide the dropdown which would cause the click to get lost
        if (composeFocused) {
          updateFocusedState()
        } else {
          Promise.race([
            new Promise(resolve => setTimeout(resolve, 200)),
            new Promise(resolve => this.once('autosuggestItemSelected', resolve))
          ]).then(updateFocusedState)
        }
      })
      this.observe('searchText', async searchText => {
        if (!searchText) {
          return
        }
        let type = searchText.startsWith('@') ? 'account' : 'emoji'
        let results = (type === 'account')
          ? await this.searchAccounts(searchText)
          : await this.searchEmoji(searchText)
        this.store.set({
          composeAutosuggestionSelected: 0,
          composeAutosuggestionSearchText: searchText,
          composeAutosuggestionSearchResults: results,
          composeAutosuggestionType: type,
        })
      })
      this.observe('shown', shown => {
        this.store.set({composeAutosuggestionShown: shown})
      })
    },
    methods: {
      once: once,
      onClick(item) {
        this.fire('autosuggestItemSelected')
        let realm = this.get('realm')
        let selectionStart = this.store.get('composeSelectionStart')
        let searchText = this.store.get('composeAutosuggestionSearchText')
        let startIndex = selectionStart - searchText.length
        let endIndex = selectionStart
        if (item.acct) {
          /* no await */ insertUsername(realm, item.acct, startIndex, endIndex)
        } else {
          /* no await */ insertEmojiAtPosition(realm, item, startIndex, endIndex)
        }

      },
      async searchAccounts(searchText) {
        searchText = searchText.substring(1)
        let currentInstance = this.store.get('currentInstance')
        let results = await database.searchAccountsByUsername(
          currentInstance, searchText, DATABASE_SEARCH_RESULTS_LIMIT)
        return results.slice(0, SEARCH_RESULTS_LIMIT)
      },
      searchEmoji(searchText) {
        searchText = searchText.toLowerCase().substring(1)
        let customEmoji = this.store.get('currentCustomEmoji')
        let results = customEmoji.filter(emoji => emoji.shortcode.toLowerCase().startsWith(searchText))
          .sort((a, b) => a.shortcode.toLowerCase() < b.shortcode.toLowerCase() ? -1 : 1)
          .slice(0, SEARCH_RESULTS_LIMIT)
        return results
      }
    },
    computed: {
      composeSelectionStart: ($composeSelectionStart) => $composeSelectionStart,
      composeFocused: ($composeFocused) => $composeFocused,
      searchResults: ($composeAutosuggestionSearchResults) => $composeAutosuggestionSearchResults || [],
      type: ($composeAutosuggestionType) => $composeAutosuggestionType || 'account',
      selected: ($composeAutosuggestionSelected) => $composeAutosuggestionSelected || 0,
      searchText: (text, composeSelectionStartDeferred) => {
        let selectionStart = composeSelectionStartDeferred || 0
        if (!text || selectionStart < MIN_PREFIX_LENGTH) {
          return
        }

        let textUpToCursor = text.substring(0, selectionStart)
        let match = textUpToCursor.match(ACCOUNT_SEARCH_REGEX) || textUpToCursor.match(EMOJI_SEARCH_REGEX)
        return match && match[1]
      },
      shown: (composeFocusedDeferred, searchText, searchResults) => {
        return !!(composeFocusedDeferred &&
          searchText &&
          searchResults.length)
      }
    },
    store: () => store,
    components: {
      ComposeAutosuggestionList
    }
  }
</script>