/*
 * 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.report2;

import java.io.File;

import org.opengion.hayabusa.db.DBTableModel;

/**
 * 帳票処理要求を管理するキューオブジェクトです。
 * このオブジェクトでは、帳票の定義及びデータと、処理中に発生したエラーメッセージを管理します。
 * また、このキューを生成したオブジェクトもこのオブジェクトにセットされます。
 *
 * @og.group 帳票システム
 *
 * @version  4.0
 * @author   Hiroki.Nakamura
 * @since    JDK1.6
 */
public class ExecQueue {

	/** 実行方法 {@value} */
	protected static final String OUT_ODS_ONLY		= "1";
	/** 実行方法 {@value} */
	protected static final String OUT_PRINT_ONLY	= "2";
	/** 実行方法 {@value} */
	protected static final String OUT_ODS_PRINT		= "3";
	/** 実行方法 {@value} */
	protected static final String OUT_ODS_PDF		= "P";
	/** 実行方法 {@value} */
	protected static final String OUT_ODS_PRINT_PDF	= "Q";
	/** 実行方法 {@value} */
	protected static final String OUT_ODS_EXCEL		= "E";
	/** 実行方法 {@value} */
	protected static final String OUT_ODS_ODS		= "S"; // 4.3.3.4 (2008/11/01) 追加
	/** 実行方法 {@value} */
	protected static final String IN_INPUT_ONLY		= "5";
	/** 実行方法 {@value} */
	protected static final String IN_EXEC_ONLY		= "6";
	/** 実行方法 {@value} */
	protected static final String IN_INPUT_EXEC		= "7";
	/** 実行方法 {@value} */
	protected static final String RFID_PRINT		= "A";
	/** 実行方法 {@value} */
	protected static final String RFID_ALLPRINT		= "B";
	/** 実行方法 {@value} */
	protected static final String RFID_ALLERASE		= "C";
	/** 実行方法 {@value} */
	protected static final String RFID_SEQERASE		= "D";

	/** 最大シート数 {@value} */
	protected static final int MAX_SHEETS_PER_FILE	= 256; // 5.1.2.0 (2010/01/01)

	private String		ykno		= null;
	private String		systemId	= null;
	private DBTableModel body		= null;
	private DBTableModel header		= null;
	private DBTableModel footer		= null;
//	private String		bsql		= null; // 5.1.2.0 (2010/01/01)
//	private String		hsql		= null; // 5.1.2.0 (2010/01/01)
//	private String		fsql		= null; // 5.1.2.0 (2010/01/01)
	private String		listId		= null;
	private String		pdfPasswd	= null;
	private String		lang		= null;
	private String		threadId	= null;
	private String		templateName = null;
	private String		outputType	= null;
	private String		printerName	= null;
	private String		outputName	= null;
	private boolean		fglocal		= false;
//	private boolean		fgdirect	= false;
	private boolean		fgcut		= false;
	private QueueManager manager	= null;
	private String		prgdir		= null;		// 4.3.3.0 (2008/10/01) 板金RFID対応。
	private String		prgfile		= null;		// 4.3.3.0 (2008/10/01)
	private String		prtid		= null;		// 4.3.3.0 (2008/10/01)

	private int			pageCnt		= 0;		// 5.1.2.0 (2010/01/01) 処理したページ数
	private int			rowCnt		= 0;		// 5.1.2.0 (2010/01/01) 処理した行数
//	private boolean		isEnd		= false;	// 5.1.2.0 (2010/01/01) 全データが処理されたか
	private boolean		isDataEnd	= false;	// 5.1.2.0 (2010/01/01) 全データが処理されたか (メソッド名と同じ変数名変更)

	private final StringBuilder errMsg = new StringBuilder();

	/**
	 * 要求NOをセットします。
	 *
	 * @param ykno 要求NO
	 */
	public void setYkno( final String ykno ) {
		this.ykno = ykno;
	}

