// @@@ START COPYRIGHT @@@
//
// 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.
//
// @@@ END COPYRIGHT @@@

package org.trafodion.jdbc.t4;

import java.nio.charset.CharacterCodingException;
import java.nio.charset.UnsupportedCharsetException;
import java.sql.SQLException;
import java.util.Locale;
import java.util.logging.Level;

class T4Connection {
	protected Locale m_locale;
	protected int m_dialogueId;
	protected NCSAddress m_ncsAddress;
	private InputOutput m_io;
	private USER_DESC_def m_userDesc;
	private CONNECTION_CONTEXT_def m_inContext;
	private String m_sessionName;
	InterfaceConnection m_ic;

	static final int INCONTEXT_OPT1_SESSIONNAME = 0x80000000; // (2^31)
	static final int INCONTEXT_OPT1_FETCHAHEAD = 0x40000000; // (2^30)
	static final int INCONTEXT_OPT1_CERTIFICATE_TIMESTAMP = 0x20000000; //(2^29)
	static final int INCONTEXT_OPT1_CLIENT_USERNAME = 0x10000000; //(2^28)

	T4Connection(InterfaceConnection ic) throws SQLException {
		if (ic == null) {
			throwInternalException();

		}
		m_ic = ic;
		m_locale = ic.getLocale();
		m_dialogueId = ic.getDialogueId();
		m_ncsAddress = ic.getNCSAddress();
		m_userDesc = ic.getUserDescription();
		m_inContext = ic.getInContext();
		m_sessionName = ic.getSessionName();

		if (m_dialogueId < 1 || m_ncsAddress == null || m_userDesc == null || m_inContext == null) {
			throwInternalException();

		}
		m_io = m_ncsAddress.getInputOutput();
		if (m_io == null) {
			throwInternalException();
		}
		m_io.setDialogueId(m_dialogueId);
		m_io.setConnectionIdleTimeout(ic.getConnectionTimeout());
		// trace_connection - AM
		m_io.setT4Connection(this);
                m_io.setNetworkTimeout(ic.t4props_.getNetworkTimeout());
		m_io.openIO();
		getInputOutput().setTimeout(ic.getLoginTimeout());
		checkConnectionIdleTimeout();
		resetConnectionIdleTimeout();
	}

	public void finalizer() {
		closeTimers();
	}

	protected int getDialogueId() {
		return m_dialogueId;
	}

	protected Locale getLocale() {
		return m_locale;
	}

	protected String getSessionName() {
		return this.m_sessionName;
	}

	protected NCSAddress getNCSAddress() {
		return m_ncsAddress;
	}

	void closeTimers() {
		if (m_io != null) {
			m_io.closeTimers();
		}
	}

	protected void reuse() {
		resetConnectionIdleTimeout();
	}

	private void setConnectionIdleTimeout() {
		m_io.startConnectionIdleTimeout();
	}

	private void resetConnectionIdleTimeout() {
		m_io.resetConnectionIdleTimeout();
	}

	private void checkConnectionIdleTimeout() throws SQLException {
		if (m_io.checkConnectionIdleTimeout()) {
			try {
				m_ic.close();
			} catch (SQLException sqex) {
				// ignores
			}
			throw TrafT4Messages.createSQLException(m_ic.t4props_, m_locale, "ids_s1_t00", null);
		}
	}

	protected boolean connectionIdleTimeoutOccured() {
		return m_io.checkConnectionIdleTimeout();
	}

	protected InputOutput getInputOutput() throws SQLException {
		checkConnectionIdleTimeout();
		resetConnectionIdleTimeout();
		return m_io;
	}

	protected void throwInternalException() throws SQLException {
		T4Properties tempP = null;

		if (m_ic != null) {
			tempP = m_ic.t4props_;

		}
		SQLException se = TrafT4Messages.createSQLException(tempP, m_locale, "internal_error", null);
		SQLException se2 = TrafT4Messages.createSQLException(tempP, m_locale, "contact_traf_error", null);

		se.setNextException(se2);
		throw se;
	}

