/*
 * 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.db.DBTableModelUtil;
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 DBTableModel	table 		= null;		// 4.3.1.1 (2008/08/23) ローカル変数化
	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 String		bSQL		= null;
	private boolean		fgLOCAL		= false;
	private String		prtName		= null;
	private String		hostName	= 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_BSQL		= 0;
	private static final int GE54_FGLOCAL	= 1;
	private static final int GE54_SYSTEM_ID	= 2;

	// GE55 の出力先マスタ情報を取得するSQL文です。
	private static final String GE55_SELECT =
		"select prtnm,host,system_id" +
		" from GE55" +
		" where fgj = '1'" +
		" and  system_id in (?,'**')" +
		" and  prtid = ?" ;
	private static final int GE55_PRTNM		= 0;
	private static final int GE55_HOST		= 1;
	private static final int GE55_SYSTEM_ID	= 2;

	// GE58 の帳票レイアウトテーブルを取得するSQL文です。
	private static final String GE58_SELECT =
		"select kbout,data1,data2,data3,data4,data5,data6,data7,data8" +
		" ,data9,data10,data11,data12,data13,data14,data15,column_name" +
		" 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;

	/**
	 * コンストラクター
	 * 引数を受けとって、インスタンスを作成します。
	 * @param systemId システムID
	 * @param ykno 要求番号
	 * @param listId 帳票ID
	 * @param lang 言語
	 * @param fgrun 実行方法
	 * @param prtid プリンタID
	 * @param prgdir プログラムディレクトリ
	 * @param prgfile プログラムファイル
	 * @param outdir 出力ディレクトリ
	 * @param isDebug デバッグフラグ
	 * 
	 * @og.rev 4.3.3.0 (2008/10/01) 板金 RFID対応。引数にprgdir,prgfile,outdir追加
	 *
	 */
	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 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;

		// アクセスログ取得の為,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追加等)
	 * @return 結果 (正常：true / 異常：false)
	 */
	public boolean initialDataSet() {

		// ===== GE54 から帳票定義情報を取得します =========================================
		String[] args = new String[] { SYSTEM_ID,LISTID };
		String[][] vals = DBUtil.dbExecute( GE54_SELECT,args,appInfo );
		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; }
		}

		bSQL = StringUtil.nval( vals[row][GE54_BSQL],bSQL );
		if( bSQL == null || bSQL.length() == 0 ) {
			errMsg.append( "Body SQL Columns 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;
		}

		// ローカルリソースフラグ
		// 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() )) ? true : false ;


		// ===== GE58 から帳票定義情報を取得します =========================================
		String[] argsGe58 = new String[] { SYSTEM_ID,LISTID };
		String[][] valsGe58 = DBUtil.dbExecute( GE58_SELECT,argsGe58,appInfo );
		if( valsGe58 == null || valsGe58.length == 0 ) {
			errMsg.append( "Data does not exist in GE58 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;
		}

		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 );
		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];

		return true;
	}

	/**
	 * RFID発行用データを作成し、発行リクエストの処理を行います。
	 *
	 * @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 );
		}

		String[] where = new String[] { SYSTEM_ID , YKNO } ;

		// ボディー情報の取得
//		table = DBTableModelUtil.makeDBTable( bSQL, where, resource ,appInfo );
		DBTableModel table = DBTableModelUtil.makeDBTable( bSQL, where, resource ,appInfo );
		if( table.getRowCount() <= 0 ) {
			errMsg.append( "Database Body row count is Zero." ).append( CR );
			errMsg.append( "==============================" ).append( CR );
			errMsg.append( bSQL );
			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.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 e ) {
			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( e.toString() );
			errMsg.append( CR );
			errMsg.append( service.getErrMsg() );
			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;
	}
}
