/*
 * Copyright (c) 2013, 2015 Eike Stepper (Berlin, Germany) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Eike Stepper - initial API and implementation
 */
package org.eclipse.net4j.internal.db;

import org.eclipse.net4j.db.DBException;
import org.eclipse.net4j.db.DBUtil;
import org.eclipse.net4j.db.IDBConnection;
import org.eclipse.net4j.db.IDBPreparedStatement;
import org.eclipse.net4j.db.IDBPreparedStatement.ReuseProbability;
import org.eclipse.net4j.db.IDBSchemaTransaction;
import org.eclipse.net4j.db.jdbc.DelegatingConnection;
import org.eclipse.net4j.util.CheckUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeMap;

/**
 * @author Eike Stepper
 */
public final class DBConnection extends DelegatingConnection implements IDBConnection
{
  private final TreeMap<String, DBPreparedStatement> cache = new TreeMap<String, DBPreparedStatement>();

  private final Set<DBPreparedStatement> checkOuts = new HashSet<DBPreparedStatement>();

  private final DBDatabase database;

  private int lastTouch;

  private boolean closed;

  public DBConnection(DBDatabase database, Connection delegate)
  {
    super(delegate);
    this.database = database;

    try
    {
      delegate.setAutoCommit(false);
    }
    catch (SQLException ex)
    {
      throw new DBException(ex, "SET AUTO COMMIT = false");
    }
  }

  public DBDatabase getDatabase()
  {
    return database;
  }

  public String getUserID()
  {
    return database.getUserID();
  }

  @Override
  public void close()
  {
    DBUtil.close(getDelegate());
    // System.out.println("-- Open connections: " + --COUNT);
    closed = true;
    database.closeConnection(this);
  }

  @Override
  public boolean isClosed()
  {
    return closed;
  }

  public IDBSchemaTransaction openSchemaTransaction()
  {
    DBSchemaTransaction schemaTransaction = database.openSchemaTransaction();
    schemaTransaction.setConnection(this);
    return schemaTransaction;
  }

  @Override
  @Deprecated
  public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
      int resultSetHoldability) throws SQLException
  {
    throw new UnsupportedOperationException();
  }

  @Override
  @Deprecated
  public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException
  {
    throw new UnsupportedOperationException();
  }

  @Override
  @Deprecated
  public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException
  {
    throw new UnsupportedOperationException();
  }

  @Override
  @Deprecated
  public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
  {
    throw new UnsupportedOperationException();
  }

  public IDBPreparedStatement prepareStatement(String sql, ReuseProbability reuseProbability)
  {
    return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, reuseProbability);
  }

  public IDBPreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
      ReuseProbability reuseProbability)
  {
    database.beginSchemaAccess(false);

    DBPreparedStatement preparedStatement;
    synchronized (this)
    {
      preparedStatement = cache.remove(sql);
      if (preparedStatement == null)
      {
        try
        {
          PreparedStatement delegate = getDelegate().prepareStatement(sql, resultSetType, resultSetConcurrency);
          preparedStatement = new DBPreparedStatement(this, sql, reuseProbability, delegate);
        }
        catch (SQLException ex)
        {
          throw new DBException(ex);
        }
      }

      checkOuts.add(preparedStatement);
    }

    return preparedStatement;
  }

  @Override
  public PreparedStatement prepareStatement(String sql) throws SQLException
  {
    return prepareStatement(sql, ReuseProbability.LOW);
  }

  @Override
  public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
  {
    return prepareStatement(sql, resultSetType, resultSetConcurrency, ReuseProbability.LOW);
  }

  public void releasePreparedStatement(DBPreparedStatement preparedStatement)
  {
    try
    {
      if (preparedStatement == null)
      {
        // Bug 276926: Silently accept preparedStatement == null and do nothing.
        return;
      }

      synchronized (this)
      {
        checkOuts.remove(preparedStatement);
        preparedStatement.setTouch(++lastTouch);

        String sql = preparedStatement.getSQL();
        if (cache.put(sql, preparedStatement) != null)
        {
          throw new IllegalStateException(sql + " already in cache"); //$NON-NLS-1$
        }

        if (cache.size() > database.getStatementCacheCapacity())
        {
          DBPreparedStatement old = cache.remove(cache.firstKey());
          DBUtil.close(old.getDelegate());
        }
      }
    }
    finally
    {
      database.endSchemaAccess();
    }
  }

  public void invalidateStatementCache()
  {
    synchronized (this)
    {
      CheckUtil.checkState(checkOuts.isEmpty(), "Statements are checked out: " + checkOuts);

      // Close all statements in the cache, then clear the cache.
      for (DBPreparedStatement preparedStatement : cache.values())
      {
        PreparedStatement delegate = preparedStatement.getDelegate();
        DBUtil.close(delegate);
      }

      cache.clear();
    }
  }

  public String convertString(DBPreparedStatement preparedStatement, int parameterIndex, String value)
  {
    return getDatabase().convertString(preparedStatement, parameterIndex, value);
  }

  public String convertString(DBResultSet resultSet, int columnIndex, String value)
  {
    return getDatabase().convertString(resultSet, columnIndex, value);
  }

  public String convertString(DBResultSet resultSet, String columnLabel, String value)
  {
    return getDatabase().convertString(resultSet, columnLabel, value);
  }
}
