package SQLite;

/**
 * Main class wrapping an SQLite database.
 */

public class Database {

    /**
     * Internal handle for the native SQLite API.
     */

    protected long handle = 0;

    /**
     * Internal last error code for exec() methods.
     */

    protected int error_code = 0;

    /**
     * Open an SQLite database file.
     *
     * @param filename the name of the database file
     * @param mode open mode (e.g. SQLITE_OPEN_READONLY)
     */

    public void open(String filename, int mode) throws SQLite.Exception {
	if ((mode & 0200) != 0) {
	    mode = SQLite.Constants.SQLITE_OPEN_READWRITE |
		   SQLite.Constants.SQLITE_OPEN_CREATE;
	} else if ((mode & 0400) != 0) {
	    mode = SQLite.Constants.SQLITE_OPEN_READONLY;
	}
	synchronized(this) {
	    try {
		_open4(filename, mode, null, false);
	    } catch (SQLite.Exception se) {
		throw se;
	    } catch (java.lang.OutOfMemoryError me) {
		throw me;
	    } catch (Throwable t) {
		_open(filename, mode);
	    }
	}
    }

    /**
     * Open an SQLite database file.
     *
     * @param filename the name of the database file
     * @param mode open mode (e.g. SQLITE_OPEN_READONLY)
     * @param vfs VFS name (for SQLite >= 3.5)
     */

    public void open(String filename, int mode, String vfs)
	throws SQLite.Exception {
	if ((mode & 0200) != 0) {
	    mode = SQLite.Constants.SQLITE_OPEN_READWRITE |
		   SQLite.Constants.SQLITE_OPEN_CREATE;
	} else if ((mode & 0400) != 0) {
	    mode = SQLite.Constants.SQLITE_OPEN_READONLY;
	}
	synchronized(this) {
	    try {
		_open4(filename, mode, vfs, false);
	    } catch (SQLite.Exception se) {
		throw se;
	    } catch (java.lang.OutOfMemoryError me) {
		throw me;
	    } catch (Throwable t) {
		_open(filename, mode);
	    }
	}
    }

    /**
     * Open an SQLite database file.
     *
     * @param filename the name of the database file
     * @param mode open mode (e.g. SQLITE_OPEN_READONLY)
     * @param vfs VFS name (for SQLite >= 3.5)
     * @param ver2 flag to force version on create (false = SQLite3, true = SQLite2)
     */

    public void open(String filename, int mode, String vfs, boolean ver2)
	throws SQLite.Exception {
	if ((mode & 0200) != 0) {
	    mode = SQLite.Constants.SQLITE_OPEN_READWRITE |
		   SQLite.Constants.SQLITE_OPEN_CREATE;
	} else if ((mode & 0400) != 0) {
	    mode = SQLite.Constants.SQLITE_OPEN_READONLY;
	}
	synchronized(this) {
	    try {
		_open4(filename, mode, vfs, ver2);
	    } catch (SQLite.Exception se) {
		throw se;
	    } catch (java.lang.OutOfMemoryError me) {
		throw me;
	    } catch (Throwable t) {
		_open(filename, mode);
	    }
	}
    }

    /*
     * For backward compatibility to older sqlite.jar, sqlite_jni
     */

    private native void _open(String filename, int mode)
	throws SQLite.Exception;

    /*
     * Newer full interface
     */

    private native void _open4(String filename, int mode, String vfs,
			       boolean ver2)
	throws SQLite.Exception;

    /**
     * Open SQLite auxiliary database file for temporary
     * tables.
     *
     * @param filename the name of the auxiliary file or null
     */

    public void open_aux_file(String filename) throws SQLite.Exception {
	synchronized(this) {
	    _open_aux_file(filename);
	}
    }

    private native void _open_aux_file(String filename)
	throws SQLite.Exception;

    /**
     * Destructor for object.
     */

    protected void finalize() {
	synchronized(this) {
	    _finalize();
	}
    }

    private native void _finalize();

    /**
     * Close the underlying SQLite database file.
     */

