/*
 * 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 org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.fukurou.system.DateSet;						// 6.4.2.0 (2016/01/29)
import org.opengion.fukurou.util.StringUtil;
import org.opengion.fukurou.db.ApplicationInfo;
import org.opengion.fukurou.system.ThrowUtil ;					// 6.4.2.0 (2016/01/29)
import org.opengion.fukurou.db.DBUtil;
import static org.opengion.fukurou.system.HybsConst.CR ;				// 6.1.0.0 (2014/12/26)
import static org.opengion.fukurou.system.HybsConst.FS ;				// 6.1.0.0 (2014/12/26)
import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;	// 6.1.0.0 (2014/12/26) refactoring

import java.io.File;

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

	private static final String FGRUN_1	= "1";	// HTMLのみ
	private static final String FGRUN_2	= "2";	// 印刷のみ
	private static final String FGRUN_3	= "3";	// 出力＋印刷

	// 3.8.0.0 (2005/06/07) 実行方法(FGRUN)に、EXCEL取込関連のフラグ値を追加。
	private static final String FGRUN_5	= "5";	// 取込のみ
	private static final String FGRUN_6	= "6";	// PG起動のみ
	private static final String FGRUN_7	= "7";	// 取込+PG起動

	private static final String FGRUN_A	= "A";	// RFID(通常印刷) 4.0.3.0 (2007/12/26)
	private static final String FGRUN_B	= "B";	// RFID(全印刷)   4.0.3.0 (2007/12/26)
	private static final String FGRUN_C	= "C";	// RFID(全消去)   4.0.3.0 (2007/12/26)
	private static final String FGRUN_D	= "D";	// RFID(連続消去) 4.1.1.0 (2008/02/21)

	private static final String FGRUN_G	= "G";	// CSV(印刷)  5.9.0.0 (2015/09/04)
	private static final String FGRUN_H	= "H";	// CSV(Excel) 5.9.0.0 (2015/09/04)
	private static final String FGRUN_I	= "I";	// CSV(PDF)   5.9.0.0 (2015/09/04)
	private static final String FGRUN_J	= "J";	// CSV(XLSX)  5.9.4.2 (2016/01/13)

	// 印刷時に使用するテンポラリフォルダ名
	private final String REPORT_URL =
		HybsSystem.url2dir( StringUtil.nval(
								HybsSystem.sys( "REPORT_FILE_URL" ) ,
								HybsSystem.sys( "FILE_URL"   ) + "REPORT/" ) ) ;

	// 3.8.0.0 (2005/06/07) 追加
	// EXCEL取込時に使用するテンポラリフォルダ名。ファイル名は、要求番号.xls
	private final String EXCELIN_URL =
		HybsSystem.url2dir( StringUtil.nval(
								HybsSystem.sys( "EXCEL_IN_FILE_URL" ) ,
								HybsSystem.sys( "FILE_URL"   ) + "EXCELIN/" ) ) ;

	private final StringBuilder errMsg = new StringBuilder( BUFFER_MIDDLE );

	// 各種DBを検索するときに、キー情報
	private String		SYSTEM_ID	;
	private String		YKNO		;
	private String		GROUPID		;
	private String		LISTID		;
	private String		JOKEN		;
	private String		OUT_DIR		;		// 5.1.0.0 (2009/11/04) OUTDIR ⇒ OUT_DIR
	private String		OUT_FILE	;		// 5.1.0.0 (2009/11/04) OUTFILE ⇒ OUT_FILE
	private String		outputFile	;
	private boolean		isDebug		;		// 3.8.5.0 (2006/03/06) デバッグ用のフラグを追加

	// GE53 検索結果
	private String		FGRUN		;
	private String		PRTID		;
	private String		LANG		= "ja";
	private String		PRGDIR		;
	private String		PRGFILE		;
	private String		DMN_GRP		;		// 3.8.0.5 (2005/08/26)
	private String		programFile	;

	// GE53 の帳票振分情報を取得するSQL文です。
	// 3.8.0.5 (2005/08/26) デーモングループ追加
	// 4.0.0 (2005/01/31) 共有 system_id を、考慮
	private static final String GE53_SELECT =
		"SELECT FGRUN,PRTID,LANG,PRGDIR,PRGFILE,SYSTEM_ID,DMN_GRP" +
		" FROM GE53" +
		" WHERE FGJ = '1'" +
		" AND  SYSTEM_ID IN (?,'**')" +
		" AND  JOKEN = ?" ;

	private static final int GE53_FGRUN		= 0;
	private static final int GE53_PRTID		= 1;
	private static final int GE53_LANG		= 2;
	private static final int GE53_PRGDIR	= 3;
	private static final int GE53_PRGFILE	= 4;
	private static final int GE53_SYSTEM_ID	= 5;
	private static final int GE53_DMN_GRP	= 6;

	/** コネクションにアプリケーション情報を追記するかどうか指定 */
	public static final boolean USE_DB_APPLICATION_INFO  = HybsSystem.sysBool( "USE_DB_APPLICATION_INFO" ) ;

	// 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
	private ApplicationInfo appInfo;
	private final String DBID = HybsSystem.sys( "RESOURCE_DBID" );		// 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対応

	/**
	 * デフォルトコンストラクター
	 *
	 * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
	 */
	public ReportProcessing() { super(); }		// これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。

	/**
	 * 処理を実行します。
	 * このメソッドを実行すると、レポート変換、レポート出力を順次処理していきます。
	 *
	 * @og.rev 3.0.0.4 (2003/02/26) FGRUN が PRT のみのときは，MODELFILE のみセットして終了する。
	 * @og.rev 3.8.0.0 (2005/06/07) ReportConverter の initialDataSet() を呼び出して，MODELFILE をセットする。
	 * @og.rev 3.8.0.0 (2005/06/07) EXCEL 登録機能を追加します。
	 * @og.rev 3.8.0.0 (2005/06/07) 実行結果を boolean ではなく、文字列(FGKAN_XX)で返します。
	 * @og.rev 3.8.0.5 (2005/08/26) デーモングループ追加
	 * @og.rev 3.8.0.9 (2005/10/17) エラーメッセージ強化
	 * @og.rev 3.8.5.0 (2006/03/06) 標準画面出力メッセージの変更。日付、ﾌﾟﾘﾝﾀIDの表示
	 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
	 * @og.rev 4.0.3.0 (2007/12/26) RFID対応(実行方法='A','B','C'の処理追加)
	 * @og.rev 4.1.1.0 (2008/02/21) RFID対応(実行方法='D'の処理追加)
	 * @og.rev 4.3.3.0 (2008/10/01) 板金RFID対応(PRGDIR,PRGFILEの渡し等)
	 * @og.rev 5.4.3.9 (2012/01/25) RFIDの雛形ファイル名私は旧帳票は無視する
	 * @og.rev 5.9.0.0 (2015/09/04) CSV出力対応
	 * @og.rev 5.9.2.2 (2015/11/20) CSV出力にgrpid,dmngrpを追加
	 * @og.rev 5.9.4.2 (2016/01/13) FGRUN_J追加
	 * @og.rev 6.4.2.0 (2016/01/29) StringUtil#stringStackTrace(Throwable) を、ThrowUtil#ogStackTrace(Throwable) に置き換え。
	 * @og.rev 6.4.2.0 (2016/01/29) DateSet.getDate( String ) を利用するように修正します。
	 * @og.rev 6.4.2.1 (2016/02/05) メソッド名変更 ReportConverter#modelFile() → ReportConverter#getModelFile() 。
	 *
	 * @return 結果 (FGKAN_XX エラー時は、null)
	 */
	public String execute() {
		System.out.println();
		System.out.println( "Process Start:" + DateSet.getDate( "yyyy/MM/dd HH:mm:ss" ) );						// 6.4.2.0 (2016/01/29)
		System.out.println( "  SYSTEM_ID=[" + SYSTEM_ID + "] YKNO=[" + YKNO + "] GROUPID=[" + GROUPID + "]" );
		System.out.println( "  PRTID=[" + PRTID + "] LISTID=[" + LISTID + "] JOKEN=[" + JOKEN + "]" );
		String  fgkan = null;

		// 3.8.7.0 (2006/12/15) アクセスログ取得の為,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( "ReportProcessing",YKNO,LISTID );
		}
		else {
			appInfo = null;
		}

		boolean flag ;
		try {
			flag = initialDataSet( appInfo );
			System.out.print( "INIT=" + flag + "," );
			final String reportDir  = REPORT_URL + SYSTEM_ID + FS + LISTID ;
			String modelFile = null;

	// ================== FGRUN_1,2,3 は、帳票印刷処理 ===========================================
			// 3.8.0.0 (2005/06/07) 実行方法(FGRUN)に、EXCEL取込関連のフラグ値を追加。Stringからintに変更
			if( flag && ( FGRUN.equals( FGRUN_1 ) || FGRUN.equals( FGRUN_2 ) || FGRUN.equals( FGRUN_3 ) ) ) {
				System.out.println( "RUN_" + FGRUN );
				final ReportConverter rc = new ReportConverter( SYSTEM_ID,YKNO,LISTID,reportDir,LANG,isDebug );

				// 3.8.0.0 (2005/06/07) MODELFILE のセットは、initialDataSet() で行う。
				flag = rc.initialDataSet();
				modelFile = rc.getModelFile();		// 6.4.2.1 (2016/02/05) メソッド名変更

				if( flag && ( FGRUN.equals( FGRUN_1 ) || FGRUN.equals( FGRUN_3 ) ) ) {
					flag = rc.execute();
				}

				if( flag ) { fgkan = GE50Access.FG_OK; }
				errMsg.append( rc.getErrMsg() ).append( CR );
			}
			if( flag && ( FGRUN.equals( FGRUN_2 ) || FGRUN.equals( FGRUN_3 ) ) ) {
				System.out.println( "RUN_" + FGRUN );
				fgkan = null;
				// 3.8.0.5 (2005/08/26) デーモングループ追加
				final ReportPrint rp = new ReportPrint( SYSTEM_ID,YKNO,PRTID,programFile,reportDir,modelFile,outputFile,DMN_GRP,isDebug );
				flag = rp.execute();
				if( flag ) { fgkan = GE50Access.FG_OK; }
				errMsg.append( rp.getErrMsg() ).append( CR );
			}

	// ================== FGRUN_4,5,6 は、EXCEL取込処理 ===========================================
			// 3.8.0.0 (2005/06/07) EXCEL 登録機能を追加します。
			final String excelinDir = EXCELIN_URL + SYSTEM_ID + FS + LISTID;
			if( flag && ( FGRUN.equals( FGRUN_5 ) || FGRUN.equals( FGRUN_7 ) ) ) {
				System.out.println( "RUN_" + FGRUN );
				final ExcelInsert ei = new ExcelInsert( SYSTEM_ID,YKNO,LISTID,excelinDir,isDebug );

				flag = ei.execute();
				if( flag ) { fgkan = GE50Access.FG_DBIN; }
				errMsg.append( ei.getErrMsg() ).append( CR );
			}
			if( flag && ( FGRUN.equals( FGRUN_6 ) || FGRUN.equals( FGRUN_7 ) ) ) {
				System.out.println( "RUN_" + FGRUN );
				fgkan = null;
				final ProgramRun pr = new ProgramRun( SYSTEM_ID,YKNO,LISTID,isDebug );
				flag = pr.execute();
				if( flag ) { fgkan = GE50Access.FG_OK; }
				errMsg.append( pr.getErrMsg() ).append( CR );
			}

	// ================== FGRUN_A,B,C,D は、RFID出力処理 ===========================================
			if( flag && ( FGRUN.equals( FGRUN_A ) || FGRUN.equals( FGRUN_B ) || FGRUN.equals( FGRUN_C ) || FGRUN.equals( FGRUN_D ) ) ) {
				System.out.println( "RUN_" + FGRUN );
				//RFIDPrintRequest rpr = new RFIDPrintRequest( SYSTEM_ID,YKNO,LISTID,LANG,FGRUN,PRTID,isDebug );
				// 4.3.3.0 (2008/10/01) RFIDPrintRequestのコンストラクタ引数追加
				// 5.4.3.9 (2012/01/25) 雛形ファイル名は新帳票のみ対応
				final RFIDPrintRequest rpr = new RFIDPrintRequest( SYSTEM_ID,YKNO,LISTID,LANG,FGRUN,PRTID,PRGDIR,PRGFILE,OUT_DIR,null,isDebug );
				flag = rpr.initialDataSet();
				if( flag ) { flag = rpr.execute(); }
				//if( flag ) { fgkan = GE50Access.FG_RUN; }
				// 4.3.3.0 (2008/10/01) 完成フラグの取り方変更
				if( flag ) { fgkan = rpr.getFgkan(); }
				errMsg.append( rpr.getErrMsg() ).append( CR );
			}

	// ================== FGRUN_G,H,I,J は、CSV出力処理 ===========================================	
			// 5.9.0.0 (2015/09/04)
			// 5.9.4.2 (2016/01/13) FGRUN_J追加
			if( flag && ( FGRUN.equals( FGRUN_G ) || FGRUN.equals( FGRUN_H ) || FGRUN.equals( FGRUN_I ) || FGRUN.equals( FGRUN_J ) ) ) {
				System.out.println( "RUN_" + FGRUN );
				final CSVPrintRequest rpr = new CSVPrintRequest( SYSTEM_ID,YKNO,LISTID,LANG,FGRUN,PRTID,PRGDIR,PRGFILE,OUT_DIR,null,GROUPID,DMN_GRP,isDebug );	// 5.9.2.2 (2015/11/20)
				flag = rpr.initialDataSet();
				if( flag ) { flag = rpr.execute(); }
				if( flag ) { fgkan = rpr.getFgkan(); }
				errMsg.append( rpr.getErrMsg() ).append( CR );
			}
		}
		catch( final RuntimeException ex ) {
			errMsg.append( "ReportProcessing Execute Error! " ).append( CR ) ;
			errMsg.append( "==============================" ).append( CR );
			errMsg.append( ThrowUtil.ogStackTrace( ex ) ).append( CR ) ;				// 6.4.2.0 (2016/01/29)
			flag = false;
		}

		return flag ? fgkan : null ;	// 正常なら、fgkan を、異常なら null を返します。
	}

	/**
	 * 内部変数をクリアします。
	 * このオブジェクトを再利用する場合は、必ずこのメソッドで内部変数の
	 * クリアが必要です。
	 * 注意：このクラス自身は、同期処理は入っていません
	 *
	 * @og.rev 3.8.0.5 (2005/08/26) デーモングループ追加
	 *
	 */
	public void clear() {
		SYSTEM_ID	= null;
		YKNO		= null;
		GROUPID		= null;
		LISTID		= null;
		JOKEN		= null;
		OUT_DIR		= null;		// 5.1.0.0 (2009/11/04) OUTDIR ⇒ OUT_DIR
		OUT_FILE	= null;		// 5.1.0.0 (2009/11/04) OUTFILE ⇒ OUT_FILE
		outputFile	= null;
		isDebug		= false;	// 3.8.5.0 (2006/03/06) デバッグ用のフラグを追加

		FGRUN		= null;
		PRTID		= null;
		LANG		= null;
		PRGDIR		= null;
		PRGFILE		= null;
		DMN_GRP		= null;		// 3.8.0.5 (2005/08/26)
		programFile	= null;

		errMsg.setLength(0);	// 6.1.0.0 (2014/12/26) refactoring
	}

	/**
	 * システムID(SYSTEM_ID)をセットします。
	 *
	 * @param val システムID
	 */
	public void setSystemId( final String val ) { SYSTEM_ID = val; }

	/**
	 * 要求番号(YKNO)をセットします。
	 *
	 * @param val 要求番号
	 */
	public void setYkno( final String val ) { YKNO = val; }

	/**
	 * グループID(GROUPID)をセットします。
	 *
	 * @param val グループID
	 */
	public void setGroupId( final String val ) { GROUPID = val; }

	/**
	 * 帳票ID(LISTID)をセットします。
	 *
	 * @param val 帳票ID
	 */
	public void setListId( final String val ) { LISTID = val; }

	/**
	 * 処理条件(JOKEN)をセットします。
	 *
	 * @param val 処理条件
	 */
	public void setJoken( final String val ) { JOKEN = val; }

	/**
	 * プリンターID(PRTID)をセットします。
	 *
	 * @og.rev 3.8.5.0 (2006/03/06) PRTID が指定されていれば、その値を使用する。なければ NULL
	 * @og.rev 4.3.4.4 (2009/01/01) メソッド名変更
	 *
	 * @param val プリンターID
	 */
	public void setPrtId( final String val ) { PRTID = val; }

	/**
	 * 出力先ディレクトリ(OUT_DIR)をセットします。
	 *
	 * @param val 出力先ディレクトリ
	 */
	public void setOutDir( final String val ) { OUT_DIR = val; }

	/**
	 * 出力先ファイル(OUT_FILE)をセットします。
	 *
	 * @param val 出力先ファイル
	 */
	public void setOutFile( final String val ) { OUT_FILE = val; }

	/**
	 * debugフラグをセットします。
	 *
	 * @og.rev 3.8.5.0 (2006/03/06) デバッグ用のフラグを追加します。
	 *
	 * @param	flag	デバッグフラグ[true:デバッグ/false:通常]
	 */
	public void setDebug( final boolean flag ) { isDebug = flag; }

	/**
	 * 初期データセットを行います。
	 * ここでは、GE53 テーブルより必要な情報を取得します。
	 *
	 * @og.rev 3.8.0.5 (2005/08/26) デーモングループ追加
	 * @og.rev 3.8.5.0 (2006/03/06) プリンタIDが引数から、渡される場合の対応
	 * @og.rev 3.8.6.0 (2006/09/29) 出力先フォルダの自動生成を行います。
	 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
	 * @og.rev 5.1.0.0 (2009/11/04) OUTDIR ⇒ OUT_DIR , OUTFILE ⇒ OUT_FILE カラム名変更
	 * @og.rev 5.5.5.1 (2012/08/07) リソース系DBID 付け忘れ対策
	 *
	 * @param	appInfo	アプリ情報オブジェクト
	 *
	 * @return	結果[true:正常/false:異常]
	 */
	private boolean initialDataSet( final ApplicationInfo appInfo ) {
		final String[] args = new String[] { SYSTEM_ID,JOKEN };
		// fgrun,prtid,lang,prgdir,prgfile
		final String[][] vals = DBUtil.dbExecute( GE53_SELECT,args,appInfo, DBID );	// 5.5.5.1 (2012/08/07)
		if( vals == null || vals.length == 0 ) {
			errMsg.append( "Data does not exist in GE53 table." ).append( CR )
				.append( "==============================" ).append( CR )
				.append( "SYSTEM_ID=[" ).append( SYSTEM_ID )
				.append( "] , JOKEN=[" ).append( JOKEN     ).append( ']' )		// 6.0.2.5 (2014/10/31) char を append する。
				.append( CR );
			return false;
		}

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

		// 3.8.5.0 (2006/03/06) プリンタIDが引数から、渡される場合の対応
		if( PRTID == null ) {
			PRTID = StringUtil.nval( vals[row][GE53_PRTID],PRTID   );
		}

		FGRUN   = StringUtil.nval( vals[row][GE53_FGRUN],	FGRUN	);
		LANG    = StringUtil.nval( vals[row][GE53_LANG],	LANG	);
		PRGDIR  = StringUtil.nval( vals[row][GE53_PRGDIR],	PRGDIR	);
		PRGFILE = StringUtil.nval( vals[row][GE53_PRGFILE],	PRGFILE	);
		DMN_GRP = StringUtil.nval( vals[row][GE53_DMN_GRP],	DMN_GRP );	// 3.8.0.5 (2005/08/26)
		programFile = PRGDIR + FS + PRGFILE ;

		if( OUT_DIR != null  && OUT_DIR.length() > 0 &&
			OUT_FILE != null && OUT_FILE.length() > 0 ) {
				outputFile  = OUT_DIR + FS + OUT_FILE ;
			 	// 3.8.6.0 (2006/09/29) 出力先フォルダの自動生成を行います。
				final File dir = new File(OUT_DIR);
				if( ! dir.exists() && ! dir.mkdirs() ) {
					final String errMsg = "ディレクトリの作成に失敗しました。[" + OUT_DIR + "]";
					throw new HybsSystemException( errMsg );
				}
		}

		return true;
	}

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