/*
    libodsstream is a library to read and write ODS documents as streams
    Copyright (C) 2013  Olivier Langella <Olivier.Langella@moulon.inra.fr>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "odsdocreader.h"
#include "odsexception.h"
#include <QDebug>
#include <QFileInfo>
#include "saxreader/qxmlstreamreadercontentxml.h"
//#include "./saxreader/saxhandlercontentxml.h"
#include <quazipfile.h>

OdsDocReader::OdsDocReader(OdsDocHandlerInterface &handler) : _handler(handler)
{
}

OdsDocReader::~OdsDocReader()
{
  qDebug();
  if(_p_quaZip != nullptr)
    {
      if(_p_quaZip->isOpen())
        {
          _p_quaZip->close();
          delete _p_quaZip;
          _p_quaZip = nullptr;
        }
    }
  qDebug();
}


void
OdsDocReader::parse(QFile &odsFile)
{
  qDebug() << odsFile.fileName();
  QFileInfo ods_file_info(odsFile.fileName());
  if(!ods_file_info.exists())
    {
      throw OdsException(QObject::tr("ODS file %1 does not exists")
                           .arg(ods_file_info.absoluteFilePath()));
    }
  if(!ods_file_info.isReadable())
    {
      throw OdsException(QObject::tr("ODS file %1 is not readable")
                           .arg(ods_file_info.absoluteFilePath()));
    }
  if(!odsFile.open(QIODevice::ReadOnly))
    {
      throw OdsException(QObject::tr("Unable to read ODS file %1")
                           .arg(ods_file_info.absoluteFilePath()));
    }
  qDebug() << ods_file_info.absoluteFilePath();
  parse(&odsFile);
  odsFile.close();
}

void
OdsDocReader::parse(QIODevice *p_inputstream)
{
  qDebug();
  _p_quaZip = new QuaZip(p_inputstream);
  _p_quaZip->open(QuaZip::mdUnzip);

  qDebug();
  for(bool more = _p_quaZip->goToFirstFile(); more;
      more      = _p_quaZip->goToNextFile())
    {
      qDebug() << _p_quaZip->getCurrentFileName();

      if(_p_quaZip->getCurrentFileName() == "content.xml")
        {


          QuaZipFile zip_file(_p_quaZip);
          QXmlStreamReaderContentXml content_reader(*this);
          zip_file.open(QIODevice::ReadOnly);
          content_reader.setDevice(&zip_file);
          content_reader.setNamespaceProcessing(true);
          content_reader.read();
          if(content_reader.error())
            {

              zip_file.close();
              qDebug() << " error " << content_reader.errorString();
              throw OdsException(QObject::tr("error reading ODS input file :\n")
                                   .append(content_reader.errorString()));
            }
          qDebug() << " contentXml : DONE on file '"
                   << _p_quaZip->getCurrentFileName() << "'";

          zip_file.close();
        }
    }
  if(_p_quaZip != nullptr)
    {
      if(_p_quaZip->isOpen())
        {
          _p_quaZip->close();
          delete _p_quaZip;
          _p_quaZip = nullptr;
        }
    }
  this->endDocument();
}

void
OdsDocReader::startInsideLine()
{
  _column_number = 0;
  startLine();
}

void
OdsDocReader::setInsideCell(const OdsCell &cell)
{
  _column_number++;
  qDebug() << cell.getOfficeValueType() << " " << cell.toString();
  if(cell.isDate())
    {
      qDebug() << " date " << cell.getDateTimeValue().toString(Qt::ISODate)
               << "  " << cell.getDateTimeValue().date().day() << "  "
               << cell.getDateTimeValue().date().month();
    }
  else if(cell.isString())
    {
      qDebug() << " string " << cell.getStringValue();
    }
  else if(cell.isDouble())
    {
      qDebug() << " double " << cell.getDoubleValue();
    }
  setCell(cell);
}


void
OdsDocReader::startSheet(const QString &sheet_name)
{
  _handler.startSheet(sheet_name);
}

void
OdsDocReader::endSheet()
{
  _handler.endSheet();
}

void
OdsDocReader::startLine()
{
  _handler.startLine();
}

void
OdsDocReader::endLine()
{
  _handler.endLine();
}

void
OdsDocReader::setCell(const OdsCell &cell)
{
  _handler.setCell(cell);
}
void
OdsDocReader::endDocument()
{
  _handler.endDocument();
}