    public void close()	throws SQLite.Exception {
	synchronized(this) {
	    _close();
	}
    }

    private native void _close()
	throws SQLite.Exception;

    /**
     * Execute an SQL statement and invoke callback methods
     * for each row of the result set.<P>
     *
     * It the method fails, an SQLite.Exception is thrown and
     * an error code is set, which later can be retrieved by
     * the last_error() method.
     *
     * @param sql the SQL statement to be executed
     * @param cb the object implementing the callback methods
     */

    public void exec(String sql, SQLite.Callback cb) throws SQLite.Exception {
	synchronized(this) {
	    _exec(sql, cb);
	}
    }

    private native void _exec(String sql, SQLite.Callback cb)
	throws SQLite.Exception;

    /**
     * Execute an SQL statement and invoke callback methods
     * for each row of the result set. Each '%q' or %Q in the
     * statement string is substituted by its corresponding
     * element in the argument vector.
     * <BR><BR>
     * Example:<BR>
     * <PRE>
     *   String args[] = new String[1];
     *   args[0] = "tab%";
     *   db.exec("select * from sqlite_master where type like '%q'",
     *           null, args);
     * </PRE>
     *
     * It the method fails, an SQLite.Exception is thrown and
     * an error code is set, which later can be retrieved by
     * the last_error() method.
     *
     * @param sql the SQL statement to be executed
     * @param cb the object implementing the callback methods
     * @param args arguments for the SQL statement, '%q' substitution
     */

    public void exec(String sql, SQLite.Callback cb,
		     String args[]) throws SQLite.Exception {
	synchronized(this) {
	    _exec(sql, cb, args);
	}
    }

    private native void _exec(String sql, SQLite.Callback cb, String args[])
	throws SQLite.Exception;

    /**
     * Return the row identifier of the last inserted
     * row.
     */

    public long last_insert_rowid() {
	synchronized(this) {
	    return _last_insert_rowid();
	}
    }

    private native long _last_insert_rowid();

    /**
     * Abort the current SQLite operation.
     */

    public void interrupt() {
	synchronized(this) {
	    _interrupt();
	}
    }

    private native void _interrupt();

    /**
     * Return the number of changed rows for the last statement.
     */

    public long changes() {
	synchronized(this) {
	    return _changes();
	}
    }

    private native long _changes();

    /**
     * Establish a busy callback method which gets called when
     * an SQLite table is locked.
     *
     * @param bh the object implementing the busy callback method
     */

    public void busy_handler(SQLite.BusyHandler bh) {
	synchronized(this) {
	    _busy_handler(bh);
	}
    }

    private native void _busy_handler(SQLite.BusyHandler bh);

    /**
     * Set the timeout for waiting for an SQLite table to become
     * unlocked.
     *
     * @param ms number of millisecond to wait
     */

    public void busy_timeout(int ms) {
	synchronized(this) {
	    _busy_timeout(ms);
	}
    }

    private native void _busy_timeout(int ms);

    /**
     * Convenience method to retrieve an entire result
     * set into memory.
     *
     * @param sql the SQL statement to be executed
     * @param maxrows the max. number of rows to retrieve
     * @return result set
     */

    public TableResult get_table(String sql, int maxrows)
	throws SQLite.Exception {
	TableResult ret = new TableResult(maxrows);
	if (!is3()) {
	    try {
		exec(sql, ret);
	    } catch (SQLite.Exception e) {
		if (maxrows <= 0 || !ret.atmaxrows) {
		    throw e;
		}
	    }
	} else {
	    synchronized(this) {
		/* only one statement !!! */
		Vm vm = compile(sql);
		set_last_error(vm.error_code);
		if (ret.maxrows > 0) {
		    while (ret.nrows < ret.maxrows && vm.step(ret)) {
			set_last_error(vm.error_code);
		    }
		} else {
		    while (vm.step(ret)) {
			set_last_error(vm.error_code);
		    }
		}
		vm.finalize();
	    }
	}
	return ret;
    }

