/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.ode.bpel.extvar.jdbc;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.List;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import javax.swing.text.StyleContext.SmallAttributeSet;
import javax.xml.namespace.QName;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.bpel.extvar.jdbc.DbExternalVariable.Column;
import org.apache.ode.bpel.extvar.jdbc.DbExternalVariable.RowKey;
import org.apache.ode.bpel.extvar.jdbc.DbExternalVariable.RowVal;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.ObjectPrinter;
import org.apache.ode.bpel.evar.ExternalVariableModule;
import org.apache.ode.bpel.evar.ExternalVariableModuleException;
import org.apache.ode.bpel.evar.IncompleteKeyException;
import org.w3c.dom.Element;

public class JdbcExternalVariableModule implements ExternalVariableModule {

    private static final Logger __log = LoggerFactory.getLogger(JdbcExternalVariableModule.class);

    public static final String JDBC_NS = "http://ode.apache.org/externalVariables/jdbc";

    /** Unique QName for the engine, this should be the element used for the external-variable configuration. */
    public static final QName NAME = new QName(JDBC_NS, "jdbc");

    /** Manually configured data sources. */
    private final HashMap<String, DataSource> _dataSources = new HashMap<String, DataSource>();

    /** Variables we know about via configure() method calls. */
    private final HashMap<EVarId, DbExternalVariable> _vars = new HashMap<EVarId, DbExternalVariable>();

