#include "mediaparticlewidget.h"
#include "../models.h"
#include "../networkmanager.h"
#include <QAudioOutput>
#include <QLabel>
#include <QMediaPlayer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QVBoxLayout>
#include <QVideoWidget>

MediaParticleWidget::MediaParticleWidget(QWidget *parent)
    : QWidget(parent)
{
  m_nam = new QNetworkAccessManager(this);
  // To prevent our network request from fetching bytes in memory
  m_nam->setRedirectPolicy(QNetworkRequest::ManualRedirectPolicy);

  auto *layout = new QVBoxLayout(this);
  layout->setContentsMargins(0, 0, 0, 0);
  layout->setSpacing(2);

  m_videoWidget = new QVideoWidget();
  m_videoWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
  layout->addWidget(m_videoWidget);

  m_durationLabel = new QLabel();
  m_durationLabel->setAlignment(Qt::AlignCenter);
  layout->addWidget(m_durationLabel);

  m_player = new QMediaPlayer(this);
  m_audioOutput = new QAudioOutput(this);
  m_player->setAudioOutput(m_audioOutput);
  m_player->setVideoOutput(m_videoWidget);
  m_player->setLoops(QMediaPlayer::Infinite);

  connect(m_player, &QMediaPlayer::durationChanged, this, [this](qint64 duration) {
    if (duration > 0)
    {
      int secs = static_cast<int>(duration / 1000);
      int mins = secs / 60;
      secs = secs % 60;
      m_durationLabel->setText(QString("%1:%2").arg(mins).arg(secs, 2, 10, QChar('0')));
    }
  });
}

void MediaParticleWidget::setParticle(const Particle *particle)
{
  if (!particle) return;
  clear();
  fetchAndPlay(particle->id);
}

void MediaParticleWidget::clear()
{
  m_player->stop();
  m_player->setSource(QUrl());
  m_durationLabel->setText("");
}

void MediaParticleWidget::fetchAndPlay(const QString &particleId)
{
  QNetworkRequest request = NetworkManager::instance().buildRequest("/particles/" + particleId + "/download");
  QNetworkReply *reply = m_nam->get(request);
  connect(reply, &QNetworkReply::finished, this, [this, reply]() {
    reply->deleteLater();

    if (reply->error() != QNetworkReply::NoError)
    {
      qWarning() << "MediaParticleWidget: download request failed:" << reply->errorString();
      return;
    }

    // m_nam uses ManualRedirectPolicy, so the reply stops at the 3xx
    // without downloading the media. Extract the pre-signed URL from Location.
    QUrl mediaUrl = reply->header(QNetworkRequest::LocationHeader).toUrl();
    if (!mediaUrl.isValid())
    {
      qWarning() << "MediaParticleWidget: no Location header in download response";
      return;
    }
    if (mediaUrl.isRelative())
    {
      mediaUrl = reply->url().resolved(mediaUrl);
    }

    m_player->setSource(mediaUrl);
    m_player->play();
  });
}