    /**
     * Convenience method to retrieve an entire result
     * set into memory.
     *
     * @param sql the SQL statement to be executed
     * @return result set
     */

    public TableResult get_table(String sql) throws SQLite.Exception {
	return get_table(sql, 0);
    }

    /**
     * Convenience method to retrieve an entire result
     * set into memory.
     *
     * @param sql the SQL statement to be executed
     * @param maxrows the max. number of rows to retrieve
     * @param args arguments for the SQL statement, '%q' substitution
     * @return result set
     */

    public TableResult get_table(String sql, int maxrows, String args[])
	throws SQLite.Exception {
	TableResult ret = new TableResult(maxrows);
	if (!is3()) {
	    try {
		exec(sql, ret, args);
	    } catch (SQLite.Exception e) {
		if (maxrows <= 0 || !ret.atmaxrows) {
		    throw e;
		}
	    }
	} else {
	    synchronized(this) {
		/* only one statement !!! */
		Vm vm = compile(sql, args);
		set_last_error(vm.error_code);
		if (ret.maxrows > 0) {
		    while (ret.nrows < ret.maxrows && vm.step(ret)) {
			set_last_error(vm.error_code);
		    }
		} else {
		    while (vm.step(ret)) {
			set_last_error(vm.error_code);
		    }
		}
		vm.finalize();
	    }
	}
	return ret;
    }

    /**
     * Convenience method to retrieve an entire result
     * set into memory.
     *
     * @param sql the SQL statement to be executed
     * @param args arguments for the SQL statement, '%q' substitution
     * @return result set
     */

    public TableResult get_table(String sql, String args[])
	throws SQLite.Exception {
	return get_table(sql, 0, args);
    }

    /**
     * Convenience method to retrieve an entire result
     * set into memory.
     *
     * @param sql the SQL statement to be executed
     * @param args arguments for the SQL statement, '%q' substitution
     * @param tbl TableResult to receive result set
     */

    public void get_table(String sql, String args[], TableResult tbl)
	throws SQLite.Exception {
	tbl.clear();
	if (!is3()) {
	    try {
		exec(sql, tbl, args);
	    } catch (SQLite.Exception e) {
		if (tbl.maxrows <= 0 || !tbl.atmaxrows) {
		    throw e;
		}
	    }
	} else {
	    synchronized(this) {
		/* only one statement !!! */
		Vm vm = compile(sql, args);
		if (tbl.maxrows > 0) {
		    while (tbl.nrows < tbl.maxrows && vm.step(tbl)) {
			set_last_error(vm.error_code);
		    }
		} else {
		    while (vm.step(tbl)) {
			set_last_error(vm.error_code);
		    }
		}
		vm.finalize();
	    }
	}
    }

    /**
     * See if an SQL statement is complete.
     * Returns true if the input string comprises
     * one or more complete SQL statements.
     *
     * @param sql the SQL statement to be checked
     */

    public synchronized static boolean complete(String sql) {
	return _complete(sql);
    }

    private native static boolean _complete(String sql);

    /**
     * Return SQLite version number as string.
     * Don't rely on this when both SQLite 2 and 3 are compiled
     * into the native part. Use the class method in this case.
     */

    public native static String version();

    /**
     * Return SQLite version number as string.
     * If the database is not open, <tt>unknown</tt> is returned.
     */

    public native String dbversion();

    /**
     * Create regular function.
     *
     * @param name the name of the new function
     * @param nargs number of arguments to function
     * @param f interface of function
     */

    public void create_function(String name, int nargs, Function f) {
	synchronized(this) {
	    _create_function(name, nargs, f);
	}
    }

    private native void _create_function(String name, int nargs, Function f);

    /**
     * Create aggregate function.
     *
     * @param name the name of the new function
     * @param nargs number of arguments to function
     * @param f interface of function
     */

    public void create_aggregate(String name, int nargs, Function f) {
	synchronized(this) {
	    _create_aggregate(name, nargs, f);
	}
    }

    private native void _create_aggregate(String name, int nargs, Function f);

