/*
 * Copyright (c) 2009 The openGion Project.
 *
 * Licensed 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.opengion.hayabusa.report;

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

import org.opengion.fukurou.db.DBUtil;
import org.opengion.fukurou.util.ApplicationInfo;
import org.opengion.fukurou.util.StringUtil;
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.db.DBTableModel;
import org.opengion.hayabusa.report2.QueueManager_DB.DBTableModelCreator;
import org.opengion.hayabusa.resource.ResourceFactory;
import org.opengion.hayabusa.resource.ResourceManager;

/**
 * DBTableModelオブジェクトをレポート形式に返還するタグリブクラスです。
 * このオブジェクトに、 データ(DBTableModel)と、コントローラ(DBTableReport クラス)を与えて、
 * 外部からコントロールすることで、各種形式で データ(DBTableModel)を表示させることが
 * 可能です。
 *
 * @og.group 帳票システム
 *
 * @version  4.0
 * @author   Hiroki Nakamura
 * @since    JDK5.0,
 */
public class RFIDPrintRequest {

	private static final String CR     = HybsSystem.CR ;

	private final StringBuilder errMsg = new StringBuilder();

	// DBTableModel に対して設定する情報
	private ResourceManager resource	= null;

	// 受け渡し変数
	private final String	SYSTEM_ID	;
	private final String	YKNO		;
	private final String	LISTID		;
	private final String	LANG		;
	private final String	FGRUN		;
	private final String	PRTID		;
	private final String	PRGDIR		;		// 4.3.3.0 (2008/10/01) 板金RFID対応で追加
	private final String	PRGFILE		;		// 4.3.3.0 (2008/10/01) 追加
	private final String	OUTDIR		;		// 4.3.3.0 (2008/10/01) 追加
	private final boolean	DEBUG		;
	private final String	FILENAME	;		// 5.4.3.9 (2012/01/25)

	// オブジェクト変数
	private boolean		fgLOCAL		= false;
	private String		prtName		= null;
	private String		hostName	= null;
	private String		portnm		= null;
	private String		fgkan		= GE50Access.FG_ERR2;	// 4.3.3.0 (2008/10/01) 初期値エラー
	private final Map<String,String[]> rfidLayout = new HashMap<String,String[]>();

	// GE54 の帳票定義情報を取得するSQL文です。
	private static final String GE54_SELECT =
		"SELECT BSQL,FGLOCAL,SYSTEM_ID" +
		" FROM GE54" +
		" WHERE FGJ = '1'" +
		" AND  SYSTEM_ID IN (?,'**')" +
		" AND  LISTID = ?" ;
	private static final int GE54_FGLOCAL	= 1;
	private static final int GE54_SYSTEM_ID	= 2;

	// 5.4.4.0 (2012/02/01) 互換モード対応漏れ
	private static final String HOST = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "HOST" : "HOST_ID";

	// GE55 の出力先マスタ情報を取得するSQL文です。
	// 5.1.0.0 (2009/11/04) HOST ⇒ HOST_ID
	// 5.4.3.1 (2011/12/27) PORTNM
	// 5.4.4.0 (2012/02/01) 互換モード
	private static final String GE55_SELECT =
		"SELECT PRTNM,"+HOST+",SYSTEM_ID,PORTNM" +
		" FROM GE55" +
		" WHERE FGJ = '1'" +
		" AND  SYSTEM_ID IN (?,'**')" +
		" AND  PRTID = ?" ;
	private static final int GE55_PRTNM		= 0;
	private static final int GE55_HOST_ID	= 1;
	private static final int GE55_SYSTEM_ID	= 2;
	private static final int GE55_PORTNM 	= 3;

	// 5.2.0.0 (2010/09/01) Ver4互換モード対応
	private static final String CLM = HybsSystem.sysBool( "VER4_COMPATIBLE_MODE" ) ? "COLUMN_NAME" : "CLM";

