/*
 * 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.fukurou.db.DBUtil;
import org.opengion.fukurou.db.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;

import static org.opengion.fukurou.system.HybsConst.CR ;			// 5.9.0.0 (2015/09/04)
import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;	// 6.4.2.1 (2016/02/05)

/**
 * 帳票システムでCSV出力をする際に、データを加工、プラグインの呼び出しを行うクラスです。
 *
 * @og.group 帳票システム
 *
 * @version  4.0
 * @author   Takahashi Masakazu
 * @since    JDK8.0,
 */
public class CSVPrintRequest {
	private final StringBuilder errMsg = new StringBuilder( BUFFER_MIDDLE );		// 6.4.2.1 (2016/02/05)

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

	// 受け渡し変数
	private final String	SYSTEM_ID	;
	private final String	YKNO		;
	private final String	LISTID		;
	private final String	LANG		;
	private final String	FGRUN		;	// G:CSV(print) H:CSV(Excel) I:CSV(PDF)
	private final String	PRTID		;
	private final String	PRGDIR		;
	private final String	PRGFILE		;
	private final String	OUTDIR		;
	private final String	FILENAME	;	// 雛形ファイル名
	private final boolean	DEBUG		;

	private final String	GRPID		;	// 5.9.2.2 (2015/11/20)
	private final String	DMNGRP		;	// 5.9.2.2 (2015/11/20)

	// オブジェクト変数
	private boolean		fgLOCAL		;
	private String		prtName		;
	private String		hostName	;
	private String		portnm		;
	private String		fgkan		= GE50Access.FG_ERR2;	// 初期値エラー
	private String		option		;						// 5.9.3.0 (2015/12/04)

	private int			bodyCount	;						// 5.9.2.7 (2015/11/27) bodyCount 追加

	// GE54 の帳票定義情報を取得するSQL文です。
	private static final String GE54_SELECT =
		"SELECT BSQL,FGLOCAL,SYSTEM_ID,HSQL,FSQL" +
		" ,OPTIONS,FGCUT" +									// 5.9.3.0 (2015/12/04)
		" 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;
	private static final int GE54_OPTIONS	= 5;			// 5.9.3.0 (2015/12/04)
	// private static final int GE54_FGCUT		= 6;			// 5.9.3.0 (2015/12/04)

//	// 5.4.4.0 (2012/02/01) 互換モード対応漏れ
//	// 6.9.5.0 (2018/04/23) VER4_COMPATIBLE_MODE 廃止
//	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) 互換モード
	// 6.9.5.0 (2018/04/23) VER4_COMPATIBLE_MODE 廃止
	private static final String GE55_SELECT =
//		"SELECT PRTNM,"+HOST+",SYSTEM_ID,PORTNM" +
		"SELECT PRTNM,HOST_ID,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;

	// コネクションにアプリケーション情報を追記するかどうか指定
	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 付け忘れ対応