    /**
     * Set function return type. Only available in SQLite 2.6.0 and
     * above, otherwise a no-op.
     *
     * @param name the name of the function whose return type is to be set
     * @param type return type code, e.g. SQLite.Constants.SQLITE_NUMERIC
     */

    public void function_type(String name, int type) {
	synchronized(this) {
	    _function_type(name, type);
	}
    }

    private native void _function_type(String name, int type);

    /**
     * Return the code of the last error occured in
     * any of the exec() methods. The value is valid
     * after an Exception has been reported by one of
     * these methods. See the <A HREF="Constants.html">Constants</A>
     * class for possible values.
     *
     * @return SQLite error code
     */

    public int last_error() {
	return error_code;
    }

    /**
     * Internal: set error code.
     * @param error_code new error code
     */

    protected void set_last_error(int error_code) {
	this.error_code = error_code;
    }

    /**
     * Return last error message of SQLite3 engine.
     *
     * @return error string or null
     */

    public String error_message() {
	synchronized(this) {
	    return _errmsg();
	}
    }

    private native String _errmsg();

    /**
     * Return error string given SQLite error code (SQLite2).
     *
     * @param error_code the error code
     * @return error string
     */

    public static native String error_string(int error_code);

    /**
     * Set character encoding.
     * @param enc name of encoding
     */

    public void set_encoding(String enc) throws SQLite.Exception {
	synchronized(this) {
	    _set_encoding(enc);
	}
    }

    private native void _set_encoding(String enc)
	throws SQLite.Exception;

    /**
     * Set authorizer function. Only available in SQLite 2.7.6 and
     * above, otherwise a no-op.
     *
     * @param auth the authorizer function
     */

    public void set_authorizer(Authorizer auth) {
	synchronized(this) {
	    _set_authorizer(auth);
	}
    }

    private native void _set_authorizer(Authorizer auth);

    /**
     * Set trace function. Only available in SQLite 2.7.6 and above,
     * otherwise a no-op.
     *
     * @param tr the trace function
     */

    public void trace(Trace tr) {
	synchronized(this) {
	    _trace(tr);
	}
    }

    private native void _trace(Trace tr);

    /**
     * Initiate a database backup, SQLite 3.x only.
     *
     * @param dest destination database
     * @param destName schema of destination database to be backed up
     * @param srcName schema of source database
     * @return Backup object to perform the backup operation
     */

    public Backup backup(Database dest, String destName, String srcName)
	throws SQLite.Exception {
	synchronized(this) {
	    Backup b = new Backup();
	    _backup(b, dest, destName, this, srcName);
	    return b;
	}
    }

    private static native void _backup(Backup b, Database dest,
				       String destName, Database src,
				       String srcName)
	throws SQLite.Exception;

    /**
     * Set profile function. Only available in SQLite 3.6 and above,
     * otherwise a no-op.
     *
     * @param pr the trace function
     */

    public void profile(Profile pr) {
	synchronized(this) {
	    _profile(pr);
	}
    }

    private native void _profile(Profile pr);

    /**
     * Return information on SQLite runtime status.
     * Only available in SQLite 3.6 and above,
     * otherwise a no-op.
     *
     * @param op   operation code
     * @param info output buffer, must be able to hold two
     *             values (current/highwater)
     * @param flag reset flag
     * @return SQLite error code
     */

    public synchronized static int status(int op, int info[], boolean flag) {
	return _status(op, info, flag);
    }

    private native static int _status(int op, int info[], boolean flag);

    /**
     * Return information on SQLite connection status.
     * Only available in SQLite 3.6 and above,
     * otherwise a no-op.
     *
     * @param op operation code
     * @param info output buffer, must be able to hold two
     *             values (current/highwater)
     * @param flag reset flag
     * @return SQLite error code
     */

    public int db_status(int op, int info[], boolean flag) {
	synchronized(this) {
	    return _db_status(op, info, flag);
	}
    }

    private native int _db_status(int op, int info[], boolean flag);

