/***

  Olive - Non-Linear Video Editor
  Copyright (C) 2022 Olive Team

  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 "subtitleparams.h"

#include <QCoreApplication>

#include "common/xmlutils.h"

namespace olive {

QString SubtitleParams::GenerateASSHeader()
{
  // NOTE: We'll probably implement more customization as we support ASS better. Right now, we only
  //       natively support SRT and only make this header because FFmpeg requires it.
  static const int kAssDefaultPlayResX = 384;
  static const int kAssDefaultPlayResY = 288;
  static const QString kAssDefaultFont = QStringLiteral("Arial");
  static const int kAssDefaultFontSize = 16;
  static const int kAssDefaultPrimaryColor = 0xFFFFFF; // White
  static const int kAssDefaultSecondaryColor = 0xFFFFFF; // White
  static const int kAssDefaultOutlineColor = 0x000000; // Black
  static const int kAssDefaultBackColor = 0x000000; // Black
  static const int kAssBold = 0;
  static const int kAssItalic = 0;
  static const int kAssUnderline = 0;
  static const int kAssStrike = 0;
  static const int kAssBorderStyle = 1;
  static const int kAssAlignment = 2;

  QString ass_code;

  // Header info
  ass_code.append(QStringLiteral("[Script Info]\r\n"));
  ass_code.append(QStringLiteral("; Script generated by %1 %2\r\n").arg(QCoreApplication::applicationName(), QCoreApplication::applicationVersion()));
  ass_code.append(QStringLiteral("ScriptType: v4.00+\r\n"));
  ass_code.append(QStringLiteral("PlayResX: %1\r\n").arg(QString::number(kAssDefaultPlayResX)));
  ass_code.append(QStringLiteral("PlayResY: %1\r\n").arg(QString::number(kAssDefaultPlayResY)));
  ass_code.append(QStringLiteral("ScaledBorderAndShadow: yes\r\n"));
  ass_code.append(QStringLiteral("\r\n"));

  // ASSv4 header
  ass_code.append(QStringLiteral("[V4+ Styles]\r\n"));
  ass_code.append(QStringLiteral("Format: Name, "));
  ass_code.append(QStringLiteral("Fontname, Fontsize, "));
  ass_code.append(QStringLiteral("PrimaryColour, SecondaryColour, OutlineColour, BackColour, "));
  ass_code.append(QStringLiteral("Bold, Italic, Underline, StrikeOut, "));
  ass_code.append(QStringLiteral("ScaleX, ScaleY, "));
  ass_code.append(QStringLiteral("Spacing, Angle, "));
  ass_code.append(QStringLiteral("BorderStyle, Outline, Shadow, "));
  ass_code.append(QStringLiteral("Alignment, MarginL, MarginR, MarginV, "));
  ass_code.append(QStringLiteral("Encoding\r\n"));
  ass_code.append(QStringLiteral("Style: "));

  // Name
  ass_code.append(QStringLiteral("Default,"));

  // Font{name,size}
  ass_code.append(QStringLiteral("%1,%2,").arg(kAssDefaultFont, QString::number(kAssDefaultFontSize)));

  // {Primary,Secondary,Outline,Back}Colour
  ass_code.append(QStringLiteral("&H%1,&H%2,&H%3,&H%4,").arg(QString::number(kAssDefaultPrimaryColor, 16),
                                                             QString::number(kAssDefaultSecondaryColor, 16),
                                                             QString::number(kAssDefaultOutlineColor, 16),
                                                             QString::number(kAssDefaultBackColor, 16)));

  // Bold, Italic, Underline, StrikeOut
  ass_code.append(QStringLiteral("%1,%2,%3,%4,").arg(QString::number(kAssBold),
                                                     QString::number(kAssItalic),
                                                     QString::number(kAssUnderline),
                                                     QString::number(kAssStrike)));

  // Scale{X,Y}
  ass_code.append(QStringLiteral("100,100,"));

  // Spacing, Angle
  ass_code.append(QStringLiteral("0,0,"));

  // BorderStyle, Outline, Shadow
  ass_code.append(QStringLiteral("%1,1,0,").arg(QString::number(kAssBorderStyle)));

  // Alignment, Margin[LRV]
  ass_code.append(QStringLiteral("%1,10,10,10,").arg(QString::number(kAssAlignment)));

  // Encoding
  ass_code.append(QStringLiteral("0\r\n"));
  ass_code.append(QStringLiteral("\r\n"));
  ass_code.append(QStringLiteral("[Events]\r\n"));
  ass_code.append(QStringLiteral("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\r\n"));

  return ass_code;
}

void SubtitleParams::Load(QXmlStreamReader *reader)
{
  this->clear();

  while (XMLReadNextStartElement(reader)) {
    if (reader->name() == QStringLiteral("streamindex")) {
      set_stream_index(reader->readElementText().toInt());
    } else if (reader->name() == QStringLiteral("enabled")) {
      set_enabled(reader->readElementText().toInt());
    } else if (reader->name() == QStringLiteral("subtitles")) {
      while (XMLReadNextStartElement(reader)) {
        if (reader->name() == QStringLiteral("subtitle")) {
          rational in, out;
          QString text;

          XMLAttributeLoop(reader, attr) {
            if (attr.name() == QStringLiteral("in")) {
              in = rational::fromString(attr.value().toString());
            } else if (attr.name() == QStringLiteral("out")) {
              out = rational::fromString(attr.value().toString());
            }
          }

          text = reader->readElementText();

          this->push_back(Subtitle(TimeRange(in, out), text));
        } else {
          reader->skipCurrentElement();
        }
      }
    } else {
      reader->skipCurrentElement();
    }
  }
}

void SubtitleParams::Save(QXmlStreamWriter *writer) const
{
  writer->writeTextElement(QStringLiteral("streamindex"), QString::number(stream_index_));
  writer->writeTextElement(QStringLiteral("enabled"), QString::number(enabled_));

  writer->writeStartElement(QStringLiteral("subtitles"));
  for (auto it=this->cbegin(); it!=this->cend(); it++) {
    writer->writeStartElement(QStringLiteral("subtitle"));
    writer->writeAttribute(QStringLiteral("in"), it->time().in().toString());
    writer->writeAttribute(QStringLiteral("out"), it->time().out().toString());
    writer->writeCharacters(it->text());
    writer->writeEndElement(); // subtitle
  }
  writer->writeEndElement(); // subtitles
}

}