	// GE58 の帳票レイアウトテーブルを取得するSQL文です。
	// 5.2.0.0 (2010/09/01) Ver4互換モード対応
	private static final String GE58_SELECT =
		"SELECT KBOUT,DATA1,DATA2,DATA3,DATA4,DATA5,DATA6,DATA7,DATA8" +
		" ,DATA9,DATA10,DATA11,DATA12,DATA13,DATA14,DATA15,"+CLM +
		" FROM GE58 WHERE SYSTEM_ID IN (?,'**')" +
		" AND LISTID = ?";
	public static final int GE58_KBOUT		= 0;
	public static final int GE58_DATA1		= 1;
	public static final int GE58_DATA2		= 2;
	public static final int GE58_DATA3		= 3;
	public static final int GE58_DATA4		= 4;
	public static final int GE58_DATA5		= 5;
	public static final int GE58_DATA6		= 6;
	public static final int GE58_DATA7		= 7;
	public static final int GE58_DATA8		= 8;
	public static final int GE58_DATA9		= 9;
	public static final int GE58_DATA10		= 10;
	public static final int GE58_DATA11		= 11;
	public static final int GE58_DATA12		= 12;
	public static final int GE58_DATA13		= 13;
	public static final int GE58_DATA14		= 14;
	public static final int GE58_DATA15		= 15;
	public static final int GE58_CLM_NAME	= 16;

	// コネクションにアプリケーション情報を追記するかどうか指定
	public static final boolean USE_DB_APPLICATION_INFO  = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;
	private final ApplicationInfo appInfo;
	private final String DBID = HybsSystem.sys( "RESOURCE_DBID" );		// 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応

	/**
	 * コンストラクター
	 * 引数を受けとって、インスタンスを作成します。
	 * @param systemId システムID
	 * @param ykno 要求番号
	 * @param listId 帳票ID
	 * @param lang 言語
	 * @param fgrun 実行方法
	 * @param prtid プリンタID
	 * @param prgdir プログラムディレクトリ
	 * @param prgfile プログラムファイル
	 * @param outdir 出力ディレクトリ
	 * @param layoutFile レイアウトファイル
	 * @param isDebug デバッグフラグ
	 *
	 * @og.rev 4.3.3.0 (2008/10/01) 板金 RFID対応。引数にprgdir,prgfile,outdir追加
	 * @og.rev 5.4.3.1 (2011/12/27) portnm追加
	 * @og.rev 5.4.3.9 (2012/01/25) 雛形ファイル名追加
	 *
	 */
	public RFIDPrintRequest( final String systemId, final String ykno
			, final String listId, final String lang, final String fgrun, final String prtid
			, final String prgdir, final String prgfile, final String outdir , final String layoutFile, final boolean isDebug ) {
		SYSTEM_ID	= systemId;
		YKNO		= ykno;
		LISTID		= listId;
		LANG		= lang;
		FGRUN		= fgrun;
		PRTID		= prtid;
		PRGDIR		= prgdir;					// 4.3.3.0 (2008/10/01)
		PRGFILE		= prgfile;					// 4.3.3.0 (2008/10/01)
		OUTDIR		= outdir;					// 4.3.3.0 (2008/10/01)
		DEBUG		= isDebug;
		FILENAME	= layoutFile;				// 5.4.3.9 (2012/01/25)

		// アクセスログ取得の為,ApplicationInfoオブジェクトを設定
		if( USE_DB_APPLICATION_INFO ) {
			appInfo = new ApplicationInfo();
			// ユーザーID,IPアドレス,ホスト名
			appInfo.setClientInfo( SYSTEM_ID,HybsSystem.HOST_ADRS,HybsSystem.HOST_NAME );
			// 画面ID,操作,プログラムID
			appInfo.setModuleInfo( "ReportConverter",YKNO,LISTID );
		}
		else {
			appInfo = null;
		}
	}

