/*
 * Copyright (C) 2023, KylinSoft Co., Ltd.
 *
 * 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, 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 "timezonemap.h"

#include <QApplication>
#include <QPainter>
#include <QIcon>
#include <QApplication>
#include <QImageReader>
#include <QDebug>

const QString timezoneMapFile =":/images/map-light.svg";
const QString dotFile = ":/images/indicator.png";


QPixmap TimezoneMap::loadPixmap(const QString &path)
{
    qreal ratio = 1.0;
    QPixmap pixmap;

    const qreal devicePixelRatio = qApp->devicePixelRatio();

    if (!qFuzzyCompare(ratio, devicePixelRatio)) {
        QImageReader reader;
        reader.setFileName(qt_findAtNxFile(path, devicePixelRatio, &ratio));
        if (reader.canRead()) {
            reader.setScaledSize(reader.size() * (devicePixelRatio / ratio));
            pixmap = QPixmap::fromImage(reader.read());
            pixmap.setDevicePixelRatio(devicePixelRatio);
        }
    } else {
        pixmap.load(path);
    }

    return pixmap;
}

TimezoneMap::TimezoneMap(QWidget* parent) : QFrame (parent),
    m_zoninfo(new ZoneInfo),m_currentZone(),m_nearestZones()
{
    m_totalZones = m_zoninfo->getzoneInforList();

    this->initUI();
}


TimezoneMap::~TimezoneMap(){
    if (m_popmenu) {
        delete m_popmenu;
        m_popmenu = nullptr;
    }
}


QString TimezoneMap::getTimezone() {
    return m_currentZone.timezone;
}

void TimezoneMap::initUI() {
    backgroundLabel = new QLabel(this);
    backgroundLabel->setObjectName("background_label");
    backgroundLabel->setProperty("useIconHighlightEffect", 0x02);

    QPixmap timezonePixmap(timezoneMapFile);
    //QPixmap timezonePixmap = loadPixmap(timezoneMapFile);
//    qDebug()<<"timezonePixmap--------->"<<timezonePixmap<<endl;
    Q_ASSERT(!timezonePixmap.isNull());
    backgroundLabel->setPixmap(timezonePixmap);

    m_dot = new Dotlabel(QSize(8, 8), this->parentWidget());
    m_dot->setFixedSize(8, 8);

    m_dot->hide();


    m_singleList = new ToolPop(this->parentWidget());
    m_singleList->setFixedHeight(36);
    m_singleList->setMinimumWidth(60);
    m_singleList->setAttribute(Qt::WA_TransparentForMouseEvents, true);
    m_singleList->hide();

    m_popmenu = new PopMenu();

    this->setContentsMargins(0,0,0,0);

    connect(m_popmenu,&PopMenu::listHide,
            m_dot, &QRadioButton::hide);
    connect(m_popmenu,&PopMenu::listAactive,
            this, &TimezoneMap::popListActiveSlot);
}


QPoint TimezoneMap::zoneInfoToPosition(ZoneInfo_ zone, int mapWidth, int mapHeight) {
    int x = int(m_zoninfo->converLongtitudeToX(zone.longtitude, mapWidth));
    int y = int(m_zoninfo->converLatitudeToY(zone.latitude, mapHeight));
    return QPoint(x, y);
}

void TimezoneMap::mark() {
    m_dot->hide();
    m_singleList->hide();

    int mapWidth = this->width();
    int mapHeight = this->height();

    Q_ASSERT(!m_nearestZones.isEmpty());

    QString locale = QLocale::system().name();
    if (!m_nearestZones.isEmpty()) {
        int correctX = 0;
        int correctY = 0;
        if (m_currentZone.timezone == "Asia/Taipei") {
            correctX = 5;
            correctY = 4;
        } else if (m_currentZone.timezone == "Asia/Vladivostok") {
            correctX = 8;
        }
        m_singleList->setText(m_zoninfo->getLocalTimezoneName(m_currentZone.timezone, locale));
        m_singleList->adjustSize();

        QPoint zonePos = this->zoneInfoToPosition(m_currentZone,mapWidth,mapHeight);
        int zoneDy = zonePos.y() - m_dot->height() / 2;

        QPoint zoneSingleRlativePos(zonePos.x(), zoneDy);
        QPoint zoneSinglePos(this->mapToParent(zoneSingleRlativePos));
        m_singleList->popupSlot(zoneSinglePos);

        QPoint dotRelativePos(zonePos.x() - m_dot->width() + correctX,
                              zonePos.y() - m_dot->height() + correctY);

        QPoint dotPos(this->mapToParent(dotRelativePos));
        m_dot->move(dotPos);
        m_dot->show();
    }
}

void TimezoneMap::popupZoneList(QPoint pos) {
    m_dot->hide();
    m_singleList->hide();
    m_popmenu->close();


    QString locale = QLocale::system().name();
    QStringList zoneNames;

    for (ZoneInfo_ zone : m_nearestZones) {
        zoneNames.append(m_zoninfo->getLocalTimezoneName(zone.timezone, locale));
    }

    m_popmenu->setStringList(zoneNames);
    // y坐标
    int dy = pos.y() - 5;
    QPoint popupListPos = this->mapToGlobal(QPoint(pos.x(), dy));
    m_popmenu->showPopLists(popupListPos);

    QPoint dotRelativePos(pos.x() - m_dot->width(),
                          pos.y() - m_dot->height());
    QPoint dot_pos(this->mapToParent(dotRelativePos));

    m_dot->move(dot_pos);
    m_dot->show();
}

void TimezoneMap::popListActiveSlot(int index) {
    m_dot->hide();

    Q_ASSERT(index < m_nearestZones.length());
    if (index < m_nearestZones.length()) {
        m_currentZone = m_nearestZones.at(index);
        this->mark();
        emit this->timezoneSelected(m_currentZone.timezone);
    }
}

void TimezoneMap::setTimezone(QString timezone) {
//    timezone = (timezone == "Asia/Beijing" ? "Asia/Shanghai" : timezone);
    m_nearestZones.clear();
    int index = m_zoninfo->getZoneInfoByZone(m_totalZones, timezone);
    if (index > -1) {
        m_currentZone = m_totalZones.at(index);
        m_nearestZones.append(m_currentZone);
        this->mark();
    } else {
        //qWarning() <<" failed to found "<<timezone<<endl;
    }
}

void TimezoneMap::mousePressEvent(QMouseEvent *event) {
    if (event->button() == Qt::LeftButton) {
        m_nearestZones = m_zoninfo->getNearestZones(m_totalZones,100.0,
                                                    event->x(), event->y(),
                                                    this->width(), this->height());
        if (m_nearestZones.length() == 1){
            m_currentZone = m_nearestZones.first();
            this->mark();
            emit this->timezoneSelected(m_currentZone.timezone);
        } else {
            this->popupZoneList(event->pos());
        }
    } else {
        QWidget::mousePressEvent(event);
    }
}

void TimezoneMap::resizeEvent(QResizeEvent *event) {
    QLabel *background_label = findChild<QLabel*>("background_label");
    if (background_label) {
        QPixmap timezone_pixmap = loadPixmap(timezoneMapFile);
        background_label->setPixmap(timezone_pixmap.scaled(event->size() * devicePixelRatioF(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
    }
    QWidget::resizeEvent(event);
}

QDebug& operator<<(QDebug& debug, const ZoneInfo_& info) {
  debug << "ZoneInfo {"
        << "cc:" << info.country
        << "tz:" << info.timezone
        << "lat:" << info.latitude
        << "lng:" << info.longtitude
        << "}";
  return debug;
}


