/*
 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
 * Version 1.0, and under the Eclipse Public License, Version 1.0
 * (http://h2database.com/html/license.html).
 * Initial Developer: H2 Group
 */
package org.h2.android;

import java.io.File;
import java.util.Locale;
import java.util.Map;
import org.h2.engine.ConnectionInfo;
import org.h2.engine.Engine;
import org.h2.engine.Session;
import android.content.ContentValues;
import android.database.Cursor;

/**
 * This class represents a database connection.
 */
public class H2Database {

    /**
     * When a conflict occurs, abort the current statement, but don't roll back
     * the transaction. This is the default value.
     */
    public static final int CONFLICT_ABORT = 2;

    /**
     * When a conflict occurs, return SQLITE_CONSTRAINT, but don't roll back the
     * transaction.
     */
    public static final int CONFLICT_FAIL = 3;

    /**
     * When a conflict occurs, continue, but don't modify the conflicting row.
     */
    public static final int CONFLICT_IGNORE = 4;

    /**
     * When a conflict occurs, do nothing.
     */
    public static final int CONFLICT_NONE = 0;

    /**
     * When a conflict occurs, the existing rows are replaced.
     */
    public static final int CONFLICT_REPLACE = 5;

    /**
     * When a conflict occurs, the transaction is rolled back.
     */
    public static final int CONFLICT_ROLLBACK = 1;

    /**
     * Create a new database if it doesn't exist.
     */
    public static final int CREATE_IF_NECESSARY = 0x10000000;

    /**
     * This flag has no effect.
     */
    public static final int NO_LOCALIZED_COLLATORS = 0x10;

    /**
     * Open the database in read-only mode.
     */
    public static final int OPEN_READONLY = 1;

    /**
     * Open the database in read-write mode (default).
     */
    public static final int OPEN_READWRITE = 0;

    private final Session session;

    private H2Database(Session session) {
        this.session = session;
    }

    /**
     * Create a new in-memory database.
     *
     * @param factory the cursor factory
     * @return a connection to this database
     */
    public static H2Database create(H2Database.CursorFactory factory) {
        ConnectionInfo ci = new ConnectionInfo("mem:");
        Session s = Engine.getInstance().createSession(ci);
        return new H2Database(s);
    }

    /**
     * Open a connection to the given database.
     *
     * @param path the database file name
     * @param factory the cursor factory
     * @param flags 0, or a combination of OPEN_READONLY and CREATE_IF_NECESSARY
     * @return a connection to this database
     */
    public static H2Database openDatabase(String path, H2Database.CursorFactory factory, int flags) {
        ConnectionInfo ci = new ConnectionInfo(path);
        if ((flags & OPEN_READWRITE) != 0) {
            // TODO readonly connections
        }
        if ((flags & CREATE_IF_NECESSARY) == 0) {
            ci.setProperty("IFEXISTS", "TRUE");
        }
        Session s = Engine.getInstance().createSession(ci);
        return new H2Database(s);
    }

    /**
     * Open a connection to the given database. The database is created if it
     * doesn't exist yet.
     *
     * @param file the database file
     * @param factory the cursor factory
     * @return a connection to this database
     */
    public static H2Database openOrCreateDatabase(File file, H2Database.CursorFactory factory) {
        return openDatabase(file.getPath(), factory, CREATE_IF_NECESSARY);
    }

    /**
     * Open a connection to the given database. The database is created if it
     * doesn't exist yet.
     *
     * @param path the database file name
     * @param factory the cursor factory
     * @return a connection to this database
     */
    public static H2Database openOrCreateDatabase(String path, H2Database.CursorFactory factory) {
        return openDatabase(path, factory, CREATE_IF_NECESSARY);
    }

    /**
     * Start a transaction.
     */
    public void beginTransaction() {
        session.setAutoCommit(false);
    }

    /**
     * Start a transaction.
     *
     * @param transactionListener the transaction listener to use
     */
    public void beginTransactionWithListener(H2TransactionListener transactionListener) {
        // TODO H2TransactionListener
        session.setAutoCommit(false);
    }

    /**
     * Close the connection.
     */
    public void close() {
        session.close();
    }

    /**
     * Prepare a statement.
     *
     * @param sql the statement
     * @return the prepared statement
     */
    public H2Statement compileStatement(String sql) {
        return new H2Statement(session.prepare(sql));
    }

    /**
     * Delete a number of rows in this database.
     *
     * @param table the table
     * @param whereClause the condition
     * @param whereArgs the parameter values
     * @return the number of rows deleted
     */
    public int delete(String table, String whereClause, String[] whereArgs) {
        return 0;
    }