	// --------------------------------------------------------------------------------
	protected LogicalByteArray getReadBuffer(short odbcAPI, LogicalByteArray wbuffer) throws SQLException {
		// trace_connection - AM
		if (m_ic.t4props_.t4Logger_.isLoggable(Level.FINEST) == true) {
			Object p[] = T4LoggingUtilities.makeParams(m_ic.t4props_);
			String temp = "LogicalByteArray";
			m_ic.t4props_.t4Logger_.logp(Level.FINEST, "T4Connection", "getReadBuffer", temp, p);
		}
		LogicalByteArray rbuffer = m_io.doIO(odbcAPI, wbuffer);

		return rbuffer;
	}

	// --------------------------------------------------------------------------------
	/**
	 * This class corresponds to the ODBC client driver function
	 * odbc_SQLSvc_InitializeDialogue_pst_ as taken from odbccs_drvr.cpp.
	 * @version 1.0
	 * 
	 * This method will make a connection to an ODBC server. The ODBC server's
	 * locaiton This method will make a connection to an ODBC server. The ODBC
	 * server's locaiton (i.e. ip address and port number), were provided by an
	 * earlier call to the ODBC association server.
	 * 
	 * @param inContext
	 *            a CONNETION_CONTEXT_def object containing connection
	 *            information
	 * @param userDesc
	 *            a USER_DESC_def object containing user information
	 * @param inContext
	 *            a CONNECTION_CONTEXT_def object containing information for
	 *            this connection
	 * @param dialogueId
	 *            a unique id identifing this connection as supplied by an
	 *            earlier call to the association server
	 * 
	 * @retrun a InitializeDialogueReply class representing the reply from the
	 *         ODBC server is returned
	 * 
	 * @exception A
	 *                SQLException is thrown
	 */