	/**
	 * コンストラクター。
	 *
	 * 引数を受けとって、インスタンスを作成します。
	 * 
	 * @og.rev 5.9.2.2 (2015/11/20) grpid,dmngrp
	 *
	 * @param systemId システムID
	 * @param ykno 要求番号
	 * @param listId 帳票ID
	 * @param lang 言語
	 * @param fgrun 実行方法
	 * @param prtid プリンタID
	 * @param prgdir プログラムディレクトリ
	 * @param prgfile プログラムファイル
	 * @param outdir 出力ディレクトリ
	 * @param filename 出力ファイル
	 * @param grpid グループID
	 * @param dmngrp デーモングループ
	 * @param isDebug デバッグフラグ
	 */
	public CSVPrintRequest( 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 filename
							, final String grpid, final String dmngrp, final boolean isDebug ) {	// 5.9.2.2 (2015/11/20)
		SYSTEM_ID	= systemId;
		YKNO		= ykno;
		LISTID		= listId;
		LANG		= lang;
		FGRUN		= fgrun;
		PRTID		= prtid;
		PRGDIR		= prgdir;
		PRGFILE		= prgfile;
		OUTDIR		= outdir;
		FILENAME	= filename;
		GRPID		= grpid;
		DMNGRP		= dmngrp;
		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 5.9.3.0 (2015/12/04) 
	 *
	 * @return 結果 [true:正常/false:異常]
	 */
	public boolean initialDataSet() {

		// ===== GE54 から帳票定義情報を取得します =========================================
		final String[] args = new String[] { SYSTEM_ID,LISTID };
		final 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 )
				.append( "==============================" ).append( CR )
				.append( "SYSTEM_ID=[" ).append( SYSTEM_ID ).append( "] , LISTID=[" ).append( LISTID ).append( ']' )
				.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; }
		}

		// GE54のbSQLは廃止となっているので下方で別で取る

		// ローカルリソースフラグ
		final String localFlag = vals[row][GE54_FGLOCAL];
		fgLOCAL = localFlag != null && "1".equals( localFlag.trim() ) ;

		option = vals[row][GE54_OPTIONS];		// 5.9.3.0 (2015/12/04)

		// ===== GE55 から出力先マスタ情報を取得します =========================================
		final String[] argsGe55 = new String[] { SYSTEM_ID,PRTID };
		final String[][] valsGe55 = DBUtil.dbExecute( GE55_SELECT,argsGe55,appInfo, DBID );
		if( valsGe55 == null || valsGe55.length == 0 ) {
			errMsg.append( "Data does not exist in GE55 table." ).append( CR )
				.append( "==============================" ).append( CR )
				.append( "SYSTEM_ID=[" ).append( SYSTEM_ID ).append( "] , PRTID=[" ).append( PRTID ).append( ']' )
				.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;
	}

	/**
	 * 発行用データを作成し、発行リクエストの処理を行います。
	 *
	 * @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追加
	 * @og.rev 5.9.2.2 (2015/11/20) GRPID,DEMGRP
	 * @og.rev 5.9.2.3 (2015/11/27) rowCount
	 * @og.rev 5.9.2.7 (2015/11/27) bodyCount 追加
	 * @og.rev 5.9.3.0 (2015/12/04) option
	 *
	 * @return 結果 [true:正常/false:異常]
	 */
	public boolean execute() {
		System.out.print( "CSV RequestData Creating ... " );

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

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

		bodyCount = table.getRowCount(); // 5.9.2.3 (2015/11/27)

		// ヘッダフッタも渡す
		tmc = new DBTableModelCreator( SYSTEM_ID, LISTID, YKNO, "H", resource );
		final DBTableModel tableH = tmc.getTable();
		tmc = new DBTableModelCreator( SYSTEM_ID, LISTID, YKNO, "F", resource );
		final DBTableModel tableF = tmc.getTable();

		// 発行用クラスを実行する。
		CSVPrintPointService service = null;
		try {
			service = (CSVPrintPointService)StringUtil.newInstance( HybsSystem.sys( "REPORT_CSV_SERVICE_CLASS" ) );
			service.setYkno( YKNO );
			service.setSystemId( SYSTEM_ID );
			service.setFgrun( FGRUN );
			service.setHostName( hostName );
			service.setPrinterName( prtName );
			service.setTable( table );
			service.setTableH( tableH );
			service.setTableF( tableF );
			service.setPrgDir( PRGDIR );
			service.setPrgFile( PRGFILE );
			service.setOutDir( OUTDIR );
			service.setPrtId( PRTID );
			service.setPortnm( portnm );
			service.setListId( LISTID );
			service.setModelname( FILENAME );
			service.setGrpId( GRPID );			// 5.9.2.2 (2015/11/20)
			service.setDmnGrp( DMNGRP );		// 5.9.2.2 (2015/11/20)
			service.setOption( option );		// 5.9.3.0 (2015/12/04)

			final boolean flag = service.execute();

			fgkan = service.getFgkan();	

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

			if( ! flag ){ 
				errMsg.append( service.getErrMsg() );
				return false;
			}
		}
		catch( final Throwable ex ) {
			fgkan = GE50Access.FG_ERR2; // エラー時はアプリエラーにしておく
			errMsg.append( "CSV Print Request Execution Error. " ).append( CR )
				.append( "==============================" ).append( CR )
				.append( "SYSTEM_ID=[" ).append( SYSTEM_ID ).append( "] , YKNO=[" ).append( YKNO ).append( ']' ).append( CR )
				.append( HybsSystem.sys( "REPORT_CSV_SERVICE_CLASS" ) ).append( CR )
				.append( ex.toString() )
				.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();
	}

	/**
	 * 完了フラグを返します。
	 *
	 *
	 * @return 完了フラグ String
	 */
	public String getFgkan() {
		return fgkan;
	}

	/**
	 * 処理件数(bodyの件数)を返します。
	 * 
	 * @og.rev 5.9.2.7 (2015/11/27) bodyCount 追加
	 *
	 * @return 処理件数 int
	 */
	public int getBodyCount() {
		return bodyCount;
	}
}