	/**
	 * 要求NOを取得します。
	 *
	 * @return	要求NO
	 */
	public String getYkno() {
		return ykno;
	}

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

	/**
	 * システムIDを取得します。
	 *
	 * @return  StringシステムID
	 */
	public String getSystemId() {
		return systemId;
	}

	/**
	 * ボディー部分のDBTableModelをセットします。
	 *
	 * @param body DBTableModelオブジェクト
	 */
	public void setBody( final DBTableModel body ) {
		this.body = body;
	}

	/**
	 * ボディー部分のDBTableModelを取得します。
	 *
	 * @return	ボディー部分のDBTableModelオブジェクト
	 */
	public DBTableModel getBody() {
		return body;
	}

	/**
	 * ヘッダー部分のDBTableModelをセットします。
	 *
	 * @param header DBTableModelオブジェクト
	 */
	public void setHeader( final DBTableModel header ) {
		this.header = header;
	}

	/**
	 * ヘッダー部分のDBTableModelを取得します。
	 *
	 * @return	ヘッダー部分のDBTableModelオブジェクト
	 */
	public DBTableModel getHeader() {
		return header;
	}

	/**
	 * フッター部分のDBTableModelをセットします。
	 *
	 * @param footer DBTableModelオブジェクト
	 */
	public void setFooter( final DBTableModel footer ) {
		this.footer = footer;
	}

	/**
	 * フッター部分のDBTableModelを取得します。
	 *
	 * @return	フッター部分のDBTableModelオブジェクト
	 */
	public DBTableModel getFooter() {
		return footer;
	}

	/**
	 * ボディー部分のDBTableModelを作成するためのSQL文をセットします。
	 *
 	 * @og.rev 5.1.2.0 (2010/01/01) 廃止(クラス内部で直接分割)
	 *
	 * @see QueueManager_DB.DBTableModelCreator
	 * @param bsql
	 */
//	public void setBsql( final String bsql ) {
//		this.bsql = bsql;
//	}

	/**
	 * ボディー部分のDBTableModelを作成するためのSQL文を取得します。
	 *
 	 * @og.rev 5.1.2.0 (2010/01/01) 廃止(クラス内部で直接分割)
	 *
	 * @see QueueManager_DB.DBTableModelCreators
	 *
	 * @return ボディーSQL
	 */
//	public String getBsql() {
//		return bsql;
//	}

	/**
	 * ヘッダー部分のDBTableModelを作成するためのSQL文をセットします。
	 *
 	 * @og.rev 5.1.2.0 (2010/01/01) 廃止(クラス内部で直接分割)
	 *
	 * @see QueueManager_DB.DBTableModelCreator
	 * @param hsql
	 */
//	public void setHsql( final String hsql ) {
//		this.hsql = hsql;
//	}

	/**
	 * ヘッダー部分のDBTableModelを作成するためのSQL文を取得します。
	 *
 	 * @og.rev 5.1.2.0 (2010/01/01) 廃止(クラス内部で直接分割)
	 *
	 * @see QueueManager_DB.DBTableModelCreator
	 *
	 * @return ヘッダーSQL
	 */
//	public String getHsql() {
//		return hsql;
//	}

	/**
	 * フッター部分のDBTableModelを作成するためのSQL文をセットします。
	 *
 	 * @og.rev 5.1.2.0 (2010/01/01) 廃止(クラス内部で直接分割)
	 *
	 * @see QueueManager_DB.DBTableModelCreator
	 * @param fsql
	 */
//	public void setFsql( final String fsql ) {
//		this.fsql = fsql;
//	}

	/**
	 * フッター部分のDBTableModelを作成するためのSQL文を取得します。
	 *
 	 * @og.rev 5.1.2.0 (2010/01/01) 廃止(クラス内部で直接分割)
	 *
	 * @see QueueManager_DB.DBTableModelCreator
	 *
	 * @return フッターSQL
	 */
//	public String getFsql() {
//		return fsql;
//	}

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

