/***************************************************************************
                          SqlOutputText.cpp  -  description
                             -------------------
    begin                : Fre Mär 8 2002
    copyright            : (C) 2002 by Harald Fernengel
    email                : harry@kdevelop.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <qsqldatabase.h>
#include <qsqlerror.h>
#include <qstringlist.h>
#include <qsqlrecord.h>
#include <qsqldriver.h>
#include <qregexp.h>

#include "sqloutputtext.h"


SqlOutputText::SqlOutputText( const KURL& u, QSqlDatabase* sdb ): SqlOutputIface( u, sdb )
{
  db = sdb;
}

SqlOutputText::~SqlOutputText()
{
}

QString SqlOutputText::showTables()
{
  if ( !db ) {
    error( cannotOpenDatabase() );
    return QString::null;
  }

  QString out;
  QStringList list = db->tables();
  if ( list.count() > 0 ) {
    out += i18n( "Available tables:" ) + "\n\n";
    for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
      out += *it + "\n";
    }
  } else {
    out += i18n( "No tables found" ) + "\n";
  }

  return out;
}

QString SqlOutputText::showQuery( const QString& q )
{
  QSqlQuery query( q, db );

  if ( !query.isActive() ) {
    QString errTxt = errorExecuteQuery() + "\n\n Query:\n " + query.lastQuery() + "\n";
    error( errTxt, query.lastError() );
    return QString::null;
  }

  QString out;
  if ( !query.isSelect() ) {
    out += i18n( "Query OK, rows affected: %1" ).arg( query.numRowsAffected() );
  } else {
    QSqlRecordInfo rec = query.driver()->recordInfo( query );
    uint count = rec.count();

    // write the first line (field names) and memorize the lengths (speed issue...).
    QMemArray<int> lengths( (int)count );
    int i = 0;
    for ( QSqlRecordInfo::iterator it = rec.begin(); it != rec.end(); ++it ) {
      int len = (*it).length();
      out += (*it).name().leftJustify( len ) + " ";
      lengths[ i ] = len;
      i++;
    }
    out += "\n";
    while ( query.next() ) {
      for ( uint i = 0; i < count; ++i ) {
        out += query.value( i ).toString().leftJustify( lengths[ i ] ) + " ";
      }
      out += "\n";
    }
  }
  return out;
}

QString SqlOutputText::showTable( const QString& tableName, int limit, int limitOffset )
{
  QString query = SqlOutputIface::generateSQLCommand( tableName, limit, limitOffset );
  return showQuery( query );
}

void SqlOutputText::error( const QString& msg, const QSqlError& err )
{
  QString out;

  out += i18n( "An error has occurred:\n" );
  out += " " +  msg + "\n\n";
  if ( err.type() != QSqlError::None ) {
    out += i18n( "This is the error message from the driver:" );
    out += "\n" + err.driverText() + "\n\n";
    out += i18n( "This is the error message from the database:" );
    out += "\n" + err.databaseText() + "\n";
  }

  lastErr = out;
}

QString SqlOutputText::success( const QString& msg )
{
  return msg;
}

QString SqlOutputText::showStartPage()
{
  QString out;

  QString drivers = QSqlDatabase::drivers().join( "\n" );
  if ( drivers.isEmpty() ) {
    error( SqlOutputIface::noPluginsAvailableStr(), QSqlError() );
    return QString::null;
  } else {
      out += i18n( "Usage: sql://[HOST]/[PLUGINNAME]/[DATABASENAME]" ) + "\n\n";
      out += i18n( "Available plugins:" ) + "\n\n" + drivers;
  }
  return out;
}

QString SqlOutputText::showMetaData( const QString& tablename )
{
  QString out;

  if ( !db ) {
    error( cannotOpenDatabase() );
    return QString::null;
  }

  QSqlRecordInfo inf = db->recordInfo( tablename );
  if ( inf.isEmpty() ) {
    error( ( errorExecuteQuery() ) );
    return QString::null;
  }

  out += QString( "%1,%2,%3,%4,%5,%6\n"
                ).arg( i18n( "Field Name" ) ).arg( i18n( "Type" ) ).arg( i18n( "Required" )
                ).arg( i18n( "Length" ) ).arg( i18n( "Precision" ) ).arg( i18n( "Default value" ) );
  for ( QSqlRecordInfo::Iterator it = inf.begin(); it != inf.end(); ++it ) {
    QString rec = i18n( "unknown" );
    if ( (*it).isRequired() == 0 ) {
      rec = i18n( "no" );
    } else if ( (*it).isRequired() > 0 ) {
      rec = i18n( "yes" );
    }
    out += (*it).name() + "," +
           QVariant::typeToName( (*it).type() ) + "," +
           rec + "," +
           QString::number( (*it).length() ) + "," +
           QString::number( (*it).precision() ) + "," +
           (*it).defaultValue().toString() + ",\n";
  }

  return out;
}

/**************************************************************************/

SqlOutputCSV::SqlOutputCSV( const KURL& u, QSqlDatabase* sdb ): SqlOutputText( u, sdb )
{
}

SqlOutputCSV::~SqlOutputCSV()
{
}

QString SqlOutputCSV::showQuery( const QString& q )
{
  QSqlQuery query( q, database() );

  if ( !query.isActive() ) {
    QString errTxt = errorExecuteQuery() + "\n\n Query:\n " + query.lastQuery() + "\n";
    error( errTxt, query.lastError() );
    return QString::null;
  }

  QString out;
  if ( !query.isSelect() ) {
    out += i18n( "Query OK, rows affected: %1" ).arg( query.numRowsAffected() );
  } else {
    QSqlRecordInfo rec = query.driver()->recordInfo( query );
    uint count = rec.count();

    // write the first line (field names)
    for ( QSqlRecordInfo::iterator it = rec.begin(); it != rec.end(); ++it ) {
      out += "\"" + (*it).name() + "\",";
    }
    out.truncate( out.length() - 1 ); // remove last comma
    out += "\n";
    // output each row
    while ( query.next() ) {
      for ( uint i = 0; i < count; ++i ) {
        QString val = query.value( i ).toString();
        val.replace( "\"", "\"\"" ); // replace quotation marks with double quotation marks
        out += "\"" + val + "\",";
      }
      out.truncate( out.length() - 1 ); // remove last comma
      out += "\n";
    }
  }
  return out;
}

QString SqlOutputCSV::showTables()
{
  if ( !database() ) {
    error( cannotOpenDatabase() );
    return QString::null;
  }

  QString out = database()->tables().join( "," );

  return out;
}