	InitializeDialogueReply InitializeDialogue(boolean setTimestamp, boolean downloadCert) throws SQLException {
		try {
			int optionFlags1 = INCONTEXT_OPT1_CLIENT_USERNAME;
			int optionFlags2 = 0;
			
			if(setTimestamp) {
				optionFlags1 |= INCONTEXT_OPT1_CERTIFICATE_TIMESTAMP;
			}

			if (m_sessionName != null && m_sessionName.length() > 0) {
				optionFlags1 |= INCONTEXT_OPT1_SESSIONNAME;
			}

			if (this.m_ic.t4props_.getFetchAhead()) {
				optionFlags1 |= INCONTEXT_OPT1_FETCHAHEAD;
			}

			// trace_connection - AM
			if (m_ic.t4props_.t4Logger_.isLoggable(Level.FINEST) == true) {
				Object p[] = T4LoggingUtilities.makeParams(m_ic.t4props_);
				String temp = "m_dialogueId=" + m_dialogueId;
				m_ic.t4props_.t4Logger_.logp(Level.FINEST, "T4Connection", "InitializeDialogue", temp, p);
			}
			LogicalByteArray wbuffer = InitializeDialogueMessage.marshal(m_userDesc, m_inContext, m_dialogueId,
					optionFlags1, optionFlags2, m_sessionName, m_ic);

			getInputOutput().setTimeout(m_ic.t4props_.getLoginTimeout());

			LogicalByteArray rbuffer = getReadBuffer(TRANSPORT.SRVR_API_SQLCONNECT, wbuffer);

			//
			// Process output parameters
			//
			InitializeDialogueReply idr1 = new InitializeDialogueReply(rbuffer, m_ncsAddress.getIPorName(), m_ic, downloadCert);

			return idr1;
		} catch (SQLException se) {
			throw se;
		} catch (CharacterCodingException e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale,
					"translation_of_parameter_failed", "InitializeDialogueMessage", e.getMessage());
			se.initCause(e);
			throw se;
		} catch (UnsupportedCharsetException e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale, "unsupported_encoding", e
					.getCharsetName());
			se.initCause(e);
			throw se;
		}

		catch (Exception e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale,
					"initialize_dialogue_message_error", e.getMessage());

			se.initCause(e);
			throw se;
		} // end catch
	} // end InitializeDialogue

	/**
	 * This method will end a connection to an ODBC server. The ODBC server's
	 * locaiton (i.e. ip address and port number), were provided by an earlier
	 * call to the ODBC association server.
	 * 
	 * @retrun a TerminateDialogueReply class representing the reply from the
	 *         ODBC server is returned
	 * 
	 * @exception A
	 *                SQLException is thrown
	 */
	TerminateDialogueReply TerminateDialogue() throws SQLException {
		try {
			// trace_connection - AM
			if (m_ic.t4props_.t4Logger_.isLoggable(Level.FINEST) == true) {
				Object p[] = T4LoggingUtilities.makeParams(m_ic.t4props_);
				String temp = "m_dialogueId=" + m_dialogueId;
				m_ic.t4props_.t4Logger_.logp(Level.FINEST, "T4Connection", "TerminateDialogue", temp, p);
			}
			LogicalByteArray wbuffer = TerminateDialogueMessage.marshal(m_dialogueId, this.m_ic);

			//
			// used m_ic instead of getInputOutput, because getInputOutput
			// implicitly calls close at timeout, which will call
			// TerminateDialogue
			// which causes recursion.
			//
			// m_io.setTimeout(m_ic.t4props_.getCloseConnectionTimeout());
			m_io.setTimeout(m_ic.t4props_.getLoginTimeout());

			LogicalByteArray rbuffer = getReadBuffer(TRANSPORT.SRVR_API_SQLDISCONNECT, wbuffer);

			//
			// Process output parameters
			//
			TerminateDialogueReply tdr1 = new TerminateDialogueReply(rbuffer, m_ncsAddress.getIPorName(), m_ic);

			//
			// Send a close message and close the port if we don't have an
			// error.
			// If there is an error, it's up to the calling routine to decide
			// what to do.
			//
			if (tdr1.m_p1.exception_nr == TRANSPORT.CEE_SUCCESS) {
				m_io.CloseIO(wbuffer); // note, I'm re-using wbuffer

			}

			closeTimers();

			return tdr1;
		} // end try
		catch (SQLException se) {
			throw se;
		} catch (CharacterCodingException e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale,
					"translation_of_parameter_failed", "TerminateDialogMessage", e.getMessage());
			se.initCause(e);
			throw se;
		} catch (UnsupportedCharsetException e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale, "unsupported_encoding", e
					.getCharsetName());
			se.initCause(e);
			throw se;
		} catch (Exception e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale,
					"terminate_dialogue_message_error", e.getMessage());

			se.initCause(e);
			throw se;
		} // end catch
	} // end TerminateDialogue

	/**
	 * This method will send a set connection option command to the server.
	 * 
	 * @param connetionOption
	 *            The connection option to be set
	 * @param optionValueNum
	 *            The number value of the option
	 * @param optionValueStr
	 *            The string value of the option
	 * 
	 * @retrun a SetConnectionOptionReply class representing the reply from the
	 *         ODBC server is returned
	 * 
	 * @exception A
	 *                SQLException is thrown
	 */
	SetConnectionOptionReply SetConnectionOption(short connectionOption, int optionValueNum, String optionValueStr)
			throws SQLException {

		if (optionValueStr == null) {
			throwInternalException();

		}
		try {

			LogicalByteArray wbuffer = SetConnectionOptionMessage.marshal(m_dialogueId, connectionOption,
					optionValueNum, optionValueStr, this.m_ic);

			getInputOutput().setTimeout(m_ic.getQueryTimeout());

			LogicalByteArray rbuffer = getReadBuffer(TRANSPORT.SRVR_API_SQLSETCONNECTATTR, wbuffer);

			SetConnectionOptionReply scor = new SetConnectionOptionReply(rbuffer, m_ncsAddress.getIPorName(), m_ic);

			return scor;
		} // end try
		catch (SQLException se) {
			throw se;
		} catch (CharacterCodingException e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale,
					"translation_of_parameter_failed", "SetConnectionOptionReply", e.getMessage());
			se.initCause(e);
			throw se;
		} catch (UnsupportedCharsetException e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale, "unsupported_encoding", e
					.getCharsetName());
			se.initCause(e);
			throw se;
		} catch (Exception e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale,
					"set_connection_option_message_error", e.getMessage());

			se.initCause(e);
			throw se;
		} // end catch
	} // end SetConnectionOption

	/**
	 * This method will send an End Transaction command, which does not return
	 * any rowsets, to the ODBC server.
	 * 
	 * @param transactionOpt
	 *            A transaction opt
	 * 
	 * @retrun A EndTransactionReply class representing the reply from the ODBC
	 *         server is returned
	 * 
	 * @exception A
	 *                SQLException is thrown
	 */
	EndTransactionReply EndTransaction(short transactionOpt) throws SQLException {

		try {
			LogicalByteArray wbuffer = EndTransactionMessage.marshal(m_dialogueId, transactionOpt, this.m_ic);

			getInputOutput().setTimeout(m_ic.getQueryTimeout());

			LogicalByteArray rbuffer = getReadBuffer(TRANSPORT.SRVR_API_SQLENDTRAN, wbuffer);

			EndTransactionReply cr = new EndTransactionReply(rbuffer, m_ncsAddress.getIPorName(), m_ic);
			return cr;
		} // end try
		catch (SQLException se) {
			throw se;
		} catch (CharacterCodingException e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale,
					"translation_of_parameter_failed", "EndTransactionMessage", e.getMessage());
			se.initCause(e);
			throw se;
		} catch (UnsupportedCharsetException e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale, "unsupported_encoding", e
					.getCharsetName());
			se.initCause(e);
			throw se;
		} catch (Exception e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale, "end_transaction_message_error",
					e.getMessage());

			se.initCause(e);
			throw se;
		} // end catch

	} // end EndTransaction

	/**
	 * This method will send an get SQL catalogs command to the ODBC server.
	 * 
	 * @param stmtLabel
	 *            a statement label for use by the ODBC server
	 * @param APIType
	 * @param catalogNm
	 * @param schemaNm
	 * @param tableNm
	 * @param tableTypeList
	 * @param columnNm
	 * @param columnType
	 * @param rowIdScope
	 * @param nullable
	 * @param uniqueness
	 * @param accuracy
	 * @param sqlType
	 * @param metadataId
	 * @param fkcatalogNm
	 * @param fkschemaNm
	 * @param fktableNm
	 * 
	 * @retrun a GetSQLCatalogsReply class representing the reply from the ODBC
	 *         server is returned
	 * 
	 * @exception A
	 *                SQLException is thrown
	 */
	GetSQLCatalogsReply GetSQLCatalogs(String stmtLabel, short APIType, String catalogNm, String schemaNm,
			String tableNm, String tableTypeList, String columnNm, int columnType, int rowIdScope, int nullable,
			int uniqueness, int accuracy, short sqlType, int metadataId, String fkcatalogNm, String fkschemaNm,
			String fktableNm) throws SQLException {

		if (stmtLabel == null) {
			throwInternalException();

		}
		try {
			LogicalByteArray wbuffer;

			wbuffer = GetSQLCatalogsMessage.marshal(m_dialogueId, stmtLabel, APIType, catalogNm, schemaNm, tableNm,
					tableTypeList, columnNm, columnType, rowIdScope, nullable, uniqueness, accuracy, sqlType,
					metadataId, fkcatalogNm, fkschemaNm, fktableNm, m_ic);

			getInputOutput().setTimeout(m_ic.getQueryTimeout());

			LogicalByteArray rbuffer = getReadBuffer(TRANSPORT.SRVR_API_GETCATALOGS, wbuffer);

			//
			// Process output parameters
			//
			GetSQLCatalogsReply gscr = new GetSQLCatalogsReply(rbuffer, m_ncsAddress.getIPorName(), m_ic);

			return gscr;
		} // end try
		catch (SQLException se) {
			throw se;
		} catch (CharacterCodingException e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale,
					"translation_of_parameter_failed", "GetSQLCatalogsMessage", e.getMessage());
			se.initCause(e);
			throw se;
		} catch (UnsupportedCharsetException e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale, "unsupported_encoding", e
					.getCharsetName());
			se.initCause(e);
			throw se;
		} catch (Exception e) {
			SQLException se = TrafT4Messages.createSQLException(m_ic.t4props_, m_locale,
					"get_sql_catalogs_message_error", e.getMessage());

			se.initCause(e);
			throw se;
		} // end catch

	} // end GetSQLCatalogs

}