    public void configure(QName pid, String extVarId, Element config) throws ExternalVariableModuleException {
        EVarId evarId = new EVarId(pid, extVarId);
        DataSource ds = null;

        Element jndiDs = DOMUtils.findChildByName(config, new QName(JDBC_NS, "datasource-jndi"));
        Element jndiRef = DOMUtils.findChildByName(config, new QName(JDBC_NS, "datasource-ref"));
        Element initMode = DOMUtils.findChildByName(config, new QName(JDBC_NS, "init-mode"));
        if (jndiRef != null) {
            String refname = jndiRef.getTextContent().trim();
            ds = _dataSources.get(refname);
            if (ds == null)
                throw new ExternalVariableModuleException("Data source reference \"" + refname
                        + "\" not found for external variable " + evarId
                        + "; make sure to register the data source with the engine!");
        } else if (jndiDs != null) {
            String name = jndiDs.getTextContent().trim();
            Object dsCandidate;
            InitialContext ctx;
            try {
                ctx = new InitialContext();
            } catch (Exception ex) {
                throw new ExternalVariableModuleException("Unable to access JNDI context for external variable " + evarId, ex);
            }

            try {
                dsCandidate = ctx.lookup(name);
            } catch (Exception ex) {
                throw new ExternalVariableModuleException("Lookup of data source for " + evarId + "  failed.", ex);
            } finally {
                try {
                    ctx.close();
                } catch (NamingException e) { /* ignore */ }
            }

            if (dsCandidate == null)
                throw new ExternalVariableModuleException("Data source \"" + name + "\" not found in JNDI!");

            if (!(dsCandidate instanceof DataSource))
                throw new ExternalVariableModuleException("JNDI object \"" + name + "\" does not implement javax.sql.DataSource");

            ds = (DataSource) dsCandidate;
        }

        if (ds == null) {
            throw new ExternalVariableModuleException("No valid data source configuration for JDBC external varible " + evarId);
        }

        Connection conn = null;
        DatabaseMetaData metaData;
        try {
            conn = ds.getConnection();
            metaData = conn.getMetaData();
        } catch (Exception ex) {
            try {
                if (conn != null) conn.close();
            } catch (SQLException e) {
                // ignore
            }
            throw new ExternalVariableModuleException("Unable to open database connection for external variable " + evarId, ex);
        }


        try {
            DbExternalVariable dbev = new DbExternalVariable(evarId, ds);
            if (initMode != null)
                try {
                    dbev._initType = InitType.valueOf(initMode.getTextContent().trim());
                } catch (Exception ex) {
                    throw new ExternalVariableModuleException("Invalid <init-mode> value: " + initMode.getTextContent().trim());
                }

            Element tableName = DOMUtils.findChildByName(config, new QName(JDBC_NS, "table"));
            if (tableName == null || tableName.getTextContent().trim().equals(""))
                throw new ExternalVariableModuleException("Must specify <table> for external variable " + evarId);
            String table = tableName.getTextContent().trim();
            String schema = null;
            if (table.indexOf('.') != -1) {
                schema = table.substring(0, table.indexOf('.'));
                table = table.substring(table.indexOf('.') + 1);
            }

            if (metaData.storesLowerCaseIdentifiers()) {
                table = table.toLowerCase();
                if (schema != null)
                    schema = table.toLowerCase();
            } else if (metaData.storesUpperCaseIdentifiers()) {
                table = table.toUpperCase();
                if (schema != null)
                    schema = schema.toUpperCase();
            }

            dbev.generatedKeys = metaData.supportsGetGeneratedKeys();
            ResultSet tables = metaData.getTables(null, schema, table, null);
            if (tables.next()) {
                dbev.table = tables.getString("TABLE_NAME");
                dbev.schema = tables.getString("TABLE_SCHEM");
            } else
                throw new ExternalVariableModuleException("Table \"" + table + "\" not found in database.");

            tables.close();

            List<Element> columns = DOMUtils.findChildrenByName(config, new QName(JDBC_NS, "column"));

            for (Element col : columns) {
                String name = col.getAttribute("name");
                String colname = col.getAttribute("column-name");
                String key = col.getAttribute("key");
                String gentype = col.getAttribute("generator");
                String expression = col.getAttribute("expression");

                if (key == null || "".equals(key))
                    key = "no";
                if (gentype == null || "".equals(gentype))
                    gentype = GenType.none.toString();
                if (colname == null || "".equals(colname))
                    colname = name;

                if (name == null || "".equals(name))
                    throw new ExternalVariableModuleException("External variable " + evarId
                            + " <column> element must have \"name\" attribute. ");

                if (metaData.storesLowerCaseIdentifiers())
                    colname = colname.toLowerCase();
                else if (metaData.storesUpperCaseIdentifiers())
                    colname = colname.toUpperCase();

                GenType gtype;
                try {
                    gtype = GenType.valueOf(gentype);
                } catch (Exception ex) {
                    throw new ExternalVariableModuleException("External variable " + evarId + " column \"" + name
                            + "\" generator type \"" + gentype + "\" is unknown.");

                }

                if (gtype == GenType.expression && (expression == null || "".equals(expression)))
                    throw new ExternalVariableModuleException("External variable " + evarId + " column \"" + name
                            + "\" used \"expression\" generator, but did not specify an expression");

                Column c = dbev.new Column(name, colname, key.equalsIgnoreCase("yes"), gtype, expression);
                ResultSet cmd = metaData.getColumns(null, dbev.schema, dbev.table, colname);
                try {
                    if (cmd.next()) {
                        c.dataType = cmd.getInt("DATA_TYPE");
                        c.nullok = cmd.getInt("NULLABLE") != 0;
                    } else
                        throw new ExternalVariableModuleException("External variable " + evarId + " referenced "
                            + "non-existant column \"" + colname + "\"!");
                } finally {
                    cmd.close();
                }

                dbev.addColumn(c);
            }

            if (dbev.numColumns() == 0)
                throw new ExternalVariableModuleException("External variable " + evarId + " did not have any <column> elements!");

            _vars.put(evarId, dbev);
        } catch (SQLException se) {
            throw new ExternalVariableModuleException("SQL Error", se);
        } finally {
            try {
                conn.close();
            } catch (SQLException e) {
            }
        }
    }

    public QName getName() {
        return NAME;
    }

    public boolean isTransactional() {
        return true;
    }

