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

import org.opengion.fukurou.system.OgRuntimeException ;		// 6.4.2.0 (2016/01/29)
// import java.io.BufferedWriter;
import java.io.PrintWriter;											// 6.3.8.0 (2015/09/11)
import java.io.File;
// import java.io.FileNotFoundException;
// import java.io.FileOutputStream;
// import java.io.OutputStreamWriter;
// import java.io.UnsupportedEncodingException;
// import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.report.AbstractRFIDPrintPointService;
import org.opengion.hayabusa.report.RFIDPrintRequest;
import org.opengion.fukurou.system.Closer ;							// 6.3.8.0 (2015/09/11)
import org.opengion.fukurou.util.FileUtil;							// 6.3.8.0 (2015/09/11)

import static org.opengion.fukurou.system.HybsConst.CR ;				// 5.9.0.0 (2015/09/04)
import static org.opengion.fukurou.system.HybsConst.FS ;				// 5.9.0.0 (2015/09/04)
import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE ;	// 5.9.0.0 (2015/09/04)

/**
 * XML形式でRFIDデータを作成します。
 * バッチのコールも内部で行います。
 *
 * @og.group 帳票システム
 *
 * @version  5.4.3.0
 * @author	 Masakazu Takahashi
 * @since    JDK6.0,
 */
public class RFIDPrintPointService_DEFAULT extends AbstractRFIDPrintPointService {

//	private static final String CR		= System.getProperty("line.separator");
	private final StringBuilder strXML	= new StringBuilder( BUFFER_MIDDLE );	// XMLはこれに吐く
	private final String	xmlEncode 	= HybsSystem.sys("REPORT_RFID_TEXT_ENCODE");

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

	/**
	 * RFID発行処理。
	 *
	 * XMLを作って、ファイル出力
	 *
	 * @og.rev 6.3.8.0 (2015/09/11) FileUtil#getPrintWriter( File,String ) を使用。
	 *
	 * @return 結果 [true:正常/false:異常]
	 */
	@Override
	public boolean execute(){
		System.out.print( "RRID RequestData Creating ... " );
//		BufferedWriter bw = null;
		PrintWriter    bw = null;				// 6.3.8.0 (2015/09/11)
//		final String filename= outdir;				// 6.3.8.0 (2015/09/11) new File( outdir ) で、直接指定する。
		// 6.3.9.1 (2015/11/27) Found 'DD'-anomaly for variable(PMD)
		final boolean flg;
		try {
			makeXMLheader();
			makeXMLprintHeader();
			makeXMLprintCards();
			makeXMLfooter();

			// 6.3.8.0 (2015/09/11) FileUtil#getPrintWriter( File,String ) を使用。
//			bw = getWriter(filename,false,xmlEncode);
			bw = FileUtil.getPrintWriter( new File( outdir ),xmlEncode ) ;		// 6.3.8.0 (2015/09/11) 
			bw.write( strXML.toString() );
			bw.flush();
//			bw.close();

			// 常に実行する
			makeShellCommand();
			flg = programRun();
		}
		catch ( Throwable ex ) {
			errMsg.append( "RFID Print Request Execution Error. " ).append( CR )
				.append( "==============================" ).append( CR )
				.append( "SYSTEM_ID=[" ).append( systemId ).append( "] , " )
				.append( "YKNO=["    ).append( ykno    ).append( "] , " )
				.append( ex.toString() )
				.append( CR );
//			throw new OgRuntimeException( errMsg.toString() );
			throw new OgRuntimeException( errMsg.toString(), ex );
		}
		finally {
			Closer.ioClose( bw );		// 6.3.8.0 (2015/09/11) 
		}
		return flg;
	}

	/**
	 * Dataタグ開始までを出力します。
	 *
	 * @og.rev 5.4.3.4 (2012/01/12) listid
	 * @og.rev 5.4.3.9 (2012/01/25) layoutFile (新帳票のみ)
	 */
//	private void makeXML_header(){
	private void makeXMLheader(){
		strXML.append( "<?xml version=\"1.0\" encoding=\"").append( xmlEncode ).append("\" ?>" ).append( CR )
			.append( "<RfidEvent>" ).append( CR )
			.append( "<Type>210</Type>" ).append( CR )			// 210固定
			.append( "<SubType>1</SubType>" ).append( CR )		// 1固定
			.append( "<Id>").append( listid ).append("</Id>" ).append( CR )	// 指定なし-> 5.4.3.4 listid
			.append( "<LayoutFilename>").append( layoutFile ).append("</LayoutFilename>" ).append( CR )	// 5.4.3.9 追加
			.append( "<SiteName>" ).append( hostName ).append( "</SiteName>" ).append( CR )
		//strXML.append( "<DeviceName>" ).append( prtName ).append( "</DeviceName>" ).append( CR )
			.append( "<DeviceName>" ).append( prtid ).append( "</DeviceName>" ).append( CR ) // 5.4.3.9 nameからidへ
			.append( "<Data>" ).append( CR );
	}

