
/****************************************************************************
** exportssa.cpp
**
**   Created : 
**        by : Varol Okan 
** Copyright : (c) Varol Okan
**   License : GPL v 2.0
**
** This file holds the implementation of the export filter for the srt 
** subtitles file.
*****************************************************************************/

#include <qregexp.h>
#include <qfiledialog.h>

#include "global.h"
#include "sourcefileentry.h"
#include "exportssa.h"

namespace Export
{

Ssa::Ssa ( )
{
  m_pSubtitles = NULL;
}

Ssa::~Ssa ( )
{
}

bool Ssa::exportSub ( Subtitles *pSubtitles )
{
  QString qsExportFile = QFileDialog::getSaveFileName ( Global::qsCurrentPath, QObject::tr("Subtitle files (*.srt *.SRT)"), NULL, QObject::tr("Save Subtitles File") );

  // Sanity check .. Did te user choose a new project file ?
  if (qsExportFile.isNull ())
    return true;

  return writeFile ( pSubtitles, qsExportFile );
}

bool Ssa::writeFile ( Subtitles *pSubtitles, QString &fileName )
{
  if ( ! pSubtitles )
    return false;

  // Assign the file
  QString qsTimeStart, qsTimeStop;
  QFile projectFile ( fileName );

  if ( ! projectFile.open ( IO_WriteOnly ) )
    return false;

  m_pSubtitles = pSubtitles;
  QTextStream ssaStream ( &projectFile );

  writeScriptInfo ( ssaStream );
  writeStyles     ( ssaStream );
  writeEvents     ( ssaStream );

  projectFile.flush ( );
  projectFile.close ( );

  return true;
}

void Ssa::writeScriptInfo ( QTextStream &stream )
{
  QFileInfo fileInfo  ( m_pSubtitles->m_qsTempFile );
  int iWidth  = m_pSubtitles->m_videoSize.width  ( );
  int iHeight = m_pSubtitles->m_videoSize.height ( );
  if ( iWidth < 100 )
       iWidth = 480;
  if ( iHeight< 100 )
       iHeight= 720;

  stream << "[Script Info]\n";
  stream << "; Create with QDVDAuthor.\n";
  stream << "; HomePage : http://QDVDAuthor.sf.net\n";
  stream << "; SSA info : http://en.wikipedia.org/wiki/SubStation_Alpha\n";
  stream << "Title: " << fileInfo.baseName ( TRUE ) << "\n";
  stream << "Original Script: \n";
  stream << "ScriptType: v4.00+\n";
  stream << "Collisions: Normal\n";
  stream << "PlayResX: " << iWidth  << "\n";
  stream << "PlayResY: " << iHeight << "\n";
  stream << "PlayDepth: 0\n";
  stream << "Timer: 100,0000\n\n";
}

void Ssa::writeStyles ( QTextStream &stream )
{
  QString qsFontName       = m_pSubtitles->m_font.family    ( );
  int     iPointSize       = m_pSubtitles->m_font.pointSize ( );
  QString qsPrimaryColor   = toAbgr ( m_pSubtitles->m_subColors[0] );
  QString qsSecondaryColor = toAbgr ( m_pSubtitles->m_subColors[1] );
  QString qsOutlineColor   = toAbgr ( m_pSubtitles->m_subColors[2] );
  QString qsBackColor      = toAbgr ( m_pSubtitles->m_subColors[3] );

  int iBold       = m_pSubtitles->m_font.bold      ( ) ? -1 : 0;
  int iItalic     = m_pSubtitles->m_font.italic    ( ) ? -1 : 0;
  int iUnderline  = m_pSubtitles->m_font.underline ( ) ? -1 : 0;
  int iStrikeout  = m_pSubtitles->m_font.strikeOut ( ) ? -1 : 0;

  stream << "[V4+ Styles]\n";
  stream << "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding\n";
  stream << "Style: Default," << qsFontName << "," << iPointSize << ",";
  stream << qsPrimaryColor << "," << qsSecondaryColor << "," << qsOutlineColor << "," << qsBackColor << ",";
  stream << iBold << "," << iItalic << "," << iUnderline << "," << iStrikeout << ",";
  stream << "100,100,0,0,1,0,2,2,20,20,40,0\n\n";
// Style: Default,Bitstream Vera Sans,26,&H00FFFFFF,&H0000FFFF,&H4B000000,&H4B404040,0,0,0,0,100,100,0,0,1,0,2,2,20,20,40,0

}

QString Ssa::toAbgr ( Rgba &color )
{
  QString qsColor;
  qsColor = QString ( "&H%1%2%3%4" ).arg ( color.alpha ( ), 2, 16 ).arg ( color.blue ( ), 2, 16 ).arg ( color.green ( ), 2, 16 ).arg ( color.red ( ), 2, 16 );
  qsColor = qsColor.upper   ( );
  qsColor = qsColor.replace ( " ", "0" );

  return qsColor;
}

void Ssa::writeEvents ( QTextStream &stream )
{
  const int PATTERNS=9;
  Subtitles::entry *pEntry = NULL;
  QString qsText, qsFont, qsTemp, rp[PATTERNS];
  QString qsTimeStart,  qsTimeStop;
  QRegExp rx[PATTERNS], rxFont, rxSize, rxFace;
  int t, iPos;

  rxFont.setPattern ( "<(font|FONT)\\b.*>" );
  rxSize.setPattern ( "size=\"\\d*\"" );
  rxFace.setPattern ( "face=\"\\d*\"" );

  rx[0].setPattern (   "<(br|BR)>" );
  rx[1].setPattern ( "<(p|P|\\r)>" );
  rx[2].setPattern (     "<(i|I)>" );
  rx[3].setPattern (    "</(i|I)>" );
  rx[4].setPattern (     "<(u|U)>" );
  rx[5].setPattern (    "</(u|U)>" );
  rx[6].setPattern (     "<(s|S)>" );
  rx[7].setPattern (    "</(s|S)>" );
  rx[8].setPattern ( "</(font|FONT)>" );

  rp[0] = "\\n";
  rp[1] = "\\n";
  rp[2] = "\\i1";
  rp[3] = "\\i0";
  rp[4] = "\\u1";
  rp[5] = "\\u0";
  rp[6] = "\\s1";
  rp[7] = "\\s0";
  rp[8] = "\\rfn\\rfs";

  // Finally we want to replace all occurences.
  for ( t=0; t<PATTERNS; t++ )
    rx[t].setMinimal ( FALSE );

  stream << "[Events]\n";
  stream << "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n";
// Dialogue: 0,0:00:40.14,0:00:43.50,Default,,0000,0000,0000,,because in Paris, you see,\nyou got to play cool jazz
  QValueList<Subtitles::entry *>::iterator it = m_pSubtitles->m_listOfSubtitles.begin ( );
  while ( it != m_pSubtitles->m_listOfSubtitles.end ( ) )  {
    pEntry = *it++;
    qsText = pEntry->qsText;
    for ( t=0; t<PATTERNS; t++ )
      qsText.replace ( rx[t], rp[t] );

    iPos = 0;
    while ( iPos > 0 )  {
      iPos   = rxFont.search ( qsText, iPos );
      if ( iPos > -1 )  {
        qsTemp = rxFont.cap ( 1 );

        // Extract info from the font - tag
        qsFont = "";
        qsTemp = qsTemp.lower ( );
        if ( rxSize.search ( qsTemp  ) > -1 )
          qsFont += "\\fs" + rxSize.cap ( 1 ) + " ";
        if ( rxFace.search ( qsTemp  ) > -1 )
          qsFont += "\\fn" + rxFace.cap ( 1 ) + " ";

        // Replace the font tag with the found parameters
        qsText.replace ( iPos, rxFont.matchedLength ( ), qsFont );
        iPos  += rxFont.matchedLength ( );
      }
    }
    qsTimeStart = pEntry->qsTimeStart.mid ( 1, pEntry->qsTimeStart.length ( ) - 2 );
    qsTimeStop  = pEntry->qsTimeStop. mid ( 1, pEntry->qsTimeStop. length ( ) - 2 );

    stream << "Dialoggue: 0," << qsTimeStart << "," << qsTimeStop << ",";
    stream << "Default,,0000,0000,0000,," << qsText << "\n";
  }
}

}; // End of namespace Export
