// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

class OptionsPage {
  constructor() {
    window.addEventListener('message', this.onMessage_.bind(this));
    document.getElementById('searchInput')
        .addEventListener('input', this.searchChanged_.bind(this));
    document.getElementById('clearButton')
        .addEventListener('click', this.clearSearch_.bind(this));
    this.sendToBackground_({type: 'getVoices'});
  }

  /**
   * @param {!Object} message
   * @private
   */
  onMessage_(message) {
    let command = JSON.parse(message.data);
    if (command.type == 'updateVoices') {
      this.updateVoices_(command.data);
    }
  }

  /**
   * @param {!Object} message
   * @private
   */
  sendToBackground_(message) {
    chrome.extension.getBackgroundPage().postMessage(
        JSON.stringify(message), window.location.origin);
  }

  /**
   * @param {!Array} voices
   * @private
   */
  updateVoices_(voices) {
    this.voices_ = voices;
    this.voices_.sort((v1, v2) => {
      return v1.displayName.localeCompare(v2.displayName);
    });

    let voiceContainer = document.getElementById('voiceContainer');
    voiceContainer.textContent = '';

    this.voiceList_ = document.createElement('ul');
    voiceContainer.appendChild(this.voiceList_);
    let langSet = new Set();
    this.voices_.forEach((voice) => {
      if (langSet.has(voice.language)) {
        return;
      }
      langSet.add(voice.language);
      voice.voiceItem = document.createElement('li');
      this.voiceList_.appendChild(voice.voiceItem);
      voice.voiceItem.className = 'option';
      voice.voiceItem.id = 'li-' + voice.language;

      let aboutVoice = document.createElement('div');
      voice.voiceItem.appendChild(aboutVoice);
      aboutVoice.className = 'about';

      let voiceText = document.createElement('div');
      aboutVoice.appendChild(voiceText);
      voiceText.id = voice.language;
      voiceText.textContent = voice.displayName;
      voiceText.className = 'name';

      // Override the DOM ordering only for accessibility by using aria-owns.
      aboutVoice.setAttribute('aria-owns', voiceText.id);

      let actionButton = document.createElement('button');
      voice.voiceItem.appendChild(actionButton);
      // TODO: get i18n working.
      actionButton.textContent = voice.remote ?
          (voice.unloaded ? 'Install' : 'Uninstall') :
          'Built in';
      actionButton.setAttribute('aria-describedby', voiceText.id);
      actionButton.disabled = !voice.remote;

      actionButton.addEventListener('click', (evt) => {
        actionButton.disabled = true;
        this.sendToBackground_(
            {type: voice.unloaded ? 'addVoice' : 'removeVoice', data: voice});
      });
    });
    // Apply the search.
    this.searchChanged_();
  }

  /**
   * Called when the button to clear the search box is clicked.
   * @private
   */
  clearSearch_() {
    let searchInput = document.getElementById('searchInput');
    searchInput.value = '';
    this.searchChanged_();
    searchInput.focus();
  }

  /**
   * Called when the search box contents change.
   * @private
   */
  searchChanged_() {
    if (!this.voiceList_) return;
    let errorMessage = document.getElementById('errorMessage');
    let clearButton = document.getElementById('clearButton');
    let searchInput = document.getElementById('searchInput').value.trim();
    let searchInputLower = searchInput.toLowerCase();
    let topResult = '';
    let resultCount = 0;
    this.voices_.forEach((voice) => {
      voice.speakers.forEach((speaker) => {
        let element = document.getElementById('li-' + voice.language);
        if (searchInput === '' ||
            speaker.name.toLowerCase().search(searchInputLower) >= 0 ||
            voice.displayName.toLowerCase().search(searchInputLower) >= 0) {
          if (topResult === '') topResult = voice.displayName;
          element.style['display'] = '';
          resultCount += 1;
        } else {
          element.style['display'] = 'none';
        }
      });
    });
    clearButton.style['display'] = searchInput === '' ? 'none' : '';
    if (resultCount === 0) {
      errorMessage.innerText = 'No search results found';
      errorMessage.style['display'] = '';
    } else {
      errorMessage.innerText = '';
      errorMessage.style['display'] = 'none';
    }
    // Update the live region with a delay to report the results.
    // Clear a previous timeout so we don't do too many duplicate announcements.
    clearTimeout(this.searchSummaryUpdate_);
    this.searchSummaryUpdate_ = setTimeout(() => {
      let searchSummary = document.getElementById('searchSummary');
      if (resultCount === 0) {
        searchSummary.innerText = 'No results for ' + searchInput;
      } else if (searchInput === '') {
        searchSummary.innerText = '';
      } else {
        searchSummary.innerText = 'Top result ' + topResult + '. ' +
            resultCount +
            (resultCount === 1 ? ' result for ' : ' results for ') +
            searchInput;
      }
    }, 200);
  }
}

window.page = new OptionsPage();