    public void shutdown() {
    }

    public void start() {
    }

    public void stop() {
    }

    public Value writeValue(QName varType, Value newval) throws ExternalVariableModuleException {
        EVarId evarId = new EVarId(newval.locator.pid, newval.locator.varId);
        DbExternalVariable evar = _vars.get(evarId);
        if (evar == null)
            throw new ExternalVariableModuleException("No such variable. "); // todo

        RowKey key = evar.keyFromLocator(newval.locator);
        RowVal val = evar.parseXmlRow(evar.new RowVal(), (Element) newval.value);
        if (__log.isDebugEnabled())
            __log.debug("JdbcExternalVariable.writeValue() RowKey: " + key + " RowVal: " + val);

        if (!key.missingValues() && evar._initType == InitType.delete_insert) {
            // do delete...
            throw new ExternalVariableModuleException("Delete not implemented. "); // todo
        }

        // should we try an update first? to do this we need to have all the required keys
        // and there should be some keys
        boolean tryupdatefirst = (evar._initType == InitType.update || evar._initType == InitType.update_insert)
                && !evar._keycolumns.isEmpty() && !key.missingDatabaseGeneratedValues();

        boolean insert = evar._initType != InitType.update;

        if (__log.isDebugEnabled())
            __log.debug("tryUpdateFirst: " + tryupdatefirst
                        + " insert: " + insert
                        + " initType: " + evar._initType
                        + " key.isEmpty: " + evar._keycolumns.isEmpty()
                        + " key.missingValues: " + key.missingValues()
                        + " key.missingDBValues: " + key.missingDatabaseGeneratedValues());

        try {
            if (tryupdatefirst)
                insert = execUpdate(evar, key, val) == 0;
            if (insert) {
                key = execInsert(evar, newval.locator, key, val);
                // Transfer the keys obtained from the db.
                key.write(varType, newval.locator);
            }
        } catch (SQLException se) {
            throw new ExternalVariableModuleException("Error updating row.", se);
        }

        return newval;
    }

    public Value readValue(QName varType, Locator locator) throws ExternalVariableModuleException {
        EVarId evarId = new EVarId(locator.pid, locator.varId);
        DbExternalVariable evar = _vars.get(evarId);
        if (evar == null)
            throw new ExternalVariableModuleException("No such variable: "+evarId);

        Element val;
        try {
            RowVal rowval = execSelect(evar, locator);
            val = evar.renderXmlRow(locator, varType, rowval);
        } catch (SQLException se) {
            throw new ExternalVariableModuleException("SQL Error.", se);
        }

        return new Value(locator, val, null);
    }

    /**
     * Manually register a data source. Handy if you don't want to use JNDI to look these up.
     *
     * @param dsName
     * @param ds
     */
    public void registerDataSource(String dsName, DataSource ds) {
        _dataSources.put(dsName, ds);
    }

    int execUpdate(DbExternalVariable dbev, RowKey key, RowVal values) throws SQLException {
        Connection conn = dbev.dataSource.getConnection();
        PreparedStatement stmt = null;
        try {
            if (__log.isDebugEnabled()) {
                __log.debug("execUpdate: key=" + key + " values=" + values);
                __log.debug("Prepare statement: " + dbev.update);
            }
            stmt = conn.prepareStatement(dbev.update);
            int idx = 1;
            for (Column c : dbev._updcolumns) {
                Object val = values.get(c.name);
                if (__log.isDebugEnabled()) __log.debug("Set value parameter "+idx+": "+val);
                if (val == null)
                    stmt.setNull(idx, c.dataType);
                else
                    stmt.setObject(idx, downcastValue(val, c.dataType));
                idx++;
            }

            for (Column ck : dbev._keycolumns) {
                Object val = key.get(ck.name);
                if (__log.isDebugEnabled()) __log.debug("Set key parameter "+idx+": "+val);
                if (val == null)
                    stmt.setNull(idx, ck.dataType);
                else
                    stmt.setObject(idx, downcastValue(val, ck.dataType));
                idx++;
            }
            return stmt.executeUpdate();
        } finally {
            if (stmt != null) stmt.close();
            try {
                conn.close();
            } catch (SQLException e) {
                // ignore
            }
        }
    }