	/**
	 * 初期データセットを行います。
	 * ここでは、GE54,GE58,GE55 テーブルより必要な情報を取得します。
	 *
	 * @og.rev 4.3.3.0 (2008/10/01) 板金 RFID対応(PRGDIR,PRGFILE追加等)
	 * @og.rev 5.4.3.0 (2011/12/26) GE54のbSQLは取らないようにする
	 * @og.rev 5.4.3.9 (2012/01/25) GE58はなくてもよい
	 * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
	 *
	 * @return 結果 [true:正常/false:異常]
	 */
	public boolean initialDataSet() {

		// ===== GE54 から帳票定義情報を取得します =========================================
		String[] args = new String[] { SYSTEM_ID,LISTID };
		String[][] vals = DBUtil.dbExecute( GE54_SELECT,args,appInfo, DBID );		// 5.5.5.1 (2012/08/07)
		if( vals == null || vals.length == 0 ) {
			errMsg.append( "Data does not exist in GE54 table." ).append( CR );
			errMsg.append( "==============================" ).append( CR );
			errMsg.append( "SYSTEM_ID=[" ).append( SYSTEM_ID ).append( "] , " );
			errMsg.append( "LISTID=["    ).append( LISTID    ).append( "]" );
			errMsg.append( CR );
			return false;
		}

		// 検索結果が複数帰ったとき、SYSTEM_ID が 指定されている方のデータ(行)を採用する。
		int row = 0;
		for( int i=0; i<vals.length; i++ ) {
			if( SYSTEM_ID.equalsIgnoreCase( vals[i][GE54_SYSTEM_ID] ) ) { row = i; break; }
		}

		// ローカルリソースフラグ
		// 4.3.3.0 (2008/10/01)
		// fgLOCAL = ( vals[row][GE54_FGLOCAL]  != null && vals[row][GE54_FGLOCAL].trim().equals( "1" ) ) ? true : false ;
		String localFlag = vals[row][GE54_FGLOCAL];
		fgLOCAL = localFlag != null && "1".equals( localFlag.trim() ) ;

		// ===== GE58 から帳票定義情報を取得します =========================================
		String[] argsGe58 = new String[] { SYSTEM_ID,LISTID };
		String[][] valsGe58 = DBUtil.dbExecute( GE58_SELECT,argsGe58,appInfo, DBID );		// 5.5.5.1 (2012/08/07)

		for( int i=0; i<valsGe58.length; i++ ) {
			rfidLayout.put( valsGe58[i][GE58_CLM_NAME], valsGe58[i] );
		}

		// ===== GE55 から出力先マスタ情報を取得します =========================================
		String[] argsGe55 = new String[] { SYSTEM_ID,PRTID };
		String[][] valsGe55 = DBUtil.dbExecute( GE55_SELECT,argsGe55,appInfo, DBID );		// 5.5.5.1 (2012/08/07)
		if( valsGe55 == null || valsGe55.length == 0 ) {
			errMsg.append( "Data does not exist in GE55 table." ).append( CR );
			errMsg.append( "==============================" ).append( CR );
			errMsg.append( "SYSTEM_ID=[" ).append( SYSTEM_ID ).append( "] , " );
			errMsg.append( "PRTID=["    ).append( PRTID    ).append( "]" );
			errMsg.append( CR );
			return false;
		}

		// 検索結果が複数帰ったとき、SYSTEM_ID が 指定されている方のデータ(行)を採用する。
		int rowGe55 = 0;
		for( int i=0; i<vals.length; i++ ) {
			if( SYSTEM_ID.equalsIgnoreCase( vals[i][GE55_SYSTEM_ID] ) ) { rowGe55 = i; break; }
		}

		prtName = valsGe55[rowGe55][GE55_PRTNM];
		hostName = valsGe55[rowGe55][GE55_HOST_ID];
		portnm = valsGe55[rowGe55][GE55_PORTNM];

		return true;
	}