    /**
     * End the transaction.
     */
    public void endTransaction() {
        // TODO
    }

    /**
     * Execute the given statement.
     *
     * @param sql the statement
     * @param bindArgs the parameter values
     */
    public void execSQL(String sql, Object[] bindArgs) {
        // TODO
    }

    /**
     * Execute the given statement.
     *
     * @param sql the statement
     */
    public void execSQL(String sql) {
        // TODO
    }

    /**
     * TODO
     *
     * @param tables the list of tables
     * @return TODO
     */
    public static String findEditTable(String tables) {
        // TODO
        return null;
    }

    /**
     * Get the maximum size of the database file in bytes.
     *
     * @return the maximum size
     */
    public long getMaximumSize() {
        return Long.MAX_VALUE;
    }

    /**
     * Get the page size of the database in bytes.
     *
     * @return the page size
     */
    public long getPageSize() {
        return 0;
    }

    /**
     * Get the name of the database file.
     *
     * @return the database file name
     */
    public String getPath() {
        return null;
    }

    /**
     * TODO
     *
     * @return TODO
     */
    public Map<String, String> getSyncedTables() {
        return null;
    }

    /**
     * Get the database version.
     *
     * @return the database version
     */
    public int getVersion() {
        return 0;
    }

    /**
     * Check if there is an open transaction.
     *
     * @return true if there is
     */
    public boolean inTransaction() {
        return false;
    }

    /**
     * Insert a row.
     *
     * @param table the table
     * @param nullColumnHack not used
     * @param values the values
     * @return TODO
     */
    public long insert(String table, String nullColumnHack, ContentValues values) {
        return 0;
    }

    /**
     * Try to insert a row.
     *
     * @param table the table
     * @param nullColumnHack not used
     * @param values the values
     * @return TODO
     */
    public long insertOrThrow(String table, String nullColumnHack, ContentValues values) {
        return 0;
    }

