(function() {
  var suggestionsXHR;
  function fetchSuggestions(term) {
    if(suggestionsXHR) {
      try {
        suggestionsXHR.abort();
      }
      catch(ex) {
      }
    }
    return new Promise(function(resolve, reject) {
      var xhr = new XMLHttpRequest();
      suggestionsXHR = xhr;
      var url = "https://www.booking.com/autocomplete_2?stype=38&lang=" +
        encodeURIComponent(navigator.language)+ "&aid=1165677&should_split=1&term=" +
        encodeURIComponent(term);
      xhr.open("GET", url);
      xhr.onload = function() {
        try {
          var data = JSON.parse(xhr.responseText);
          var res = [];
          if(data.city && Array.isArray(data.city)) {
            for(let cityInfo of data.city) {
              res.push({
                id: cityInfo.dest_id,
                type: cityInfo.dest_type,
                value: cityInfo.label,
                title: cityInfo.labels,
                hotels: cityInfo.hotels
              });
            }
          }
          resolve(res);
        }
        catch(err) {
          reject(err);
        }
      };
      xhr.onerror = function(err) {
        reject(err);
      };
      xhr.send(null);
    });
  }

  var suggestionsContainer;
  var Suggestions = {
    onChose: new chrome.Event(),
    lastCities: null,
    input: null,
    _onBodyClick: function(event) {
      if(event.target === Suggestions.input || suggestionsContainer.contains(event.target)) {
        return;
      }
      Suggestions.hide();
    },
    _onInputKeyPress: function(event) {
      if(event.key === "ArrowDown") {
        let selected = Suggestions._kbSelectedItem();
        let newSelected;
        if(selected) {
          newSelected = selected.nextSibling;
          if(!newSelected) {
            newSelected = suggestionsContainer.firstChild;
          }
          selected.classList.remove("kb-selected-item");
        }
        else {
          newSelected = suggestionsContainer.firstChild;
        }
        newSelected.classList.add("kb-selected-item");
        event.preventDefault();
      }
      else if(event.key === "ArrowUp") {
        let selected = Suggestions._kbSelectedItem();
        let newSelected;
        if(selected) {
          newSelected = selected.previousSibling;
          if(!newSelected) {
            newSelected = suggestionsContainer.firstChild;
          }
          selected.classList.remove("kb-selected-item");
        }
        else {
          newSelected = suggestionsContainer.firstChild;
        }
        newSelected.classList.add("kb-selected-item");
        event.preventDefault();
      }
      else if(event.key === "Enter") {
        let selected = Suggestions._kbSelectedItem();
        if(selected) {
          Suggestions.onChose.dispatch({
            value: selected.getAttribute("data-value"),
            type: selected.getAttribute("data-type"),
            id: selected.getAttribute("data-id"),
          });
          Suggestions.hide();
          event.preventDefault();
          event.stopPropagation();
        }
      }
      else if(event.key === "Escape") {
        Suggestions.hide();
        event.preventDefault();
        event.stopPropagation();
      }
    },
    _kbSelectedItem: function() {
      return suggestionsContainer.querySelector(".kb-selected-item");
    },
    isVisible: function() {
      return suggestionsContainer.classList.contains("visible");
    },
    tryShow: function(query, input) {
      fetchSuggestions(query).then((cities) => {
        this.lastCities = cities;
        while(suggestionsContainer.firstChild) {
          suggestionsContainer.removeChild(suggestionsContainer.firstChild);
        }
        if(!cities.length) {
          suggestionsContainer.classList.remove("visible");
          return;
        }
        for(let city of cities) {
          let suggestion = document.createElement("div");
          suggestion.classList.add("suggestion");
          let citySpan = document.createElement("span");
          citySpan.textContent = city.title[0].text;
          suggestion.appendChild(citySpan);
          var remainCityParts = city.title.slice(1).map(part => part.text);
          suggestion.appendChild(document.createTextNode(remainCityParts.join(", ")));
          suggestion.setAttribute("data-value", city.value);
          suggestion.setAttribute("data-id", city.id);
          suggestion.setAttribute("data-type", city.type);
          suggestionsContainer.appendChild(suggestion);
        }
        this.show(input);
      });
    },
    show: function(input) {
      this.input = input;
      if(!suggestionsContainer.classList.contains("visible")) {
        suggestionsContainer.classList.add("visible");
        input.addEventListener("keydown", this._onInputKeyPress, false);
        document.body.addEventListener("click", this._onBodyClick, false);
      }
    },
    hide: function() {
      if(suggestionsContainer.classList.contains("visible")) {
        suggestionsContainer.classList.remove("visible");
        this.input && this.input.removeEventListener("keydown", this._onInputKeyPress, false);
        document.body.removeEventListener("click", this._onBodyClick, false);
      }
      var selected = this._kbSelectedItem();
      if(selected) {
        selected.classList.remove("kb-selected-item");
      }
    }
  };
  window.Suggestions = Suggestions;

  document.addEventListener("DOMContentLoaded", function() {
    suggestionsContainer = document.getElementById("city-suggestions");
    suggestionsContainer.addEventListener("click", function(event) {
      var target = event.target;
      if(target.parentNode.matches(".suggestion")) {
        target = target.parentNode;
      }
      if(target.matches(".suggestion")) {
        var value = target.getAttribute("data-value");
        Suggestions.onChose.dispatch({
          id: target.getAttribute("data-id"),
          type: target.getAttribute("data-type"),
          value: value,
        });
        Suggestions.hide();
      }
    }, false);
  }, false);
})();