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

import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.db.AbstractTableFilter;
import org.opengion.hayabusa.db.DBTableModel;

/**
 * TableFilter_JUDG は、TableFilter インターフェースを継承した、DBTableModel 処理用の
 * 実装クラスです。
 *
 * 必要なカラムから、判定結果(JUDG) と 判定理由(RIYU) を設定します。
 * これは、GG10 の発生日(DY_HATU),登録ｷｰ(SET_KEY),設定ｸﾞﾙｰﾌﾟ(SET_GRP),ﾄｰｸﾝ(TOKEN) の
 * ﾚｺｰﾄﾞを処理して、判定結果を設定します。
 *
 * GG10 書き込むﾃｰﾌﾞﾙ (必須ｶﾗﾑ)
 *   値ﾃﾞｰﾀ(VAL)			値の設定(存在、上限、下限判定)
 *   判定結果(JUDG)			0:未決 1:不要 2:任意 3:合格 4:保留 5:警告 6:必須 7:不合格
 *   判定理由(RIYU)			上限、下限で判定した結果が入っている。titleに入れてﾎﾟｯﾌﾟｱｯﾌﾟさせる
 *
 * GG01 ﾄｰｸﾝﾏｽﾀ (GG02がnullの時)
 *   ﾃﾞｰﾀ型(DATA_TYPE)		EDITORを決定
 *
 * 	GG02 雛形設定ﾏｽﾀ
 *   登録方法(CDREC)		0:未決 1:不要 2:任意 4:保留 6:必須
 *   異常下限(E_MIN)		異常値の下限判定に使用
 *   警告下限(W_MIN)		警告値の下限判定に使用
 *   警告上限(W_MAX)		警告値の上限判定に使用
 *   異常上限(E_MAX)		異常値の上限判定に使用
 *
 * @og.formSample
 * ●形式：
 *      ① &lt;og:tableFilter classId="JUDG" /&gt;
 *
 * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを追加
 *
 * @version  0.9.0  2000/10/17
 * @author   Kazuhiko Hasegawa
 * @since    JDK1.1,
 */
public class TableFilter_JUDG extends AbstractTableFilter {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "7.3.1.1 (2021/02/25)" ;

	private int noVal		= -1;
	private int noJudg		= -1;
	private int noRiyu		= -1;

	private int noType		= -1;

	private int noCdrec		= -1;
	private int noEmin		= -1;
	private int noWmin		= -1;
	private int noWmax		= -1;
	private int noEmax		= -1;

	private DBTableModel table ;

	/**
	 * デフォルトコンストラクター
	 *
	 * @og.rev 6.4.1.1 (2016/01/16) keysMap を、サブクラスから設定させるように変更。
	 */
	public TableFilter_JUDG() { super(); }