    private Object downcastValue(Object value, int dataType) {
        if (value == null) {
            return null;
        }
        // Try down casting the value as per its column type.
        try {
            // Some JDBC 4.0 types have been ignored to avoid compilation errors
            switch (dataType) {
            case Types.ARRAY:
                break;
            case Types.BIGINT:
                if (!(value instanceof BigInteger)) {
                    value = new BigDecimal(value.toString()).longValue();
                }
                break;
            case Types.BINARY:
                break;
            case Types.BIT:
                if (!(value instanceof Boolean)) {
                    value = new Boolean(value.toString());
                }
                break;
            case Types.BLOB:
                break;
            case Types.BOOLEAN:
                if (!(value instanceof Boolean)) {
                    value = new Boolean(value.toString());
                }
                break;
            case Types.CHAR:
                break;
            case Types.CLOB:
                break;
            case Types.DATALINK:
                break;
            case Types.DATE:
                break;
            case Types.DECIMAL:
                //ODE-872: Oracle 9g and 10g has problems with BigDecimal on Java1.5
                value = new BigDecimal(new BigDecimal(value.toString()).toPlainString());
                break;
            case Types.DISTINCT:
                break;
            case Types.DOUBLE:
                if (!(value instanceof Double)) {
                    value = Double.valueOf(value.toString()).doubleValue();
                }
                break;
            case Types.FLOAT:
                if (!(value instanceof Float)) {
                    value = Float.valueOf(value.toString()).floatValue();
                }
                break;
            case Types.INTEGER:
                if (!(value instanceof Integer)) {
                    value = Double.valueOf(value.toString()).intValue();
                }
                break;
            case Types.JAVA_OBJECT:
                break;
//	    	case Types.LONGNVARCHAR:
//	    		break;
            case Types.LONGVARBINARY:
                break;
            case Types.LONGVARCHAR:
                break;
//	    	case Types.NCHAR:
//	    		break;
//	    	case Types.NCLOB:
//	    		break;
            case Types.NUMERIC:
                //ODE-872: Oracle 9g and 10g has problems with BigDecimal on Java1.5
                value = new BigDecimal(new BigDecimal(value.toString()).toPlainString());
                break;
//	    	case Types.NVARCHAR:
//	    		break;
            case Types.OTHER:
                break;
            case Types.REAL:
                if (!(value instanceof Double)) {
                    value = Float.valueOf(value.toString()).floatValue();
                }
                break;
            case Types.REF:
                break;
//	    	case Types.ROWID:
//	    		break;
            case Types.SMALLINT:
                if (!(value instanceof Short)) {
                    value = new Short(value.toString()).shortValue();
                }
                break;
//	    	case Types.SQLXML:
//	    		break;
            case Types.STRUCT:
                break;
            case Types.TIME:
                break;
            case Types.TIMESTAMP:
                break;
            case Types.TINYINT:
                if (!(value instanceof Short)) {
                    value = new Short(value.toString()).shortValue();
                }
                break;
            case Types.VARBINARY:
                break;
            case Types.VARCHAR:
                break;
            default:
                break;
            }
        } catch (Exception e) {
            // couldn't cast... let's just use original value object
        }
        return value;
    }