    /**
     * Compile and return SQLite VM for SQL statement. Only available
     * in SQLite 2.8.0 and above, otherwise a no-op.
     *
     * @param sql SQL statement to be compiled
     * @return a Vm object
     */

    public Vm compile(String sql) throws SQLite.Exception {
	synchronized(this) {
	    Vm vm = new Vm();
	    vm_compile(sql, vm);
	    return vm;
	}
    }

    /**
     * Compile and return SQLite VM for SQL statement. Only available
     * in SQLite 3.0 and above, otherwise a no-op.
     *
     * @param sql SQL statement to be compiled
     * @param args arguments for the SQL statement, '%q' substitution
     * @return a Vm object
     */

    public Vm compile(String sql, String args[]) throws SQLite.Exception {
	synchronized(this) {
	    Vm vm = new Vm();
	    vm_compile_args(sql, vm, args);
	    return vm;
	}
    }

    /**
     * Prepare and return SQLite3 statement for SQL. Only available
     * in SQLite 3.0 and above, otherwise a no-op.
     *
     * @param sql SQL statement to be prepared
     * @return a Stmt object
     */

    public Stmt prepare(String sql) throws SQLite.Exception {
	synchronized(this) {
	    Stmt stmt = new Stmt();
	    stmt_prepare(sql, stmt);
	    return stmt;
	}
    }

    /**
     * Open an SQLite3 blob. Only available in SQLite 3.4.0 and above.
     * @param db database name
     * @param table table name
     * @param column column name
     * @param row row identifier
     * @param rw if true, open for read-write, else read-only
     * @return a Blob object
     */

    public Blob open_blob(String db, String table, String column,
			  long row, boolean rw) throws SQLite.Exception {
	synchronized(this) {
	    Blob blob = new Blob();
	    _open_blob(db, table, column, row, rw, blob);
	    return blob;
	}
    }

    /**
     * Check type of open database.
     * @return true if SQLite3 database
     */

    public native boolean is3();

    /**
     * Internal compile method.
     * @param sql SQL statement
     * @param vm Vm object
     */

    private native void vm_compile(String sql, Vm vm)
	throws SQLite.Exception;

    /**
     * Internal compile method, SQLite 3.0 only.
     * @param sql SQL statement
     * @param args arguments for the SQL statement, '%q' substitution
     * @param vm Vm object
     */

    private native void vm_compile_args(String sql, Vm vm, String args[])
	throws SQLite.Exception;

    /**
     * Internal SQLite3 prepare method.
     * @param sql SQL statement
     * @param stmt Stmt object
     */

    private native void stmt_prepare(String sql, Stmt stmt)
	throws SQLite.Exception;

    /**
     * Internal SQLite open blob method.
     * @param db database name
     * @param table table name
     * @param column column name
     * @param row row identifier
     * @param rw if true, open for read-write, else read-only
     * @param blob Blob object
     */

    private native void _open_blob(String db, String table, String column,
				   long row, boolean rw, Blob blob)
	throws SQLite.Exception;

    /**
     * Establish a progress callback method which gets called after
     * N SQLite VM opcodes.
     *
     * @param n number of SQLite VM opcodes until callback is invoked
     * @param p the object implementing the progress callback method
     */

    public void progress_handler(int n, SQLite.ProgressHandler p) {
	synchronized(this) {
	    _progress_handler(n, p);
	}
    }

    private native void _progress_handler(int n, SQLite.ProgressHandler p);

    /**
     * Specify key for encrypted database. To be called
     * right after open() on SQLite3 databases.
     * Not available in public releases of SQLite.
     *
     * @param ekey the key as byte array
     */

    public void key(byte[] ekey) throws SQLite.Exception {
	synchronized(this) {
	    _key(ekey);
	}
    }

    /**
     * Specify key for encrypted database. To be called
     * right after open() on SQLite3 databases.
     * Not available in public releases of SQLite.
     *
     * @param skey the key as String
     */

