//==============================================
//  copyright            : (C) 2003-2005 by Will Stokes
//==============================================
//  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 of the License, or
//  (at your option) any later version.
//==============================================

//Systemwide includes
#include <qstring.h>
#include <qdir.h>
#include <qfile.h>
#include <qdragobject.h>

#include <iostream>
#include <string>
#include <libxml/xmlmemory.h>
#include <libxml/debugXML.h>
#include <libxml/HTMLtree.h>
#include <libxml/xmlIO.h>
#include <libxml/xinclude.h>
#include <libxml/catalog.h>
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#include <stdio.h>

//Projectwide includes
#include "xmlTools.h"
#include "../../config.h"

//==============================================
QString fixXMLString( QString text )
{
  //the following checks are necessary before exporting
  //strings to XML. see http://hdf.ncsa.uiuc.edu/HDF5/XML/xml_escape_chars.html for details
  text.replace("&", "&amp;");
  text.replace("\"","&quot;");
  text.replace("'", "&apos;");
  text.replace("<", "&lt;");
  text.replace(">", "&gt;");
  text.replace("\n", "&#10;");
  text.replace("\r", "&#13;");
  return text;
}
//==============================================
void transformXMLtoHTML( QString outputPath, QString theme, bool smallWebExport)
{
  xmlSubstituteEntitiesDefault(1);
  xmlLoadExtDtdDefaultValue = 1;
  xsltStylesheetPtr cur = xsltParseStylesheetFile( (const xmlChar *) QString(THEMES_PATH + theme + "/theme.xsl").ascii() );

  QString xmlFile = QString(outputPath + "/Album.xml");
  xmlDocPtr doc = xmlParseFile( QFile::encodeName(xmlFile) ); 
  
  const char* params[5];
  //--
  params[0] = "outputPath";
  QString quotedPath = outputPath;

  //For some reason libxslt has trouble handling filenames with spaces on Unix platforms (OSX,
  //Linux, FreeBSD?). this problem can be averted by converting the filename to a URI. Converting it
  //to a URI on windows using the qt method mangles the drive name though, so only convert to
  //URI on OSX. We need to nail this weirdness at some point and be consistant IMHO but for now
  //this works...
#ifndef Q_OS_WIN
  quotedPath = QUriDrag::localFileToUri( quotedPath );  
#endif
  
  params[1] = quotedPath.prepend('\"').append('\"').ascii();
  //--
  params[2] = "smallWebExport";
  if(smallWebExport)
    params[3] = "1";
  else
    params[3] = "0";
  //--
  params[4] = NULL;
  xmlDocPtr res = xsltApplyStylesheet( cur, doc, params);
  xsltFreeStylesheet( cur );
  xmlFreeDoc( res );
  xmlFreeDoc( doc );
  xsltCleanupGlobals();
  xmlCleanupParser();
}
//==============================================
void updateXML( QString inputPath )
{
  //skip updating the xml file if we can't find the update.xsl file
  QDir tmpDir;
  if( !tmpDir.exists( XMLCONVERSION_PATH + "update.xsl" ) )
  {
    std::cout << "Can't find update.xsl! Skipping auto-update!\n";
    return;
  }
  
  xmlSubstituteEntitiesDefault(1);
  xmlLoadExtDtdDefaultValue = 1;

  xsltStylesheetPtr stylesheet;
  xmlDocPtr inputDoc, outputDoc;

  stylesheet = xsltParseStylesheetFile( (const xmlChar *) QString(XMLCONVERSION_PATH + "update.xsl").ascii() );

  QString xmlFile = QString( inputPath + "/Album.xml" );
  xmlFile = QDir::convertSeparators( xmlFile );
  inputDoc = xmlParseFile( QFile::encodeName(xmlFile) ); 

  const char* params[3];
  params[0] = "outputPath";

  QString quotedPath = inputPath;

  //For some reason libxslt has trouble handling filenames with spaces on Unix platforms (OSX,
  //Linux, FreeBSD?). this problem can be averted by converting the filename to a URI. Converting it
  //to a URI on windows using the qt method mangles the drive name though, so only convert to
  //URI on OSX. We need to nail this weirdness at some point and be consistant IMHO but for now
  //this works...
  #ifndef Q_OS_WIN
  quotedPath = QUriDrag::localFileToUri( quotedPath );  
  #endif


  params[1] = quotedPath.prepend('\"').append('\"').ascii();

  params[2] = NULL;

  std::cout.flush();

  //iterate until Album.updated file is created
  QDir workingDir( inputPath );

  int iterations = 0;
  while(true)
  {
    iterations++;

    //apply the stylesheet
    outputDoc = xsltApplyStylesheet( stylesheet, inputDoc, params );

    //if Album.updated file now exists we have already completed the last iteration,
    //meaning the input document is the most up-to-date so break out of loop
    if(workingDir.exists( "Album.updated" ))
      break;

    //free input  doc
    xmlFreeDoc( inputDoc );

    //swap input and output
    inputDoc = outputDoc;
  }

  //remove updated file
  workingDir.remove( inputPath + "/Album.updated" );

  //if we made more than one iteration then changes were applied
  if(iterations > 1)
  {
    //output updated xml file
    FILE* outfile = fopen( QFile::encodeName(xmlFile), "w" );
    xsltSaveResultToFile( outfile, inputDoc, stylesheet);
    fclose( outfile );
  }

  //memory
  xsltFreeStylesheet( stylesheet );
  xmlFreeDoc( inputDoc );
  xmlFreeDoc( outputDoc );
  xsltCleanupGlobals();
  xmlCleanupParser();
}
//==============================================


