/*
    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 <QFileInfo>
#include <QDebug>
#include "tsvdirectorywriter.h"
#include "odsexception.h"


TsvDirectoryWriter::TsvDirectoryWriter()
{
}

TsvDirectoryWriter::TsvDirectoryWriter(const QDir &directory)
  : _directory(directory)
{
  if(_directory.exists())
    {
    }
  else
    {
      if(!_directory.mkdir(_directory.absolutePath()))
        {
          throw OdsException(QString("unable to create output directory %1")
                               .arg(_directory.absolutePath()));
        }
    }
}

TsvDirectoryWriter::~TsvDirectoryWriter()
{
  close();
}

void
TsvDirectoryWriter::setSeparator(TsvSeparator separator)
{
  qDebug();
  m_tsvSeparatorEnum = separator;
  switch(separator)
    {
      case TsvSeparator::tab:
        m_separator = "\t";
        break;
      case TsvSeparator::comma:
        m_separator = ",";
        break;
      case TsvSeparator::semicolon:
        m_separator = ";";
        break;
    }
  qDebug();
}

void
TsvDirectoryWriter::close()
{
  if(mpa_otxtstream != nullptr)
    {
      *mpa_otxtstream << _end_of_line;
      mpa_otxtstream->flush();
      //_p_otxtstream->close();
      delete(mpa_otxtstream);
      mpa_otxtstream = nullptr;
    }
  if(mpa_ofile != nullptr)
    {
      mpa_ofile->flush();
      mpa_ofile->close();
      delete(mpa_ofile);
      mpa_ofile = nullptr;
    }
}

void
TsvDirectoryWriter::writeSheet(const QString &sheetName)
{
  close();
  // qDebug() << " TsvDirectoryWriter::writeSheet " <<
  // _directory.absolutePath();
  mpa_ofile = new QFile(QString(_directory.absolutePath())
                          .append("/")
                          .append(sheetName)
                          .append(this->_file_extension));
  // qDebug() << " TsvDirectoryWriter::writeSheet " <<
  // QFileInfo(*_p_ofile).absoluteFilePath();
  if(mpa_ofile->open(QIODevice::WriteOnly))
    {
      mpa_otxtstream = new QTextStream(mpa_ofile);
    }
  else
    {
      throw OdsException(QString("unable to write into file %1")
                           .arg(QFileInfo(*mpa_ofile).absoluteFilePath()));
    }
  initializeSheet();
}

void
TsvDirectoryWriter::initializeSheet()
{

  _tableRowStart = true;
  _startingSheet = true;
}


void
TsvDirectoryWriter::ensureSheet()
{
  if(mpa_otxtstream == nullptr)
    {
      writeSheet("default");
    }
}

void
TsvDirectoryWriter::writeLine()
{
  ensureSheet();
  if(_startingSheet)
    {
    }
  else
    {
      *mpa_otxtstream << _end_of_line;
    }
  _startingSheet = false;
  _tableRowStart = true;

  if(m_flushLines)
    mpa_otxtstream->flush();
}
void
TsvDirectoryWriter::writeCell(const char *cstr)
{
  writeCell(QString(cstr));
}
void
TsvDirectoryWriter::writeCell(const QString &text)
{
  ensureSheet();
  if(!_tableRowStart)
    {
      *mpa_otxtstream << m_separator;
    }
  _tableRowStart = false;

  if(m_quoteStrings)
    {
      *mpa_otxtstream << QString("\"%1\"").arg(
        QString(text).replace("\"", "\"\""));
    }
  else
    {
      if(text.contains(_end_of_line) || text.contains(m_separator) ||
         text.contains("\""))
        {
          *mpa_otxtstream << QString("\"%1\"").arg(
            QString(text).replace("\"", "\"\""));
        }
      else
        {
          *mpa_otxtstream << text;
        }
    }

  _startingSheet = false;
}

void
TsvDirectoryWriter::writeRawCell(const QString &text)
{
  ensureSheet();
  if(!_tableRowStart)
    {
      *mpa_otxtstream << m_separator;
    }
  _tableRowStart = false;
  *mpa_otxtstream << text;
  _startingSheet = false;
}
void
TsvDirectoryWriter::writeEmptyCell()
{
  ensureSheet();
  if(!_tableRowStart)
    {
      *mpa_otxtstream << m_separator;
    }
  _tableRowStart = false;
  _startingSheet = false;
}
void
TsvDirectoryWriter::writeCell(std::size_t num)
{
  writeRawCell(QString::number(num, 'g', 10));
}
void
TsvDirectoryWriter::writeCell(int num)
{
  writeRawCell(QString::number(num, 'g', 10));
}
void
TsvDirectoryWriter::writeCell(float num)
{
  writeRawCell(QString::number(num, 'g', numFloatPrecision));
}
void
TsvDirectoryWriter::writeCell(double num)
{
  writeRawCell(QString::number(num, 'g', numFloatPrecision));
}

void
TsvDirectoryWriter::writeCellPercentage(double value)
{
  writeCell(value);
}
void
TsvDirectoryWriter::writeCell(bool isOk)
{
  if(isOk)
    {
      writeRawCell(QString("T"));
    }
  else
    {
      writeRawCell(QString("F"));
    }
}
void
TsvDirectoryWriter::writeCell(const QDate &date)
{
  writeRawCell(date.toString("yyyy-MM-dd"));
}
void
TsvDirectoryWriter::writeCell(const QDateTime &date)
{
  writeRawCell(date.toString("yyyy-MM-ddThh:mm:ss"));
}
void
TsvDirectoryWriter::writeCell([[maybe_unused]] const QUrl &url,
                              const QString &text)
{
  writeCell(text);
}


bool
TsvDirectoryWriter::setQuoteStrings(bool quote_strings)
{
  m_quoteStrings = quote_strings;
  return m_quoteStrings;
}

bool
TsvDirectoryWriter::isQuoteStrings() const
{
  return m_quoteStrings;
}

bool
TsvDirectoryWriter::isFlushLines() const
{
  return m_flushLines;
}

bool
TsvDirectoryWriter::setFlushLines(bool flushOk)
{
  m_flushLines = flushOk;
  return m_flushLines;
}

TsvSeparator
TsvDirectoryWriter::getSeparator() const
{
  return m_tsvSeparatorEnum;
}