    public void key(String skey) throws SQLite.Exception {
	synchronized(this) {
	    byte ekey[] = null;
	    if (skey != null && skey.length() > 0) {
		ekey = new byte[skey.length()];
		for (int i = 0; i< skey.length(); i++) {
		    char c = skey.charAt(i);
		    ekey[i] = (byte) ((c & 0xff) ^ (c >> 8));
		}
	    }
	    _key(ekey);
	}
    }

    private native void _key(byte[] ekey);

    /**
     * Change the key of a encrypted database. The
     * SQLite3 database must have been open()ed.
     * Not available in public releases of SQLite.
     *
     * @param ekey the key as byte array
     */

    public void rekey(byte[] ekey) throws SQLite.Exception {
	synchronized(this) {
	    _rekey(ekey);
	}
    }

    /**
     * Change the key of a encrypted database. The
     * SQLite3 database must have been open()ed.
     * Not available in public releases of SQLite.
     *
     * @param skey the key as String
     */

    public void rekey(String skey) throws SQLite.Exception {
	synchronized(this) {
	    byte ekey[] = null;
	    if (skey != null && skey.length() > 0) {
		ekey = new byte[skey.length()];
		for (int i = 0; i< skey.length(); i++) {
		    char c = skey.charAt(i);
		    ekey[i] = (byte) ((c & 0xff) ^ (c >> 8));
		}
	    }
	    _rekey(ekey);
	}
    }

    private native void _rekey(byte[] ekey);

    /**
     * Enable/disable shared cache mode (SQLite 3.x only).
     *
     * @param onoff boolean to enable or disable shared cache
     * @return boolean when true, function supported/succeeded
     */

    protected static native boolean _enable_shared_cache(boolean onoff);

    /**
     * Internal native initializer.
     */

    private static native void internal_init();

    /**
     * Make long value from julian date for java.lang.Date
     *
     * @param d double value (julian date in SQLite3 format)
     * @return long
     */

    public static long long_from_julian(double d) {
	d -= 2440587.5;
	d *= 86400000.0;
	return (long) d;
    }

    /**
     * Make long value from julian date for java.lang.Date
     *
     * @param s string (double value) (julian date in SQLite3 format)
     * @return long
     */

    public static long long_from_julian(String s) throws SQLite.Exception {
	try {
	    double d = Double.parseDouble(s); // android-changed: performance
	    return long_from_julian(d);
	} catch (java.lang.Exception ee) {
	    throw new SQLite.Exception("not a julian date");
	}
    }

    /**
     * Make julian date value from java.lang.Date
     *
     * @param ms millisecond value of java.lang.Date
     * @return double
     */

    public static double julian_from_long(long ms) {
	double adj = (ms < 0) ? 0 : 0.5;
	double d = (ms + adj) / 86400000.0 + 2440587.5;
	return d;
    }

    /**
     * Static initializer to load the native part.
     */

    static {
	try {
	    String path = System.getProperty("SQLite.library.path");
	    if (path == null || path.length() == 0) {
		System.loadLibrary("sqlite_jni");
	    } else {
		try {
		    java.lang.reflect.Method mapLibraryName;
		    Class param[] = new Class[1];
		    param[0] = String.class;
		    mapLibraryName = System.class.getMethod("mapLibraryName",
							    param);
		    Object args[] = new Object[1];
		    args[0] = "sqlite_jni";
		    String mapped = (String) mapLibraryName.invoke(null, args);
		    System.load(path + java.io.File.separator + mapped);
		} catch (Throwable t) {
		    System.err.println("Unable to load sqlite_jni from" +
				       "SQLite.library.path=" + path +
				       ", trying system default: " + t);
		    System.loadLibrary("sqlite_jni");
		}
	    }
	} catch (Throwable t) {
	    System.err.println("Unable to load sqlite_jni: " + t);
	}
	/*
	 * Call native initializer functions now, since the
	 * native part could have been linked statically, i.e.
	 * the try/catch above would have failed in that case.
	 */
	try {
	    internal_init();
	    new FunctionContext();
	} catch (java.lang.Exception e) {
	}
    }
}