	/**
	 * 帳票IDを取得します。
	 *
	 * @return 帳票ID
	 */
	public String getListId() {
		return listId;
	}

	/**
	 * PDFパスワードをセットします。
	 *
	 * @param pdfPasswd PDFパスワード
	 */
	public void setPdfPasswd( final String pdfPasswd ) {
		this.pdfPasswd = pdfPasswd;
	}

	/**
	 * PDFパスワードを取得します。
	 *
	 * @return PDFパスワード
	 */
	public String getPdfPasswd() {
		return pdfPasswd;
	}

	/**
	 * 言語をセットします。
	 *
	 * @param lang 言語
	 */
	public void setLang( final String lang ) {
		this.lang = lang;
	}

	/**
	 * 言語を取得します。
	 *
	 * @return 言語
	 */
	public String getLang() {
		return lang;
	}

	/**
	 * 雛形ファイル名をセットします。
	 *
	 * @param templateName 雛形ファイル名
	 */
	public void setTemplateName( final String templateName ) {
		this.templateName = templateName;
	}

	/**
	 * 雛形ファイル名を取得します。
	 *
	 * @return 帳票雛形ファイル名
	 */
	public String getTemplateName() {
		return templateName;
	}

	/**
	 * 実行方法をセットします。
	 *
	 * @param outputType 実行方法
	 */
	public void setOutputType( final String outputType ) {
		this.outputType = outputType;
	}

	/**
	 * 出力タイプを取得します。
	 *
	 * @return 出力タイプ
	 */
	public String getOutputType() {
		return outputType;
	}

	/**
	 * プリンター名をセットします。
	 *
	 * @param  printerName プリンター名
	 */
	public void setPrinterName( final String printerName ) {
		this.printerName = printerName;
	}

	/**
	 * プリンター名を取得します。
	 *
	 * @return プリンタ名
	 */
	public String getPrinterName() {
		return printerName;
	}

	/**
	 * 処理要求を処理するスレッドIDをセットします。
	 *
	 * @param threadId スレッドID
	 */
	public void setThreadId( final String threadId ) {
		this.threadId = threadId;
	}

	/**
	 * 処理要求を処理するスレッドIDを取得します。
	 *
	 * @return スレッドID
	 */
	public String getThreadId() {
		return threadId;
	}

	/**
	 * 出力ファイル名をセットします。
	 *
	 * @param outputName 出力ファイル名
	 */
	public void setOutputName( final String outputName ) {
		this.outputName = outputName;
	}

	/**
	 * 出力ファイル名を設定します。
	 * GE50に設定されていない場合は第四引数(要求番号)を利用する。
	 * その場合、タイプに応じた拡張子が自動設定される。
	 *
	 * ".xls" : OUT_ODS_EXCEL
	 * ".pdf" : OUT_ODS_PDF , OUT_ODS_PRINT_PDF
	 * ".ods" : OUT_ODS_ODS
	 * ".xml" : RFID_PRINT , RFID_ALLPRINT , RFID_ALLERASE , RFID_SEQERASE
	 *
	 * @og.rev 4.3.3.4 (2008/11/01) ODS出力対応
	 * @og.rev 5.4.3.0 (2011/12/26) RFIDデフォルト対応
	 * @og.rev 5.4.4.1 (2012/02/03) RFID拡張子変更
	 *
	 * @param	outputDir	出力ディレクトリ名
	 * @param	outputFile	出力ファイル名
	 * @param	type		タイプ
	 * @param	yokyu		要求番号(ファイル名が指定されていない場合のファイル名)
	 *
	 */
	public void setOutputName( final String outputDir, final String outputFile, final String type, final String yokyu ){
		StringBuilder filePath = new StringBuilder();
		filePath.append( outputDir + File.separator );

		if( outputFile == null || outputFile.length() == 0 ){ // ファイル名が指定されていない場合は要求番号を利用する。
			if( OUT_ODS_EXCEL.equals( type ) ){
				filePath.append( yokyu );
				filePath.append( ".xls" );
			}
			else if( OUT_ODS_PDF.equals( type ) || OUT_ODS_PRINT_PDF.equals( type ) ){
				filePath.append( yokyu );
				filePath.append( ".pdf" );
			}
			// 4.3.3.4 (2008/11/01) 追加
			else if( OUT_ODS_ODS.equals ( type ) ){
				filePath.append( yokyu );
				filePath.append( ".ods" );
			}
			// 5.4.3.0 (2011/12/26) 追加
			// 5.4.4.2 (2012/02/03) .txtではなく.xml
			else if( ExecQueue.RFID_PRINT.equals( type ) || ExecQueue.RFID_ALLPRINT.equals( type )
					|| ExecQueue.RFID_ALLERASE.equals( type ) || ExecQueue.RFID_SEQERASE.equals( type ) ) {
				filePath.append( yokyu );
				filePath.append( ".xml" ); //txt-xml
			}
		}
		else {
			filePath.append( outputFile );
		}

		this.outputName = filePath.toString();
	}

