/****************************************************************************
** importkino.cpp
**
** This file holds the implementation of the import filter for the kino 
** generated smil file format.
*****************************************************************************/

#include <qdom.h>
#include <qfileinfo.h>
#include <qfiledialog.h>

#include "global.h"
#include "qdvdauthor.h"
#include "importkino.h"
#include "messagebox.h"
#include "sourcefileentry.h"

namespace Import
{

CXmlKino::CXmlKino ()
{
}

CXmlKino::~CXmlKino ()
{
}

bool CXmlKino::readXml ( QString &fileName )
{
  // Assign the file
  QFile projectFile ( fileName );
  if (!projectFile.open ( IO_Raw | IO_ReadWrite ) )
    return false;
  
  QDomDocument xmlDoc;
  if (!xmlDoc.setContent ( &projectFile ) )	{
    // Error handling ...
    projectFile.close();
    MessageBox::warning ( NULL, QObject::tr ("xml smil file seems to be defective."),
			   QObject::tr ("Please choose another file ?"),
			   QMessageBox::Ok, QMessageBox::NoButton);
    return false;
  }
  // And at last lets try to read the information of the file.
  QDomElement docElem = xmlDoc.documentElement ( );
  bool bReturn = m_smil.readXml ( &docElem );
  
  projectFile.close();
  return bReturn;
}

CXmlKino::smil_struct::smil_struct ()
{
  ppArraySeq = NULL;
}

CXmlKino::smil_struct::~smil_struct ()
{
  int iCounter = 0;
  seq_struct *pSeq;
  if ( ppArraySeq ) {
    pSeq = ppArraySeq[ iCounter ++ ];
    while ( pSeq ) {
      delete pSeq;
      pSeq = ppArraySeq[ iCounter ++ ];
    }
    delete []ppArraySeq;
  }
}

bool CXmlKino::smil_struct::readXml ( QDomElement *pDocElem )
{
  bool bReturn = false;
  if ( pDocElem->tagName () != SMIL_SMIL )
    return false;
  QDomNode xmlNode = pDocElem->firstChild ();

  // get the video - tag first ...
  while ( !xmlNode.isNull() ) {
    QDomElement searchTree = xmlNode.toElement ();
    seq_struct *pSeq = addSeq ();
    if ( searchTree.tagName () == SMIL_SEQ )
      bReturn = pSeq->readXml ( &searchTree );
    if ( ! bReturn ) 
      return false;
    // go to the next node ...
    xmlNode = xmlNode.nextSibling ();
  }

  return true;
}

CXmlKino::seq_struct *CXmlKino::smil_struct::addSeq ()
{
  // This function simply enlarges the array of available titlesets.
  // That'll keep the structure dynamic.
  if (!ppArraySeq)	{
    // This is the first ...
    ppArraySeq=new seq_struct *[2];
    ppArraySeq[0]=new seq_struct;
    ppArraySeq[1]=NULL;
    return ppArraySeq[0];
  }

  int i,t=0;
  seq_struct  *pSeq = ppArraySeq[t];
  seq_struct **ppNewArray=NULL, **ppOldArray=NULL;
  while (pSeq) 
    pSeq = ppArraySeq[++t];

  // Now we have the count of actual titlesets.
  ppNewArray=new seq_struct *[t+2];
  for (i=0;i<t;i++) 
    ppNewArray[i]=ppArraySeq[i];
  
  ppNewArray[i] = new seq_struct();
  ppNewArray[i+1] = NULL;
  // Now we can delete th old array (but not the contents.
  ppOldArray = ppArraySeq;
  ppArraySeq = ppNewArray;
  delete []ppOldArray;
  // And finally return the latest addition ...
  return ppArraySeq[i];
}

CXmlKino::seq_struct::seq_struct ()
{
  clipBegin  = 0;
  clipEnd    = 0;
}

bool CXmlKino::seq_struct::readXml ( QDomElement *pDocElem )
{
  if ( pDocElem->tagName () != SMIL_SEQ )
    return false;

  QDomNode xmlNode = pDocElem->firstChild ();
  while ( !xmlNode.isNull() ) {
    QDomElement searchTree = xmlNode.toElement ();
    if ( searchTree.tagName () == SMIL_VIDEO ) {
      // So lets get first the attributes for this node.
      QDomAttr a = searchTree.attributeNode ( ATTRIB_SRC );
      src = a.value();
      a = searchTree.attributeNode ( ATTRIB_CLIPBEGIN );
      clipBegin = a.value().toLong ();
      a = searchTree.attributeNode ( ATTRIB_CLIPEND );
      clipEnd = a.value().toLong ();

      a = searchTree.attributeNode ( ATTRIB_TITLE );
      title = a.value();
      a = searchTree.attributeNode ( ATTRIB_AUTHOR );
      author = a.value();
      a = searchTree.attributeNode ( ATTRIB_ABSTRACT );
      abstract = a.value();
      a = searchTree.attributeNode ( ATTRIB_ID );
      id = a.value().toInt ();
      a = searchTree.attributeNode ( ATTRIB_COPYRIGHT );
      copyright = a.value();
    }
    // go to the next node ...
    xmlNode = xmlNode.nextSibling ();
  }
  return true;
}


Kino::Kino ( QDVDAuthor *pDVDAuthor )
{
  m_pDVDAuthor = pDVDAuthor;
  m_pEntry     = NULL;
}

Kino::~Kino ()
{
}

/**
 * import will open a QFileDialog for selecting the kino xml file.
 *
 */
bool Kino::import ()
{
  QString fileName = QFileDialog::getOpenFileName ( Global::qsCurrentPath, QObject::tr ("Kinos smil files ( *.kino *.KINO *.xml *.XML *_smil *_SMIL *.smil *.SMIL )"));
  return import ( fileName );
}

bool Kino::import ( QString fileName )
{
  CXmlKino theXmlStructure;
  bool          bSuccess;
  QFileInfo     theFile;

  // Read in the dvdauthor file.
  bSuccess = theXmlStructure.readXml ( fileName );

  if ( ! bSuccess )
    return false;
  
  theFile.setFile ( fileName );
  Global::qsCurrentPath = theFile.dirPath();

  return buildFromKinoXML ( &theXmlStructure );
}

/////////////////////////////////////////////////////////////
//
// Private member functions.
//
////////////////////////////////////////////////////////////
bool Kino::buildFromKinoXML ( CXmlKino *pXMLKino )
{
  if ( ! pXMLKino->m_smil.ppArraySeq )
    return true;
  
  SourceFileEntry *pEntry = new SourceFileEntry;
  SourceFileInfo  *pInfo  = NULL;
  
  int iCounter = 0;
  CXmlKino::seq_struct *pSeq = pXMLKino->m_smil.ppArraySeq[ iCounter ++ ];

  while ( pSeq ) {
    pInfo = new SourceFileInfo;
    pInfo->qsFileName = pSeq->src;

    pEntry->listFileInfos.append ( pInfo );
    pSeq = pXMLKino->m_smil.ppArraySeq[ iCounter ++ ];
  }
  pEntry->qsDisplayName.sprintf ("[%02d] - kino-smil <%02d - files>", 
				 (int)m_pDVDAuthor->getFreeSourceSlot (), 
				 (int)pEntry->listFileInfos.count());
  m_pEntry = pEntry;
  return true;
}

SourceFileEntry *Kino::getEntry ()
{
  return m_pEntry;
}

}; // End of namespace Import