    RowVal execSelect(DbExternalVariable dbev, Locator locator) throws SQLException, ExternalVariableModuleException {
        RowKey rowkey = dbev.keyFromLocator(locator);
        if (__log.isDebugEnabled()) __log.debug("execSelect: " + rowkey);

        if (rowkey.missingDatabaseGeneratedValues()) {
            return null;
        }

        if (rowkey.missingValues()) {
            throw new IncompleteKeyException(rowkey.getMissing());
        }

        RowVal ret = dbev.new RowVal();
        Connection conn = dbev.dataSource.getConnection();
        PreparedStatement stmt = null;
        try {
            if (__log.isDebugEnabled()) __log.debug("Prepare statement: " + dbev.select);
            stmt = conn.prepareStatement(dbev.select);
            int idx = 1;
            for (Object k : rowkey) {
                if (__log.isDebugEnabled()) __log.debug("Set key parameter "+idx+": "+k);
                stmt.setObject(idx++, k);
            }

            ResultSet rs = stmt.executeQuery();
            try {
                if (rs.next()) {
                    for (Column c : dbev._columns)  {
                        Object val;
                        int i = c.idx+1;
                        if (c.isDate()) val = rs.getDate(i);
                        else if (c.isTimeStamp()) val = rs.getTimestamp(i);
                        else if (c.isTime()) val = rs.getTime(i);
                        else if (c.isInteger()) val = new Long(rs.getLong(i));
                        else if (c.isReal()) val = new Double(rs.getDouble(i));
                        else if (c.isBoolean()) val = new Boolean(rs.getBoolean(i));
                        else val = rs.getObject(i);
                        if (__log.isDebugEnabled()) __log.debug("Result column index "+c.idx+": "+val);
                        ret.set(c.idx,val);
                    }
                } else
                    return null;
            } finally {
                rs.close();
            }
        } finally {
            if (stmt != null) stmt.close();
            try {
                conn.close();
            } catch (SQLException e) {
                // ignore
            }
        }

        return ret;
    }

    RowKey execInsert(DbExternalVariable dbev, Locator locator, RowKey keys, RowVal values) throws SQLException {
        Connection conn = dbev.dataSource.getConnection();
        PreparedStatement stmt = null;
        try {
            if (__log.isDebugEnabled()) {
                __log.debug("execInsert: keys=" + keys + " values=" + values);
                __log.debug("Prepare statement: " + dbev.insert);
                __log.debug("missingDatabaseGeneratedValues: " + keys.missingDatabaseGeneratedValues());
                __log.debug("_autoColNames: " + ObjectPrinter.stringifyNvList(dbev._autoColNames));
            }

            stmt = keys.missingDatabaseGeneratedValues()
                ? conn.prepareStatement(dbev.insert, dbev._autoColNames)
                : conn.prepareStatement(dbev.insert);

            int idx = 1;
            for (Column c : dbev._inscolumns) {
                Object val = c.getValue(c.name, keys, values, locator.iid);
                values.put(c.name, val);
                if (__log.isDebugEnabled()) __log.debug("Set parameter "+idx+": "+val);
                if (val == null)
                    stmt.setNull(idx, c.dataType);
                else
                    stmt.setObject(idx, val);
                idx++;
            }

            stmt.execute();

            for (Column ck : keys._columns) {
                Object val = values.get(ck.name);
                if (__log.isDebugEnabled()) __log.debug("Key "+ck.name+": "+val);
                keys.put(ck.name,val);
            }

            if (keys.missingDatabaseGeneratedValues() ) {
                // With JDBC 3, we can get the values of the key columns (if the db supports it)
                ResultSet keyRS = stmt.getGeneratedKeys();
                try {
                    if (keyRS == null)
                        throw new SQLException("Database did not return generated keys");
                    keyRS.next();
                    for (Column ck : keys._columns) {
                        Object value = keyRS.getObject(ck.idx+1);
                        if (__log.isDebugEnabled()) __log.debug("Generated key "+ck.name+": "+value);
                        keys.put(ck.name, value);
                    }
                } finally {
                    keyRS.close();
                }
            }
            return keys;
        } finally {
            if (stmt != null) stmt.close();
            try {
                conn.close();
            } catch (SQLException e) {
                // ignore
            }
        }
    }

}