	/**
	 * 出力ファイル名を取得します。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) 256シートを超える場合に対応。2ファイル目以降は、_1、_2･･･をファイル名の後ろにつける
	 *
	 * @return 出力先ファイル名
	 */
	public String getOutputName() {
		if( pageCnt <= MAX_SHEETS_PER_FILE ) {
			return outputName;
		}
		else {
			StringBuilder fileName = new StringBuilder();

			int idx = outputName.lastIndexOf( '.' );
			String name = outputName.substring( 0, idx );
			String suffix = outputName.substring( idx );
			int addNo = (int)Math.ceil( (double)pageCnt/(double)MAX_SHEETS_PER_FILE ) - 1;
//			String addName = "_" + String.valueOf( addNo );

//			fileName.append( name ).append( addName ).append( suffix );;
			fileName.append( name ).append( "_" ).append( addNo ).append( suffix );

			return fileName.toString();
		}
	}

	/**
	 * 実行ファイルディレクトリを指定します。
	 *
	 * @og.rev 4.3.3.0 (2008/10/01) 板金RFID対応
	 *
	 * @param dir ディレクトリ
	 */
	public void setPrgDir( final String dir ) {
		this.prgdir = dir;
	}

	/**
	 * 実行ファイルディレクトリを取得します。
	 *
	 * @og.rev 4.3.3.0 (2008/10/01) 板金RFID対応
	 *
	 * @return プログラムディレクトリ
	 */
	public String getPrgDir() {
		return prgdir;
	}

	/**
	 * 実行ファイル名をセットします。
	 *
	 * @og.rev 4.3.3.0 (2008/10/01) 板金RFID対応
	 * @param	file	ファイル名
	 */
	public void setPrgFile( final String file ) {
		this.prgfile = file;
	}

	/**
	 * 実行ファイル名を取得します。
	 *
	 * @og.rev 4.3.3.0 (2008/10/01) 板金RFID対応
	 *
	 * @return プログラムファイル名
	 */
	public String getPrgFile() {
		return prgfile;
	}

	/**
	 * プリンタIDをセットします。
	 *
	 * @og.rev 4.3.3.0 (2008/10/01) 板金RFID対応
	 * @param	id	プリンタID
	 */
	public void setPrtId( final String id ) {
		this.prtid = id;
	}

	/**
	 * プリンタIDを取得します。
	 *
	 * @og.rev 4.3.3.0 (2008/10/01) 板金RFID対応
	 *
	 * @return プリンタID
	 */
	public String getPrtId() {
		return prtid;
	}

	/**
	 * ローカルリソース使用フラグをセットします。
	 *
	 * @param	fglocal	ローカルリソース使用フラグ[true:使用する/false:使用しない]
	 */
	public void setFglocal( final boolean fglocal ) {
		this.fglocal = fglocal;
	}

