/* poppler-media.cc: qt interface to poppler
 * Copyright (C) 2012 Guillermo A. Amaral B. <gamaral@kde.org>
 * Copyright (C) 2013, 2018 Albert Astals Cid <aacid@kde.org>
 *
 * 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 2, 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "poppler-media.h"

#include "Rendition.h"

#include "poppler-private.h"

#include <QtCore/QBuffer>

#define BUFFER_MAX 4096

namespace Poppler
{

class MediaRenditionPrivate
{
public:

  MediaRenditionPrivate(::MediaRendition *renditionA)
  : rendition(renditionA)
  {
  }
  
  ~MediaRenditionPrivate()
  {
    delete rendition;
  }

  MediaRenditionPrivate(const MediaRenditionPrivate &) = delete;
  MediaRenditionPrivate& operator=(const MediaRenditionPrivate &) = delete;

  ::MediaRendition *rendition;
};

MediaRendition::MediaRendition(::MediaRendition *rendition)
  : d_ptr(new MediaRenditionPrivate(rendition))
{
}

MediaRendition::~MediaRendition()
{
  delete d_ptr;
}

bool
MediaRendition::isValid() const
{
  Q_D( const MediaRendition );
  return d->rendition && d->rendition->isOk();
}

QString
MediaRendition::contentType() const
{
  Q_ASSERT(isValid() && "Invalid media rendition.");
  Q_D( const MediaRendition );
  return UnicodeParsedString(d->rendition->getContentType());
}

QString
MediaRendition::fileName() const
{
  Q_ASSERT(isValid() && "Invalid media rendition.");
  Q_D( const MediaRendition );
  return UnicodeParsedString(d->rendition->getFileName());
}

bool
MediaRendition::isEmbedded() const
{
  Q_ASSERT(isValid() && "Invalid media rendition.");
  Q_D( const MediaRendition );
  return d->rendition->getIsEmbedded();
}

QByteArray
MediaRendition::data() const
{
  Q_ASSERT(isValid() && "Invalid media rendition.");
  Q_D( const MediaRendition );

  Stream *s = d->rendition->getEmbbededStream();
  if (!s)
    return QByteArray();

  QBuffer buffer;
  unsigned char data[BUFFER_MAX];
  int bread;

  buffer.open(QIODevice::WriteOnly);
  s->reset();
  while ((bread = s->doGetChars(BUFFER_MAX, data)) != 0)
    buffer.write(reinterpret_cast<const char *>(data), bread);
  buffer.close();

  return buffer.data();
}

bool
MediaRendition::autoPlay() const
{
  Q_D( const MediaRendition );
  if (d->rendition->getBEParameters()) {
    return d->rendition->getBEParameters()->autoPlay;
  } else if (d->rendition->getMHParameters()) {
    return d->rendition->getMHParameters()->autoPlay;
  } else qDebug("No BE or MH parameters to reference!");
  return false;
}

bool
MediaRendition::showControls() const
{
  Q_D( const MediaRendition );
  if (d->rendition->getBEParameters()) {
    return d->rendition->getBEParameters()->showControls;
  } else if (d->rendition->getMHParameters()) {
    return d->rendition->getMHParameters()->showControls;
  } else qDebug("No BE or MH parameters to reference!");
  return false;
}

float
MediaRendition::repeatCount() const
{
  Q_D( const MediaRendition );
  if (d->rendition->getBEParameters()) {
    return d->rendition->getBEParameters()->repeatCount;
  } else if (d->rendition->getMHParameters()) {
    return d->rendition->getMHParameters()->repeatCount;
  } else qDebug("No BE or MH parameters to reference!");
  return 1.f;
}

QSize
MediaRendition::size() const
{
  Q_D( const MediaRendition );
  const MediaParameters *mp = nullptr;

  if (d->rendition->getBEParameters())
    mp = d->rendition->getBEParameters();
  else if (d->rendition->getMHParameters())
    mp = d->rendition->getMHParameters();
  else qDebug("No BE or MH parameters to reference!");

  if (mp)
    return QSize(mp->windowParams.width, mp->windowParams.height);
  return QSize();
}

}

