package com.quantum.adapters;

import java.util.HashMap;
import java.util.Map;

import com.quantum.Messages;
import com.quantum.util.StringUtil;
import com.quantum.util.sql.TypesHelper;

/**
 * Abstract base class for all the adapter classes. Most functions can be redefined in
 * the adapters for the different databases. If the functions is not redefined, the base
 * implementation (usually a direct call to the JDBC driver) is used.
 * 
 * @author root
 */
public abstract class DatabaseAdapter {
    
	private final String type;
	
	protected DatabaseAdapter(String type) {
		this.type = type;
	}
	
	public String getDisplayName() {
		return Messages.getString(DatabaseAdapter.class, getType());
	}
	
	/**
	 * Returns the SQL Query to get a list of the tables for the current user (schema) 
	 * @param info
	 * @return - A String with the SQL query 
	 */
	public String getShowTableQuery(String schema) {
		return null;
	}
	/**
	 * Returns the SQL Query to get a list of the queries for the current user (schema) 
	 * @param info
	 * @return - A String with the SQL query
	 */
	public String getShowViewQuery(String schema) {
		return null;
	}
	/**
	 * Returns the SQL Query to get a list of the sequences for the current user (schema) 
	 * @param info
	 * @return - A String with the SQL query
	 */
	public String getShowSequenceQuery(String schema) {
        return null;
	}

	/** Returns the SQL Query to access all the columns of a table (SELECT)
	 * @param info
	 * @param table
	 * @return - A String with the SQL query
	 */
	public String getTableQuery( String table) {
			return "SELECT * FROM " + filterTableName(table); //$NON-NLS-1$
	}
    
	/**
	 * Gets the SQL query to get the next value of a sequence, (incrementing it).
	 * @param sequence - The name of the sequence
	 * @param owner - The owner (schema) of it
	 * @return - A string with the SQL query
	 */
	public String getNextValue(String sequence, String owner) {
        return null;
	}
	/**
	 * Gets the SQL query to get the actual value (previously used) of a sequence, (the sequence is not altered).
	 * @param sequence - The name of the sequence
	 * @param owner - The owner (schema) of it
	 * @return - A string with the SQL query
	 */
	public String getPrevValue(String sequence, String owner) {
		return null;
	}
	/**
	 * Returns a query to get the comments on the columns of a table. 
	 * Should return a query to generate a recordset with one row where
	 * the first and only column is the comment
	 * @param tableName - The full name of the table qualified with schema if applicable
	 * @param columnName - The name of the column
	 */
	public String getCommentsQuery(String tableName, String columnName) {
		return null;
	}

	/**
	 * @param table
	 * @return : A query to get an empty ResultSet (null if failed) for that table or view.
	 * Subclassed if needed by the different database adapters
	 */
	public String getEmptySetQuery(String table){
		return "SELECT * FROM " + filterTableName(table) + " WHERE (1 = 0)"; //$NON-NLS-1$ //$NON-NLS-2$
	}
    
	/**
	 * Quotes a string according to the type of the column 
	 * @param string to be quoted
	 * @param type according to java.sql.Types
	 * @return
	 */
	public String quote(String string, int type, String typeString) {
		if (isTextType(type, typeString)) {
			return "'" + StringUtil.substituteString(string, "'", "''") + "'";
		} else if (type == java.sql.Types.DATE || type == java.sql.Types.TIMESTAMP){		
			string = string.trim();
			//Check if we have to strip the millisecods
			if (string.length() > 2) {
				String sub = string.substring(string.length() - 2, string.length() - 1);
				if (string.length() > 1 && sub.equals(".")) //$NON-NLS-1$
					string = string.substring(0, string.length() - 2); // strip the milliseconds
			}
				
			return "'" + string + "'"; //$NON-NLS-1$ //$NON-NLS-2$

		}
		return string;
	}
    
    /**
     * Indicates whether or not a particular type should be quoted in 
     * SQL statements.  Some databases support non-standard types such as
     * TEXT that aren't normally recognized as quoted types.
     * 
     * @param type according to java.sql.Types
     * @param typeString if the type is "Other".
     * @return
     */
    protected boolean isTextType(int type, String typeString) {
        return TypesHelper.isText(type);
    }
    
    
	/**
	 * Makes an SQL insert string with the given table, names of columns and values
	 * @param string
	 * @param namesClause
	 * @param valuesClause
	 * @return
	 */
	public String getInsert(String tableName, String namesClause, String valuesClause) {
		String query = "INSERT INTO " + filterTableName(tableName);
		if (namesClause != "") {
					query += " (" + namesClause + ")";
					query += " VALUES " + "(" + valuesClause; //$NON-NLS-1$
					query += " )"; //$NON-NLS-1$
				}
		return query;
	}
	/**
	 * Changes the name of the table, usually to allow for lowercase situations.
	 * The parent implementation does nothing to the tableName, simply returns it.
	 * @param tableName
	 * @return
	 */
	public String filterTableName(String tableName) {
		return tableName;
	}
	/**
	 * Returns a query to get the number of registers from a table
	 * @param tableName
	 * @return
	 */
	public String getCountQuery(String tableName) {
		return "SELECT COUNT(*) FROM " + filterTableName(tableName);	
	}
	/**
	 * @param string
	 * @param string2
	 * @param whereClause
	 * @param string3
	 */
	public void getUpdate(String tableName, String string2, StringBuffer whereClause, String string3) {
		// TODO Auto-generated method stub
		
	}
	/**
	 * Returns an SQL UPDATE statement
	 * @param string
	 * @param string2
	 * @param string3
	 */
	public String getUpdate(String tableName, String setClause, String whereClause) {
		String query = "UPDATE " + filterTableName(tableName); //$NON-NLS-1$
		query += " SET " + setClause; //$NON-NLS-1$
		if (!whereClause.equals("")) query += " WHERE " + whereClause; //$NON-NLS-1$
		return query;
	}
	/**
	 * Returns an SQL DELETE statement
	 * @param string
	 * @param string2
	 * @return
	 */
	public String getDelete(String tableName, String whereClause) {
		String query = "DELETE FROM " + filterTableName(tableName); //$NON-NLS-1$
		if (!whereClause.equals("")) {
			query += " WHERE " + whereClause; //$NON-NLS-1$
		}
		return query;
	}
    /**
     * @param userid - the userid used to connect to the database
     * @return the default schema for the database
     */
    public String getDefaultSchema(String userid) {
        return userid;
    }
	/**
	 * @return Returns the type.
	 */
	public String getType() {
		return this.type;
	}

	protected String getQualifiedName(String schema, String name) {
		return (schema != null && schema.length() > 0) ? schema + "." + name : name;
	}
	
	public Map getDefaultConnectionParameters() {
		return new HashMap();
	}
	
	/**
	 * Returns the SQL Query to get a list of the Sysnonyms for the current user (schema), of the given type 
	 * @param schema	The schema to get the query for
	 * @param type		The type of the synonym to get. Types can be one from the Entity types
	 * @return - A String with the SQL query 
	 */
	public String getShowSynonymsQuery(String schema, String type) {
		return null;
	}
}