/**********************************************************************************************
    Copyright (C) 2025 Oliver Eichler <oliver.eichler@gmx.de>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

**********************************************************************************************/

#include "CWptIconSelectWidget.h"

#include <helpers/CWptIconManager.h>
#include <qcombobox.h>
#include <qcompleter.h>

#include <QBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMouseEvent>
#include <QPainter>
#include <QResizeEvent>
#include <QScrollArea>
#include <QScrollBar>

#include "widgets/CIconGrid.h"

CWptIconSelectWidget::CWptIconSelectWidget(QWidget *parent) : QWidget(parent) {
  scrollArea = new QScrollArea(this);
  scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
  scrollArea->verticalScrollBar()->setSingleStep(CIconGrid::kTileSize);
  scrollArea->setWidgetResizable(true);
  scrollArea->setMinimumHeight(CIconGrid::kVisibleRows * CIconGrid::kTileSize);
  scrollArea->setMinimumWidth(CIconGrid::kVisibleCols * CIconGrid::kTileSize);

  iconGrid = new CIconGrid(scrollArea);
  scrollArea->setWidget(iconGrid);

  iconName = new QLabel(this);
  QFont f = iconName->font();
  f.setBold(true);
  iconName->setFont(f);
  iconName->setAlignment(Qt::AlignCenter);

  actionClearFilter = new QAction(QIcon(":/icons/Filter.svgt"), tr("Clear Filter"), this);
  actionClearFilter->setObjectName("actionClearFilter");

  iconFilter = new QLineEdit(this);
  iconFilter->setPlaceholderText(tr("start typing..."));
  iconFilter->setToolTip(tr("Filter: Start to type and the list will be reduced to matching items."));
  iconFilter->addAction(actionClearFilter, QLineEdit::TrailingPosition);

  categoryFilter = new QComboBox(this);
  categoryFilter->setToolTip(tr("Filter: Show only icons in selected category"));

  vendorFilter = new QComboBox(this);
  vendorFilter->setToolTip(tr("Filter: Show only icons for selected vendor"));

  layout1 = new QBoxLayout(QBoxLayout::TopToBottom, this);
  layout1->setContentsMargins(0, 0, 0, 0);

  layout2 = new QBoxLayout(QBoxLayout::LeftToRight);
  layout2->setContentsMargins(0, 0, 0, 0);
  layout2->addWidget(categoryFilter);
  layout2->addWidget(iconFilter);
  layout2->addWidget(vendorFilter);

  layout1->addLayout(layout2);
  layout1->addWidget(iconName);
  layout1->addWidget(scrollArea);

  connect(iconGrid, &CIconGrid::sigIconName, iconName, &QLabel::setText);
  connect(iconGrid, &CIconGrid::sigSelectedIcon, this, &CWptIconSelectWidget::sigSelectedIcon);
  connect(iconFilter, &QLineEdit::textChanged, this, &CWptIconSelectWidget::slotFilterChanged);
  connect(categoryFilter, &QComboBox::currentTextChanged, this, &CWptIconSelectWidget::slotCategoryChanged);
  connect(vendorFilter, &QComboBox::currentTextChanged, this, &CWptIconSelectWidget::slotVendorChanged);
  connect(actionClearFilter, &QAction::triggered, iconFilter, &QLineEdit::clear);
  connect(&CWptIconManager::self(), &CWptIconManager::sigChanged, this, &CWptIconSelectWidget::slotWptListChanged);

  slotWptListChanged();
}

void CWptIconSelectWidget::slotFilterChanged(const QString &str) {
  actionClearFilter->setIcon(str.isEmpty() ? QIcon("://icons/Filter.svgt") : QIcon("://icons/Cancel.svgt"));
  updateIconList(str, categoryFilter->currentText(), vendorFilter->currentText());
}

void CWptIconSelectWidget::slotCategoryChanged(const QString &str) {
  updateIconList(iconFilter->text(), str, vendorFilter->currentText());
}

void CWptIconSelectWidget::slotVendorChanged(const QString &str) {
  updateIconList(iconFilter->text(), categoryFilter->currentText(), str);

  updateCategories(str, categoryFilter->currentText());
}

void CWptIconSelectWidget::slotWptListChanged() {
  QStringList vendors = {"QMapShack", "Garmin"};

  QString selectedVendor = vendorFilter->currentText();
  if (selectedVendor.isEmpty()) {
    selectedVendor = vendors[0];
  }

  iconFilter->clear();
  vendorFilter->clear();

  updateCategories(selectedVendor, categoryFilter->currentText());

  vendorFilter->addItems(vendors);

  updateIconList("", "", "");
}

void CWptIconSelectWidget::updateCategories(const QString &vendor, const QString &selected) {
  categoryFilter->clear();

  const QMap<QString, QStringList> &vendorCategories = CWptIconManager::self().getVendorCategories();

  QStringList categories;
  if (vendorCategories.contains(vendor)) {
    categories = vendorCategories[vendor];
  }
  categories.prepend("");
  categories.sort();

  categoryFilter->addItems(categories);

  if (categories.contains(selected)) {
    categoryFilter->setCurrentText(selected);
  }
}

void CWptIconSelectWidget::updateIconList(const QString &filter, const QString &category, const QString &vendor) {
  // filter by category
  QList<CWptIconManager::icon_t> availableIcons;
  if (category.isEmpty()) {
    availableIcons = CWptIconManager::self().getWptIcons();
  } else {
    const QList<CWptIconManager::icon_t> &icons = CWptIconManager::self().getWptIcons();
    for (const CWptIconManager::icon_t &icon : icons) {
      if (icon.categories.contains(category)) {
        availableIcons.append(icon);
      }
    }
  }

  // filter by vendor
  QString selectedVendor = vendor.isEmpty() ? "QMapShack" : vendor;
  QList<CWptIconManager::icon_t> vendorIcons;
  for (const CWptIconManager::icon_t &icon : availableIcons) {
    if (icon.vendors.contains(selectedVendor)) {
      vendorIcons.append(icon);
    }
  }

  QList<CWptIconManager::icon_t> visibleIcons;
  // filter by name and tags
  if (filter.isEmpty()) {
    visibleIcons = vendorIcons;
  } else {
    visibleIcons.clear();
    for (const CWptIconManager::icon_t &icon : vendorIcons) {
      if (icon.name.contains(filter, Qt::CaseInsensitive)) {
        visibleIcons.append(icon);
      } else {
        const QStringList &tags = icon.tags;
        if (!tags.filter(filter, Qt::CaseInsensitive).isEmpty()) {
          visibleIcons.append(icon);
        }
      }
    }
  }

  QSet<QString> availableTags;
  for (const CWptIconManager::icon_t &icon : visibleIcons) {
    availableTags.insert(icon.name);
    for (const QString &tag : icon.tags) {
      availableTags.insert(tag);
    }
  }

  iconFilterCompleter = new QCompleter(availableTags.values(), this);
  iconFilterCompleter->setCaseSensitivity(Qt::CaseInsensitive);
  iconFilterCompleter->setFilterMode(Qt::MatchContains);
  iconFilterCompleter->setCompletionMode(QCompleter::UnfilteredPopupCompletion);
  iconFilterCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel);
  iconFilter->setCompleter(iconFilterCompleter);
  iconGrid->updateIconList(visibleIcons);
  scrollArea->verticalScrollBar()->setValue(0);
}