	/**
	 * printHeaderタグを出力します。
	 * カラム数分のデータができます
	 *
	 * @og.rev 5.4.3.9 (2012/01/25) GE58はなくてもよい
	 */
//	private void makeXML_printHeader(){
	private void makeXMLprintHeader(){
		strXML.append( "<PrintHeader systemId=\"" ).append( systemId ).append( "\" demandNo=\"" )
						.append( ykno ).append( "\">" ).append( CR );

		for( int clmNo=0; clmNo<table.getColumnCount(); clmNo++ ) {
			final String clmNm = table.getColumnName( clmNo );

			final String[] rfidConf = rfidLayout.get( clmNm );
//			if( rfidConf == null ) {
//				// 5.4.3.9 なくてもエラーにしない
//				errMsg.append( "Column does not Exists in GE58. " ).append( CR );
//				errMsg.append( "==============================" ).append( CR );
//				errMsg.append( "SYSTEM_ID=[" ).append( systemId ).append( "] , " );
//				errMsg.append( "YKNO=["    ).append( ykno    ).append( "] , " );
//				errMsg.append( "COLUMN=["    ).append( table.getColumnName( clmNo )    ).append( "]" );
//				errMsg.append( CR );
//				throw new OgRuntimeException( errMsg.toString() );
//			}
//			else{
			if( rfidConf != null ) {
				strXML.append( "<Col name=\"" ).append( clmNm ).append( '"' ).append( CR )
					.append( " kbout=\"" ).append( rfidConf[RFIDPrintRequest.GE58_KBOUT] ).append( '"' ).append( CR )
					.append( " data1=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA1] ).append( '"' ).append( CR )
					.append( " data2=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA2] ).append( '"' ).append( CR )
					.append( " data3=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA3] ).append( '"' ).append( CR )
					.append( " data4=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA4] ).append( '"' ).append( CR )
					.append( " data5=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA5] ).append( '"' ).append( CR )
					.append( " data6=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA6] ).append( '"' ).append( CR )
					.append( " data7=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA7] ).append( '"' ).append( CR )
					.append( " data8=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA8] ).append( '"' ).append( CR )
					.append( " data9=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA9] ).append( '"' ).append( CR )
					.append( " data10=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA10] ).append( '"' ).append( CR )
					.append( " data11=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA11] ).append( '"' ).append( CR )
					.append( " data12=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA12] ).append( '"' ).append( CR )
					.append( " data13=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA13] ).append( '"' ).append( CR )
					.append( " data14=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA14] ).append( '"' ).append( CR )
					.append( " data15=\"" ).append( rfidConf[RFIDPrintRequest.GE58_DATA15] ).append( '"' )
					.append( " />" ).append(	CR );
			}
		}

		strXML.append( "</PrintHeader>" ).append( CR );
	}

	/**
	 * printCardsタグ開始までを出力します。
	 * 印刷枚数分のデータができます
	 */
//	private void makeXML_printCards(){
	private void makeXMLprintCards(){
		strXML.append( "<PrintCards>" ).append( CR );

		for( int rowNo=0; rowNo<table.getRowCount(); rowNo++ ) {
			strXML.append( "<PrintCard control=\"" ).append( fgrun ).append( "\" edno=\"" )
				.append( Integer.toString( rowNo+1 ) ).append( "\">" ).append( CR );

			// カラム単位の処理
			for( int clmNo=0; clmNo<table.getColumnCount(); clmNo++ ) {
				strXML.append( "<ColData name=\"" ).append( table.getColumnName( clmNo ) ).append("\">")
					.append( table.getValue( rowNo, clmNo ) )
					.append( "</ColData>" ).append( CR );
			}

			strXML.append( "</PrintCard>" ).append( CR );
		}

		strXML.append( "</PrintCards>" ).append( CR );
	}

	/**
	 * Dataタグ終了から最後までを出力します。
	 */
//	private void makeXML_footer(){
	private void makeXMLfooter(){
		strXML.append( "</Data>" ).append( CR )
			.append( "<Time>systemstamp</Time>" ).append( CR )				// systemstamp固定
			.append( "<SourceName>null</SourceName>" ).append( CR )
			.append( "<CorrelationId>null</CorrelationId>" ).append( CR )
			.append( "</RfidEvent>" ).append( CR );
	}

//	/**
//	 * XMLファイル書き込み用のライターを返します。
//	 *
//	 * @og.rev 6.3.8.0 (2015/09/11) FileUtil#getPrintWriter( File,String ) を使用。廃止。
//	 *
//	 * @param fileName ファイル名
//	 * @param append アベンドするか
//	 * @param encode エンコード
//	 *
//	 * @return ライター
//	 */
//	private BufferedWriter getWriter( final String fileName, final boolean append, final String encode) {
//		final File file = new File ( fileName );
//		BufferedWriter bw;
//
//		try {
//			bw = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( file, append ), encode ) );
//		}
//		catch ( UnsupportedEncodingException ex ) {
//			errMsg.append( "[ERROR] Input File is written by Unsupported Encoding" );
//			throw new HybsSystemException( ex );
//		}
//		catch ( FileNotFoundException ex ) {
//			errMsg.append( "[ERROR] File not Found" );
//			throw new HybsSystemException( ex );
//		}
//		return bw;
//	}

	/**
	 * シェルコマンドの文字列を作成します。
	 *
	 * @og.rev 5.4.3.9 引数変更
	 *
	 * @return 結果 [true:正常/false:異常]
	 */
	private boolean makeShellCommand() {
		final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
//			.append( prgdir + HybsSystem.FS + prgfile ).append( " " )		// 実行するコマンド
			.append( prgdir ).append( FS ).append( prgfile ).append( ' ' )	// 実行するコマンド
			.append( '"' ).append( ykno		).append( "\" " )			// 引数１：要求NO
			.append( '"' ).append( prtid	).append( "\" " )			// 引数２：プリンタID
			.append( '"' ).append( prtName	).append( "\" " )			// 引数３：プリンタID
			.append( '"' ).append( hostName ).append( "\" " )			// 引数４：ホスト名
			.append( '"' ).append( portnm	).append( "\" " );			// 引数５：プリンタポート 5.4.3.1(2011/12/27)

		shellCmd = buf.toString();
		System.out.println( CR + shellCmd + CR );

		return true;
	}
}
