package org.postgresforest.vm.core;

import java.sql.SQLException;
import java.sql.SQLWarning;
import java.util.Timer;
import java.util.TimerTask;

import org.postgresforest.PGNotification;
import org.postgresforest.core.Encoding;
import org.postgresforest.core.ProtocolConnection;
import org.postgresforest.core.QueryExecutor;
import org.postgresforest.jdbc2.AbstractJdbc2Connection;
import org.postgresforest.vm.LogUtil;
import org.postgresforest.vm.StatementThreadMng;
import org.postgresforest.vm.gsc.GscData;

public class ProtocolConnectionImpl implements ProtocolConnection {

	/** グローバルシステムカタログクラス */
	protected GscData m_gsc;

	/** SQL実行スレッド管理クラス */
	protected StatementThreadMng m_threadMng;


	/** ログ出力 @since 2.1 */
	protected LogUtil m_logUtil;

	/** @since 2.1*/
	protected static Timer m_closeTimer = new Timer(true);
	
	
	private final String user;
    private final String database;
    private final QueryExecutorImpl executor;
    private final int m_protocolVersion;
    private final String m_serverVersion;
    protected Encoding m_encoding;
     	
    protected int m_transactionState = ProtocolConnection.TRANSACTION_IDLE;

	public ProtocolConnectionImpl(String database, GscData gsc, StatementThreadMng mng, String user) throws SQLException{
		super();

		this.database = database;
		m_gsc = gsc;
		m_threadMng = mng;
		m_logUtil = m_gsc.getLogUtil();
		this.user = user;
		this.executor = new QueryExecutorImpl(m_gsc, m_threadMng,this);
		AbstractJdbc2Connection con = (AbstractJdbc2Connection)m_gsc.getLastServer();
		m_protocolVersion = con.getProtocolVersion();
		m_serverVersion = con.getDBVersionNumber();
		
		m_encoding = con.getEncoding();
		
		
	}


	public String getHost() {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	public int getPort() {
		// TODO 自動生成されたメソッド・スタブ
		return 0;
	}


	public String getServerVersion() {
		return m_serverVersion;
	}

	public Encoding getEncoding() {
		/*
		 * FIXME: V2プロトコルだと、SET CLIENT_ENCODINGコマンドで
		 * クライアントエンコーディングを変更できてしまう。
		 *
		 * そのため、接続時に保存していた値 m_encoding をそのまま返却すると
		 * 実際の設定と違ってくる可能性がある。
		 *
		 * が、そもそもバックエンドに接続しないようにするために
		 * メンバ変数に保持するように変更したため、V2プロトコルの場合に
		 * 接続に行ってしまってはメンバ変数を使うように変更した意味がない。
		 *
		 * V2プロトコル時にAPからSET CLIENT_ENCODINGコマンドを発行した場合、
		 * getEncoding()の動作は保証しない仕様とする。
		 * 
		 * よって以下のコードはdisableとする。
		 */
		/*
		if(m_protocolVersion == 2){
			try {
				m_encoding = ((AbstractJdbc2Connection)m_gsc.getLastServer()).getEncoding();
			} catch (SQLException e) {
			}
 		}
		*/

		return m_encoding;
	}

    public int getTransactionState()
    {
		return m_transactionState;
    }


	public PGNotification[] getNotifications() throws SQLException {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}

	public SQLWarning getWarnings() {
		// TODO 自動生成されたメソッド・スタブ
		return null;
	}


	public void sendQueryCancel() throws SQLException {
		// TODO 自動生成されたメソッド・スタブ

	}

	public void close() {

		if(!isClosed()){
			m_gsc.setClosed(true);
			m_closeTimer.schedule(new CloseTask(), 0);
		}

	}

	/**
	 * プロトコルバージョン
	 * ユーザDBの最初の接続先のバージョンを返す
	 */
	public int getProtocolVersion() {
		return m_protocolVersion;
	}

	
	public QueryExecutor getQueryExecutor() {
        return executor;
	}

	public String getUser() {
        return user;
    }

    public String getDatabase() {
        return database;
    }

	public boolean isClosed() {
		return m_gsc.isClosed();
	}
	
	
	/**
	 * コネクションクローズ処理TimerTaskクラス
	 * @since 2.1
	 */
	protected class CloseTask extends TimerTask {

		/**
		 * コネクションクローズ
		 */
		public void run() {

			m_threadMng.terminate();

			m_gsc.close();
		
		}

	}


	public void setTransactionState(int transactionState) {
		m_transactionState = transactionState;
	}
	
	

}