	/**
	 * RFID発行用データを作成し、発行リクエストの処理を行います。
	 *
	 * @og.rev 5.4.3.0 (2011/12/26) _DEFAULT対応
	 * @og.rev 5.4.3.4 (2012/01/12) listid追加
	 * @og.rev 5.4.3.9 (2012/01/25) FILENAME追加
	 *
	 * @return 結果 [true:正常/false:異常]
	 */
	public boolean execute() {
		System.out.print( "RRID RequestData Creating ... " );

		// FGLOCAL 指定時は、SYSTEM_ID を指定してリソース作成
		if( fgLOCAL ) {
			// ローカルリソース指定時は、SYSTEM_ID,LANG を使用します。先読みは、使用しません。
			resource = ResourceFactory.newInstance( SYSTEM_ID,LANG,false );
		}
		else {
			// 従来と互換性のあるモード(ローカルリソースは使用しない。
			resource = ResourceFactory.newInstance( LANG );
		}

		// ボディー情報の取得
		// 5.2.3.0 tableのとり方変更
		DBTableModelCreator tmc = new DBTableModelCreator( SYSTEM_ID, LISTID, YKNO, "B", resource );
		DBTableModel table = tmc.getTable();
		if( table.getRowCount() <= 0 ) {
			errMsg.append( "Database Body row count is Zero." ).append( CR );
			errMsg.append( "==============================" ).append( CR );
			// 5.5.2.4 (2012/05/16) 廃止の消し忘れ。
			errMsg.append( "SYSTEM_ID=" ).append( SYSTEM_ID );
			errMsg.append( ",LISTID="   ).append( LISTID );
			errMsg.append( ",YKNO="     ).append( YKNO );
			errMsg.append( CR );
			return false;
		}
		// 検索時の最大件数での打ち切りをエラーとする。
		if( table.isOverflow() ) {
			errMsg.append( "Database is Overflow. [" );
			errMsg.append( table.getRowCount() );
			errMsg.append( "]" ).append( CR ).append( CR );
			errMsg.append( "==============================" ).append( CR );
			errMsg.append( "Check SystemParameter Data in DB_MAX_ROW_COUNT Overflow" );
			errMsg.append( CR );
			return false;
		}

		// RFID発行用クラスを実行する。
		RFIDPrintPointService service = null;
		try {
			service = (RFIDPrintPointService)StringUtil.newInstance( HybsSystem.sys( "REPORT_RFID_SERVICE_CLASS" ) );
			service.setYkno( YKNO );
			service.setSystemId( SYSTEM_ID );
			service.setFgrun( FGRUN );
			service.setHostName( hostName );
			service.setPrinterName( prtName );
			service.setTable( table );
			service.setLayout( rfidLayout );
			service.setPrgDir( PRGDIR );		// 4.3.3.0 (2008/10/01) 板金 RFID対応
			service.setPrgFile( PRGFILE );		// 4.3.3.0 (2008/10/01)
			service.setOutDir( OUTDIR );		// 4.3.3.0 (2008/10/01)
			service.setPrtId( PRTID );			// 5.4.3.0 (2011/12/26)
			service.setPortnm( portnm );		// 5.4.3.1 (2011/12/27)
			service.setListId( LISTID );		// 5.4.3.4 (2012/01/12)
			service.setLayoutFile( FILENAME );	// 5.4.3.9 (2012/01/25)

			// service.execute();
			boolean flag = service.execute();	// 4.3.3.0 (2008/10/01) booleanを返す

			fgkan = service.getFgkan();			// 4.3.3.0 (2008/10/01) FGKANを受け取るようにする

			if( DEBUG ) {
				System.out.println( service );
			}

			if( ! flag ){ // 4.3.3.0 (2008/10/01)
				errMsg.append( service.getErrMsg() );
				return false;
			}
		}
		catch ( Throwable ex ) {
			fgkan = GE50Access.FG_ERR2; // 4.3.3.0 (2008/10/01) エラー時はアプリエラーにしておく
			errMsg.append( "RFID Print Request Execution Error. " ).append( CR );
			errMsg.append( "==============================" ).append( CR );
			errMsg.append( "SYSTEM_ID=[" ).append( SYSTEM_ID ).append( "] , " );
			errMsg.append( "YKNO=[" ).append( YKNO ).append( "]" ).append( CR );
			errMsg.append( HybsSystem.sys( "REPORT_RFID_SERVICE_CLASS" ) ).append( CR );
			errMsg.append( ex.toString() );
			errMsg.append( CR );
			if( service != null ) { errMsg.append( service.getErrMsg() ); }		// 5.5.2.6 (2012/05/25) findbugs対応
			return false;
		}

		System.out.println( "End." );
		return true ;
	}

	/**
	 * エラーが存在した場合に、エラーメッセージを返します。
	 *
	 * @return エラーメッセージ String
	 */
	public String getErrMsg() {
		return errMsg.toString();
	}

	/**
	 * 完了フラグを返します。
	 *
	 * @og.rev 4.3.3.0 (2008/10/01) 板金RFID メソッド追加
	 *
	 * @return 完了フラグ String
	 */
	public String getFgkan() {
		return fgkan;
	}
}