    /**
     * Try to insert a row, using the given conflict resolution option.
     *
     * @param table the table
     * @param nullColumnHack not used
     * @param initialValues the values
     * @param conflictAlgorithm what conflict resolution to use
     * @return TODO
     */
    public long insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm) {
        return 0;
    }

    /**
     * Check if the database is locked by the current thread.
     *
     * @return true if it is
     */
    public boolean isDbLockedByCurrentThread() {
        return false;
    }

    /**
     * Check if the database is locked by a different thread.
     *
     * @return true if it is
     */
    public boolean isDbLockedByOtherThreads() {
        return false;
    }

    /**
     * Check if the connection is open.
     *
     * @return true if it is
     */
    public boolean isOpen() {
        return false;
    }

    /**
     * Check if the connection is read-only.
     *
     * @return true if it is
     */
    public boolean isReadOnly() {
        return false;
    }

    /**
     * TODO
     *
     * @param table the table
     * @param deletedTable TODO
     */
    public void markTableSyncable(String table, String deletedTable) {
        // TODO
    }

    /**
     * TODO
     *
     * @param table the table
     * @param foreignKey the foreign key
     * @param updateTable TODO
     */
    public void markTableSyncable(String table, String foreignKey, String updateTable) {
        // TODO
    }

    /**
     * Check if an upgrade is required.
     *
     * @param newVersion the new version
     * @return true if the current version doesn't match
     */
    public boolean needUpgrade(int newVersion) {
        return false;
    }

    /**
     * Execute the SELECT statement for the given parameters.
     *
     * @param distinct if only distinct rows should be returned
     * @param table the table
     * @param columns the list of columns
     * @param selection TODO
     * @param selectionArgs TODO
     * @param groupBy the group by list or null
     * @param having the having condition or null
     * @param orderBy the order by list or null
     * @param limit the limit or null
     * @return the cursor
     */
    public Cursor query(boolean distinct, String table, String[] columns, String selection, String[] selectionArgs,
            String groupBy, String having, String orderBy, String limit) {
        return null;
    }

    /**
     * Execute the SELECT statement for the given parameters.
     *
     * @param table the table
     * @param columns the list of columns
     * @param selection TODO
     * @param selectionArgs TODO
     * @param groupBy the group by list or null
     * @param having the having condition or null
     * @param orderBy the order by list or null
     * @return the cursor
     */
    public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy,
            String having, String orderBy) {
        return null;
    }

    /**
     * Execute the SELECT statement for the given parameters.
     *
     * @param table the table
     * @param columns the list of columns
     * @param selection TODO
     * @param selectionArgs TODO
     * @param groupBy the group by list or null
     * @param having the having condition or null
     * @param orderBy the order by list or null
     * @param limit the limit or null
     * @return the cursor
     */
    public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy,
            String having, String orderBy, String limit) {
        return null;
    }

    /**
     * Execute the SELECT statement for the given parameters.
     *
     * @param cursorFactory the cursor factory to use
     * @param distinct if only distinct rows should be returned
     * @param table the table
     * @param columns the list of columns
     * @param selection TODO
     * @param selectionArgs TODO
     * @param groupBy the group by list or null
     * @param having the having condition or null
     * @param orderBy the order by list or null
     * @param limit the limit or null
     * @return the cursor
     */
    public Cursor queryWithFactory(H2Database.CursorFactory cursorFactory, boolean distinct, String table, String[] columns,
            String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) {
        return null;
    }

    /**
     * Execute the query.
     *
     * @param sql the SQL statement
     * @param selectionArgs the parameter values
     * @return the cursor
     */
    public Cursor rawQuery(String sql, String[] selectionArgs) {
        return null;
    }

    /**
     * Execute the query using the given cursor factory.
     *
     * @param cursorFactory the cursor factory
     * @param sql the SQL statement
     * @param selectionArgs the parameter values
     * @param editTable TODO
     * @return the cursor
     */
    public Cursor rawQueryWithFactory(H2Database.CursorFactory cursorFactory, String sql, String[] selectionArgs,
            String editTable) {
        return null;
    }

    /**
     * Try to release memory.
     *
     * @return TODO
     */
    public static int releaseMemory() {
        return 0;
    }

    /**
     * Replace an existing row in the database.
     *
     * @param table the table
     * @param nullColumnHack ignored
     * @param initialValues the values
     * @return TODO
     */
    public long replace(String table, String nullColumnHack, ContentValues initialValues) {
        return 0;
    }

    /**
     * Try to replace an existing row in the database.
     *
     * @param table the table
     * @param nullColumnHack ignored
     * @param initialValues the values
     * @return TODO
     */
    public long replaceOrThrow(String table, String nullColumnHack, ContentValues initialValues) {
        return 0;
    }

    /**
     * Set the locale.
     *
     * @param locale the new locale
     */
    public void setLocale(Locale locale) {
        // TODO
    }

    /**
     * Enable or disable thread safety.
     *
     * @param lockingEnabled the new value
     */
    public void setLockingEnabled(boolean lockingEnabled) {
        // TODO
    }

    /**
     * Set the maximum database file size.
     *
     * @param numBytes the file size in bytes
     * @return the effective maximum size
     */
    public long setMaximumSize(long numBytes) {
        return 0;
    }

    /**
     * Set the database page size. The value can not be changed once the
     * database exists.
     *
     * @param numBytes the page size
     */
    public void setPageSize(long numBytes) {
        // TODO
    }

    /**
     * Mark the transaction as completed successfully.
     */
    public void setTransactionSuccessful() {
        // TODO
    }

    /**
     * Update the database version.
     *
     * @param version the version
     */
    public void setVersion(int version) {
        // TODO
    }

    /**
     * Update one or multiple rows.
     *
     * @param table the table
     * @param values the values
     * @param whereClause the where condition
     * @param whereArgs the parameter values
     * @return the number of rows updated
     */
    public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {
        return 0;
    }

    /**
     * Update one or multiple rows.
     *
     * @param table the table
     * @param values the values
     * @param whereClause the where condition
     * @param whereArgs the parameter values
     * @param conflictAlgorithm the conflict resolution option
     * @return the number of rows updated
     */
    public int updateWithOnConflict(String table, ContentValues values, String whereClause, String[] whereArgs,
            int conflictAlgorithm) {
        return 0;
    }

    /**
     * TODO
     *
     * @deprecated
     * @return TODO
     */
    public boolean yieldIfContended() {
        return false;
    }

    /**
     * Temporarily pause the transaction.
     *
     * @param sleepAfterYieldDelay TODO
     * @return TODO
     */
    public boolean yieldIfContendedSafely(long sleepAfterYieldDelay) {
        return false;
    }

    /**
     * Temporarily pause the transaction.
     *
     * @return TODO
     */
    public boolean yieldIfContendedSafely() {
        return false;
    }

    /**
     * The cursor factory.
     */
    public interface CursorFactory {

        /**
         * Create a new cursor.
         *
         * @param db the connection
         * @param masterQuery TODO
         * @param editTable TODO
         * @param query TODO
         * @return the cursor
         */
        Cursor newCursor(H2Database db, H2CursorDriver masterQuery, String editTable, H2Query query);
    }

}
