#pragma once

#include "map/framework.hpp"

#include "platform/downloader_defines.hpp"

#include "base/thread_checker.hpp"

#include <cstdint>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include <QtWidgets/QApplication>
#include <QtWidgets/QDialog>

class QTreeWidget;
class QTreeWidgetItem;
class QLabel;
class QPushButton;

class Framework;

namespace qt
{
  class UpdateDialog : public QDialog
  {
    Q_OBJECT

  public:
    explicit UpdateDialog(QWidget * parent, Framework & framework);
    virtual ~UpdateDialog();

    /// @name Called from downloader to notify GUI
    //@{
    void OnCountryChanged(storage::CountryId const & countryId);
    void OnCountryDownloadProgress(storage::CountryId const & countryId,
                                   downloader::Progress const & progress);
    //@}

    void ShowModal();

  private slots:
    void OnItemClick(QTreeWidgetItem * item, int column);
    void OnCloseClick();
    void OnLocaleTextChanged(QString const & text);
    void OnQueryTextChanged(QString const & text);

  private:
    // CountryId to its ranking position and matched string (assuming no duplicates).
    using Filter = std::unordered_map<storage::CountryId, std::pair<size_t, std::string>>;

    void RefillTree();
    void StartSearchInDownloader();

    // Adds only those countries present in |filter|.
    // Calls whose timestamp is not the latest are discarded.
    void FillTree(std::optional<Filter> const & filter, uint64_t timestamp);
    void FillTreeImpl(QTreeWidgetItem * parent, storage::CountryId const & countryId,
                      std::optional<Filter> const & filter);

    void UpdateRowWithCountryInfo(storage::CountryId const & countryId);
    void UpdateRowWithCountryInfo(QTreeWidgetItem * item, storage::CountryId const & countryId);
    QString GetNodeName(storage::CountryId const & countryId);

    QTreeWidgetItem * CreateTreeItem(storage::CountryId const & countryId, size_t posInRanking,
                                     std::string matchedBy, QTreeWidgetItem * parent);
    std::vector<QTreeWidgetItem *> GetTreeItemsByCountryId(storage::CountryId const & countryId);
    storage::CountryId GetCountryIdByTreeItem(QTreeWidgetItem *);

    inline storage::Storage & GetStorage() const { return m_framework.GetStorage(); }

    QTreeWidget * m_tree;
    Framework & m_framework;
    int m_observerSlotId;

    // Params of the queries to the search engine.
    std::string m_query;
    std::string m_locale = "en";
    uint64_t m_fillTreeTimestamp = 0;

    std::unordered_multimap<storage::CountryId, QTreeWidgetItem *> m_treeItemByCountryId;

    DECLARE_THREAD_CHECKER(m_threadChecker);
  };
}  // namespace qt