	/**
	 * DBTableModel処理を実行します。
	 *
	 * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加
	 *
	 * @return 処理結果のDBTableModel
	 */
	public DBTableModel execute() {
		table = getDBTableModel();
		if( table == null ) { return table; }				// 6.4.0.5 (2016/01/09)

		noVal	= table.getColumnNo( "VAL"				);	// 必須
		noJudg	= table.getColumnNo( "JUDG"				);	// 必須
		noRiyu	= table.getColumnNo( "RIYU"				);	// 必須
		noType	= table.getColumnNo( "DATA_TYPE", false );	//
		noCdrec	= table.getColumnNo( "CDREC"	, false );	//
		noEmin	= table.getColumnNo( "E_MIN"	, false );	//
		noWmin	= table.getColumnNo( "W_MIN"	, false );	//
		noWmax	= table.getColumnNo( "W_MAX"	, false );	//
		noEmax	= table.getColumnNo( "E_MAX"	, false );	//

		final int rowCnt = table.getRowCount();
		for( int row=0; row<rowCnt; row++ ) {
			final String[] data  = table.getValues( row );

			final String val     = data[noVal] ;
			final String orgJudg = data[noJudg];					// 現在の判定結果をｷｰﾌﾟ(4:保留対応)
			final String cdrec   = rowData( row,noCdrec ,"0" );		// 登録方法 0:未決 1:不要 2:任意 4:保留 6:必須
			// ﾃﾞｰﾀが未設定の場合か、1:不要 2:任意 の場合は、登録方法(CDREC) をそのままセットする。
			if( val== null || val.isEmpty() || "1".equals( cdrec ) || "2".equals( cdrec ) ) {
				data[noJudg] = cdrec;
			}
			else {
				// 判定結果(JUDG) 0:未決 1:不要 2:任意 3:合格 4:保留 5:警告 6:必須 7:不合格
				final String dbType= rowData( row,noType,"TP_TEXT" );		// DBﾀｲﾌﾟ 未指定時は、TP_TEXT:ﾃｷｽﾄ
				if( "TP_ON".equals( dbType ) ) {							// TP_ON : 0:未決 1:OK 2:NG (3:保留)
					if(      "1".equals( val ) ){ data[noJudg] = "3"; }		// 3:合格
					else if( "0".equals( val ) ){ data[noJudg] = "0"; }		// 0:未決
					else if( "3".equals( val ) ){ data[noJudg] = "4"; }		// (3:保留) は使われていないが、あれば、4:保留
					else						{ data[noJudg] = "7"; }		// 7:不合格
				}
				else if( "TP_CHECK".equals( dbType ) ) {					// TP_CHECK : 1:ﾁｪｯｸ 0:未
					if(      "1".equals( val ) )	{ data[noJudg] = "3"; }	// 3:合格
		//			else if( "6".equals( cdrec ) )	{ data[noJudg] = "6"; }	// 合格以外で、登録方法が 6:必須 の場合は、6:必須 をｾｯﾄ
					else						{ data[noJudg] = cdrec; }	// 合格以外は、登録方法(CDREC) をそのままセット
				}
				else if( "TP_NUMBER".equals( dbType ) ) {
					final double emin = rowData( row,noEmin,Double.NEGATIVE_INFINITY );		// 異常下限(E_MIN)
					final double wmin = rowData( row,noWmin,Double.NEGATIVE_INFINITY );		// 警告下限(W_MIN)
					final double wmax = rowData( row,noWmax,Double.POSITIVE_INFINITY );		// 警告上限(W_MAX)
					final double emax = rowData( row,noEmax,Double.POSITIVE_INFINITY );		// 異常上限(E_MAX)

					try {
						final double wval = Double.parseDouble( val );		// DBﾀｲﾌﾟが、TP_NUMBER なので数値変換出来る

						// 厳しい方からﾁｪｯｸする。
						if( emin > wval ) {			// 異常下限(E_MIN)より小さい
							data[noJudg] = "7";		// 7:不合格
							data[noRiyu] = String.format( "下限値(%.2f)異常 [ ＞ %.2f ]" ,emin,wval );
						}
						else if( emax < wval ) {	// 異常上限(E_MAX)より大きい
							data[noJudg] = "7";		// 7:不合格
							data[noRiyu] = String.format( "上限値(%.2f)異常 [ ＜ %.2f ]" ,emax,wval );
						}
						else if( wmin > wval ) {	// 警告下限(W_MIN)より小さい
							data[noJudg] = "5";		// 5:警告
							data[noRiyu] = String.format( "下限値(%.2f)警告 [ ＞ %.2f ]" ,wmin,wval );
						}
						else if( wmax < wval ) {	// 警告上限(W_MAX)より大きい
							data[noJudg] = "5";		// 5:警告
							data[noRiyu] = String.format( "上限値(%.2f)警告 [ ＜ %.2f ]" ,wmax,wval );
						}
						else {
							data[noJudg] = "3";		// 3:合格
							data[noRiyu] = "";		// 判定理由のｸﾘｱ
						}
					}
					catch( final NumberFormatException ex ) {
						data[noJudg] = "7";			// 7:不合格
						data[noRiyu] = "数値変換ｴﾗｰ " + val ;
					}
				}
				// TP_ON,TP_CHECK,TP_NUMBER 以外はﾃﾞｰﾀが設定されていれば、3:合格
				else {
					data[noJudg] = "3";		// 3:合格
				}
			}

			// ｵﾘｼﾞﾅﾙの判定結果が、4:保留 で、5:警告か7:不合格 の場合は、4:保留 のままにしておく。
			if( "4".equals( orgJudg ) && ( "5".equals( data[noJudg] ) || "7".equals( data[noJudg] ) ) ) {
				data[noJudg] = "4";		// 4:保留
			}
		}

		return table;
	}

	/**
	 * DBTableModelから、指定行-列のデータを取得します。
	 *
	 * 列番号がマイナスの場合は、ｶﾗﾑが存在していないため、初期値を返します。
	 *
	 * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加
	 *
	 * @param	row 行
	 * @param	col 列
	 * @param	defVal 初期値(文字列)
	 *
	 * @return 指定行-列のデータ(文字列)
	 */
	private String rowData( final int row , final int col , final String defVal ) {
		String rtn = defVal ;
		if( col >= 0 ) {
			final String str = table.getValue( row,col );
			if( str != null && !str.isEmpty()) {
				rtn = str ;
			}
		}
		return rtn ;
	}

	/**
	 * DBTableModelから、指定行-列のデータを取得します。
	 *
	 * 列番号がマイナスの場合は、ｶﾗﾑが存在していないため、初期値を返します。
	 *
	 * @og.rev 7.3.1.1 (2021/02/25) USE_CSV 属性追加
	 *
	 * @param	row 行
	 * @param	col 列
	 * @param	defVal 初期値(数値)
	 *
	 * @return 指定行-列のデータ(数値)
	 */
	private double rowData( final int row , final int col , final double defVal ) {
		final String val = col < 0 ? null : table.getValue( row,col ) ;

		try {
			return val == null || val.isEmpty() ? defVal : Double.parseDouble( val );
		}
		catch( final NumberFormatException ex ) {
			final String errMsg = "数値項目の数値変換ｴﾗｰ　行=" + row + " , 列=" + col + " , 値=" + val ;
			throw new HybsSystemException( errMsg,ex );
		}
	}
}