	/**
	 * ローカルリソース使用フラグを取得します。
	 *
	 * @return ロールリソース使用フラグ[true:使用する/false:使用しない]
	 */
	public boolean isFglocal() {
		return fglocal;
	}

//	/**
//	 * @param fgdirect
//	 */
//	public void setFgdirect( final boolean fgdirect ) {
//		this.fgdirect = fgdirect;
//	}

//	/**
//	 * @return ダイレクト出力フラグ
//	 */
//	public boolean isFgdirect() {
//		return fgdirect;
//	}

	/**
	 * ページエンドカットフラグをセットします。
	 *
	 * @param fgcut ページエンドカットの使用可否[true:使用/false:通常]
	 */
	public void setFgcut( final boolean fgcut ) {
		this.fgcut = fgcut;
	}

	/**
	 * ページエンドカットフラグを取得します。
	 *
	 * @return ページエンドカットフラグ
	 */
	public boolean isFgcut() {
		return fgcut;
	}

	/**
	 * キューマネージャーをセットします。
	 *
	 * @param manager キューマネージャー
	 */
	public void setManager( final QueueManager manager ) {
		this.manager = manager;
	}

	/**
	 * 帳票処理データをセットします。
	 * 既にテーブルモデルがセットされている場合は、再セットしません。
	 *
	 */
	public void setData() {
		if( body == null && manager != null ) {
			manager.set( this );
		}
	}

	/**
	 * キューを実行中の状態に更新します。
	 *
	 */
	public void setExecute() {
		if( manager != null ) {
			manager.execute( this );
		}
	}

	/**
	 * キューを完了済の状態に更新します。
	 *
	 */
	public void setComplete() {
		if( manager != null ) {
			manager.complete( this );
		}
	}

	/**
	 * キューをエラーの状態に更新します。
	 */
	public void setError() {
		if( manager != null ) {
			manager.error( this );
		}
	}

	/**
	 * エラーメッセージをセットします。
	 *
	 * @param msg エラーメッセージ
	 */
	public void addMsg( final String msg ) {
//		this.msg.append( msg );
		errMsg.append( msg );
	}

	/**
	 * エラーメッセージを取得します。
	 *
	 * @return エラーメッセージ
	 */
	public String getMsg() {
//		return msg.toString();
		return errMsg.toString();
	}

	/**
	 * 処理したページ数を引数の分だけカウントアップします。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) 新規追加
	 *
	 * @param pgs カウントアップするページ数
	 */
	public void addExecPageCnt( final int pgs ) {
		pageCnt += pgs;
	}

	/**
	 * 処理したページ数を返します。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) 新規追加
	 *
	 * @return 処理したページ数
	 */
	public int getExecPagesCnt() {
		return pageCnt;
	}

	/**
	 * 処理した行数をセットします。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) 新規追加
	 *
	 * @param rws 処理した行数
	 */
	public void setExecRowCnt( final int rws ) {
		rowCnt = rws;
	}

	/**
	 * 処理した行数を返します。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) 新規追加
	 *
	 * @return 処理した行数
	 */
	public int getExecRowCnt() {
		return rowCnt;
	}

	/**
	 * 全ての行が処理されたかをセットします。
	 *
	 * これは、処理結果が、256シートを超えていた場合、再度残りのデータについて
	 * 処理を行うかどうかの判定するために、利用します。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) 新規追加
	 *
	 * @param flag 全ての行が処理されたか
	 */
	public void setEnd( final boolean flag ) {
		isDataEnd = flag;
	}

	/**
	 * 全ての行が処理されているかを返します。
	 *
	 * これは、処理結果が、256シートを超えていた場合、再度残りのデータについて
	 * 処理を行うかどうかの判定するために、利用します。
	 *
	 * @og.rev 5.1.2.0 (2010/01/01) 新規追加
	 *
	 * @return 全ての行が処理されたか
	 */
	public boolean isEnd() {
		return isDataEnd;
	}
}
