#include <utility>
#include <QObject>
#include <QFileDialog>
#include <QMessageBox>
#include <QHash>
#include <QImage>
#include <QThreadPool>
#include <QTableWidgetItem>
#include "ui_taskwindow.h"

#include <taskwindow.h>
#include <tmslayer.h>
#include <network.h>
#include <imgwriter.h>
#include <tmsprovider.h>
#pragma execution_character_set("utf-8")

namespace LAMPMainWidget
{
  void
  DownloadTask::run()
  {
    auto currentLayer = dynamic_cast<const TmsLayer *>(mTaskInfo.layer);
    auto provider = dynamic_cast<const TmsProvider*>(&currentLayer->provider());
    auto tileSize = provider->tileSize();

    QHash<QPoint, QString> tiles{};
    QSize imgSize{};
    if (!currentLayer->parseTiles(mTaskInfo.extent, mTaskInfo.zoom, tiles, imgSize)) {
      qCritical() << "瓦片路径解析错误";
      generateErrorRow();
      return;
    }
    generateSuccessRow();

    ImgWriter imgWriter{mTaskInfo.taskPath, imgSize};
    QByteArray tileData{};
    Network web{};
    auto item = tiles.constBegin();
    auto count = tiles.count();
    int completed{0};
    for (; item != tiles.constEnd(); ++item) {
      tileData = web.httpsRequest(item.value());
      if (tileData.isEmpty()) {
        qCritical() << item.value() << "下载数据为空";
        return;
      }
      ++completed;
      auto pos = QPoint(item.key().x() * tileSize.width(), item.key().y() * tileSize.height());
      if (!imgWriter.write(pos, tileData)) {
        qCritical() << "瓦片写出失败";
      }
      double progress = static_cast<double>(completed) / count;
      auto progessStr = QString("%1").arg(progress * 100);
      mTaskInfo.display->takeItem(mRowId, 4);
      mTaskInfo.display->setItem(mRowId, 4,
                                 new QTableWidgetItem(QString("%1").arg(progress * 100)));
      // mTaskInfo.display->resizeColumnsToContents();
      // mTaskInfo.display->horizontalHeader()->setStretchLastSection(true);
    }
  }

  void
  DownloadTask::generateCommonRow()
  {
    auto provider = dynamic_cast<const TmsProvider*>(&mTaskInfo.layer->provider());
    mRowId = mTaskInfo.display->rowCount();
    mTaskInfo.display->insertRow(mRowId);
    mTaskInfo.display->setItem(mRowId, 0, new QTableWidgetItem(mTaskInfo.taskName));
    mTaskInfo.display->setItem(mRowId, 1, new QTableWidgetItem(getExtentStr()));
    mTaskInfo.display->setItem(mRowId, 2, new QTableWidgetItem(QString("%1").arg(mTaskInfo.zoom)));
    mTaskInfo.display->setItem(mRowId, 3, new QTableWidgetItem(provider->id()));
  }

  void
  DownloadTask::generateErrorRow()
  {
    generateCommonRow();
    mTaskInfo.display->setItem(mRowId, 4, new QTableWidgetItem("任务新建失败"));
    mTaskInfo.display->resizeColumnsToContents();
  }

  void
  DownloadTask::generateSuccessRow()
  {
    generateCommonRow();
    mTaskInfo.display->setItem(mRowId, 4, new QTableWidgetItem("0.0%"));
    mTaskInfo.display->resizeColumnsToContents();
  }

  QString
  DownloadTask::getExtentStr()
  {
    auto leftTop = mTaskInfo.extent.topLeft();
    auto rightBottom = mTaskInfo.extent.bottomRight();
    return QString("[%1, %2], [%3, %4]").arg(leftTop.x()).arg(leftTop.y())
                                        .arg(rightBottom.x()).arg(rightBottom.y());
  }

  TaskWindow::TaskWindow(QWidget* parent)
    : mUi(new Ui::TaskWindow),
      mParent(dynamic_cast<RasterMainWidget *>(parent)),
      mSavePath(),
      QDialog(parent)
  {
    mUi->setupUi(this);
    setupWindow();
    setupAction();
  }

  TaskWindow::~TaskWindow()
  {
    delete mUi;
  }

  void
  TaskWindow::setupWindow()
  {
    setFixedSize(size());
    auto currentLayer = dynamic_cast<const TmsLayer *>(mParent->mMapConvas->currentLayer());

    auto minZoom = currentLayer->minZoom();
    auto maxZoom = currentLayer->maxZoom();
    for (auto i = minZoom; i <= maxZoom; ++i) {
      mUi->zoomValueCbx->addItem(QString("%1").arg(i), i);
    }
    mUi->leftTopText->setText(
      QString("%1, %2").arg(mParent->mLeftTop.x()).arg(mParent->mLeftTop.y()));
    mUi->rightBottomText->setText(
      QString("%1, %2").arg(mParent->mRightBottom.x()).arg(mParent->mRightBottom.y()));
  }

  void
  TaskWindow::setupAction()
  {
    QObject::connect(mUi->exitBtn, &QPushButton::clicked, this, &TaskWindow::close);
    QObject::connect(mUi->createBtn, &QPushButton::clicked, this, &TaskWindow::createTask);
    QObject::connect(mUi->saveDirBtn, &QPushButton::clicked, this, &TaskWindow::setupSaveDir);
    QObject::connect(mUi->taskNameText, &QLineEdit::textChanged, this, &TaskWindow::setupTaskName);
    QObject::connect(mUi->zoomValueCbx, QOverload<int>::of(&QComboBox::currentIndexChanged),
                     this, &TaskWindow::setupZoomValue);
  }

  void
  TaskWindow::createTask()
  {
    if (!taskInfoCheck()) {
      return;
    }

    mSavePath.append("/").append(mTaskName).append(".tiff");
    auto savePath = QDir::toNativeSeparators(mSavePath);
    auto extent = QRectF(QPointF(mParent->mLeftTop.x(), mParent->mLeftTop.y()),
                         QPointF(mParent->mRightBottom.x(), mParent->mRightBottom.y()));
    auto tileInfo = TaskInfo{ mTaskName, savePath, extent,
        mZoomValue,
        mParent->mMapConvas->currentLayer(),
        mParent->getTaskTable()
        /*mParent->mUi->taskTable*/};

    auto task = new DownloadTask(tileInfo);
    QThreadPool::globalInstance()->start(task);
    close();
  }

  void
  TaskWindow::setupSaveDir()
  {
    auto saveDir = QFileDialog::getExistingDirectory(dynamic_cast<QWidget *>(this), "存储路径选择");
    if (saveDir.isEmpty()) {
      qWarning() << "未选择存储路径";
      return;
    }

    mSavePath = saveDir;
    mUi->saveDirText->setText(mSavePath);
  }

  void
  TaskWindow::setupTaskName(const QString& text)
  {
    qDebug() << "任务名=>" << text;
    mTaskName = text;
  }

  bool
  TaskWindow::taskInfoCheck()
  {
    if (mTaskName.isEmpty()) {
      QMessageBox::critical(dynamic_cast<QWidget *>(this), "错误", "任务名称为空");
      return false;
    }

    if (mSavePath.isEmpty()) {
      QMessageBox::critical(dynamic_cast<QWidget *>(this), "错误", "存储路径为空");
      return false;
    }

    return true;
  }

  void
  TaskWindow::setupZoomValue(int index)
  {
    auto zoom = mUi->zoomValueCbx->itemData(index).toInt();
    qDebug() << "设置下载任务zoom值=>" << zoom;
    mZoomValue = zoom;
  }
}
