/* ============================================================
 *
 * This file is a part of digiKam project
 * http://www.digikam.org
 * 
 * Date        : 2005-06-05
 * Description : TQSlite DB interface.
 *
 * Copyright (C) 2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu>
 *
 * 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, 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 General Public License for more details.
 *
 * ============================================================ */

#ifdef HAVE_CONFIG_H
#include "config.h"    // Needed for NFS_HACK
#endif

// TQt includes.

#include <tqstringlist.h>
#include <tqdir.h>
#include <tqfile.h>

// KDE includes.

#include <tdeio/global.h>
#include <kdebug.h>

// SQlite includes.

#include "sqlite3.h"

// Local includes.

#include "sqlitedb.h"

SqliteDB::SqliteDB()
{
    m_db = 0;
}

SqliteDB::~SqliteDB()
{
    closeDB();
}

void SqliteDB::openDB(const TQString& directory)
{
    if (m_db)
    {
        closeDB();
    }

    TQString dbPath = directory + "/digikam3.db";

#ifdef NFS_HACK
    dbPath = TQDir::homeDirPath() + "/.trinity/share/apps/digikam/"  +
             TDEIO::encodeFileName(TQDir::cleanDirPath(dbPath));
#endif

    sqlite3_open(TQFile::encodeName(dbPath), &m_db);
    if (m_db == 0)
    {
        kdWarning() << "Cannot open database: "
                    << sqlite3_errmsg(m_db)
                    << endl;
    }
}

void SqliteDB::closeDB()
{
    if (m_db)
    {
        sqlite3_close(m_db);
        m_db = 0;
    }
}

bool SqliteDB::execSql(const TQString& sql, TQStringList* const values,
                       TQString* errMsg, bool debug ) const
{
    if ( debug )
        kdDebug() << "SQL-query: " << sql << endl;

    if ( !m_db )
    {
        kdWarning() << k_funcinfo << "SQLite pointer == NULL"
                    << endl;
        if (errMsg)
        {
            *errMsg = TQString::fromLatin1("SQLite database not open");
        }
        return false;
    }

    const char*   tail;
    sqlite3_stmt* stmt;
    int           error;

    //compile SQL program to virtual machine
    error = sqlite3_prepare(m_db, sql.utf8(), -1, &stmt, &tail);
    if ( error != SQLITE_OK )
    {
        kdWarning() << k_funcinfo
                    << "sqlite_compile error: "
                    << sqlite3_errmsg(m_db)
                    << " on query: "
                    << sql << endl;
        if (errMsg)
        {
            *errMsg = TQString::fromLatin1("sqlite_compile error: ") +
                      TQString::fromLatin1(sqlite3_errmsg(m_db)) +
                      TQString::fromLatin1(" on query: ") +
                      sql;
        }
        return false;
    }

    int cols = sqlite3_column_count(stmt);

    while ( true )
    {
        error = sqlite3_step( stmt );

        if ( error == SQLITE_DONE || error == SQLITE_ERROR )
            break;

        //iterate over columns
        for ( int i = 0; values && i < cols; i++ )
        {
            *values << TQString::fromUtf8( (const char*)sqlite3_column_text( stmt, i ) );
        }
    }

    sqlite3_finalize( stmt );

    if ( error != SQLITE_DONE )
    {
        kdWarning() << "sqlite_step error: "
                    << sqlite3_errmsg( m_db )
                    << " on query: "
                    << sql << endl;
        if (errMsg)
        {
            *errMsg = TQString::fromLatin1("sqlite_step error: ") +
                      TQString::fromLatin1(sqlite3_errmsg(m_db)) +
                      TQString::fromLatin1(" on query: ") +
                      sql;
        }
        return false;
    }

    return true;
}

void SqliteDB::setSetting( const TQString& keyword, const TQString& value )
{
    execSql( TQString("REPLACE into Settings VALUES ('%1','%2');")
            .arg( escapeString(keyword) )
            .arg( escapeString(value) ));
}

TQString SqliteDB::getSetting( const TQString& keyword )
{
    TQStringList values;
    execSql( TQString("SELECT value FROM Settings "
                     "WHERE keyword='%1';")
            .arg(escapeString(keyword)),
            &values );

    if (values.isEmpty())
        return TQString();
    else
        return values[0];
}

extern TQString escapeString(const TQString& str)
{
    TQString st(str);
    st.replace( "'", "''" );
    return st;
}

TQ_LLONG SqliteDB::lastInsertedRow() const
{
    return sqlite3_last_insert_rowid(m_db);    
}
