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

import java.util.regex.Matcher;							// 5.10.4.0 (2018/10/05) 暗号化処理追加
import java.util.regex.Pattern;							// 5.10.4.0 (2018/10/05) 暗号化処理追加

import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.fukurou.util.StringFormat;
import org.opengion.fukurou.util.StringUtil;			// 5.9.0.1 (2015/09/11)
import org.opengion.fukurou.security.HybsCryptography;	// 5.10.4.0 (2018/10/05) 暗号化処理追加
import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;	// 5.10.4.0 (2018/10/05)

/**
 * 動的プルダウンなどで利用されるイベントカラムの各種情報を保持するための
 * 管理クラスです。
 *
 * 内容を置き換えるカラム(子カラム)の名前をキーに、イベントカラム(親カラム)や、
 * イベント発行時の処理URL等を管理します。
 *
 * これらの情報は、ColumnTagやSelectTag、ViewFormTagなどで登録され、その結果を
 * JavaScriptのコードとして出力します。(common/eventColumn.jsp)
 *
 * ここで出力された情報をイベント発行時に、JavaScriptが参照し、処理URLに渡す
 * ことで、動的な項目の入れ替えを実現しています。
 *
 * @og.rev 5.1.7.0 (2010/06/01) 新規追加
 * @og.rev 5.9.0.1 (2015/09/11) アンダースコア対応
 *
 * @version  4.0
 * @author   Hiroki Nakamura
 * @since    JDK5.0,
 */
public class DBEventColumn {

	private static final String EVENT_COLUMN_URL = HybsSystem.sys( "JSP" ) + "/" + HybsSystem.sys( "EVENT_COLUMN_URL" );

	private final String name			;	// 内容を置き換えるカラム(子カラム)
	private final String eventColumn	;	// イベントカラム(親カラム・CSV形式)
	private final String eventValue		;	// 6.3.3.0 (2015/07/25) eventValue 追加
	private final String eventUrl		;	// イベント発行時の処理URL
	private final String renderer		;	// 子カラムのレンデラー
	private final String editor			;	// 子カラムのエディター
	private final String rendParam		;	// 子カラムの表示パラメーター
	private final String editParam		;	// 子カラムの編集パラメーター
	private final String valParam		;	// 6.3.3.0 (2015/07/25) rendParam,editParam で使用する変数化された親カラム

	private final Pattern trgPattern	= Pattern.compile( "(?<=\\{@)[^.]+?(?=\\})" );		// 5.10.4.0 (2018/10/05)
	private final boolean flgEncrypt	= HybsSystem.sysBool( "EVENT_SQL_ENCRYPT" );		// 5.10.4.0 (2018/10/05)
	private final HybsCryptography hc	= flgEncrypt ? new HybsCryptography() : null ;		// 5.10.4.0 (2018/10/05)

	/**
	 * 初期情報を含んだ新規オブジェクトを作成します。
	 * このコンストラクタではflgEncryptをfalseとして扱う。
	 *
	 * @og.rev 6.3.3.0 (2015/07/25) eventValue 追加
	 * @og.rev 5.9.0.1 (2015/09/11) アンダースコア対応
	 * @og.rev 5.10.4.0 (2018/10/05) 暗号化対応
	 *
	 * @param name 内容を置き換えるカラム(子カラム)
	 * @param eventColumn イベントカラム(親カラム・CSV形式)
	 * @param eventValue 子カラムの値SQL
	 * @param eventUrl イベント発行時の処理URL
	 * @param renderer 子カラムのレンデラー
	 * @param editor 子カラムのエディター
	 * @param rendParam 子カラムの表示パラメーター
	 * @param editParam 子カラムの編集パラメーター
	 */
	public DBEventColumn( final String name, final String eventColumn, final String eventValue, final String eventUrl,
							final String renderer, final String editor, final String rendParam, final String editParam ) {
		this.name			= name;
		this.eventColumn	= eventColumn;
		this.eventValue		= eventValue;								// 6.3.3.0 (2015/07/25)
		// 6.4.2.1 (2016/02/05) PMD refactoring. Useless parentheses.
		this.eventUrl		= eventUrl != null && eventUrl.length() > 0 ? eventUrl : EVENT_COLUMN_URL;	 // 5.1.9.0 (2010/08/01) 動的プルダウン不具合対応
		this.renderer		= renderer;
		this.editor			= editor;
		this.rendParam		= rendParam;
		this.editParam		= editParam;

		valParam = "{@" + evColReplace( eventColumn ).replace( ",", "}:{@" ) + "}" ;	// 5.9.0.1 (2015/09/11)

//		// 5.10.4.0 (2018/10/05) 暗号化対応
//		this.flgEncrypt = HybsSystem.sysBool("EVENT_SQL_ENCRYPT");
//		if(flgEncrypt) {
//			this.hc = new HybsCryptography();
//		}
	}

	/**
	 * 内容を置き換えるカラム(子カラム)を返します。
	 *
	 * @return 内容を置き換えるカラム(子カラム)
	 */
	public String getName() { return name; }

	/**
	 * イベントカラム(親カラム・CSV形式)を返します。
	 *
	 * @return イベントカラム(親カラム・CSV形式)
	 */
	public String getEventColumn() { return eventColumn; }

	/**
	 * イベント発行時の処理URLを返します。
	 *
	 * @og.rev 5.1.8.0 (2010/07/01) getEventUrl ⇒ getEventURL に変更
	 *
	 * @return イベント発行時の処理URL
	 */
	public String getEventURL() { return eventUrl; }

	/**
	 * 子カラムのレンデラーを返します。
	 *
	 * @return 子カラムのレンデラー
	 */
	public String getRenderer() { return renderer; }

	/**
	 * 子カラムのエディターを返します。
	 *
	 * @return 子カラムのエディター
	 */
	public String getEditor() { return editor; }

	/**
	 * 子カラムの表示パラメーターを返します。
	 *
	 * @og.rev 5.10.4.0 (2018/10/05) 暗号化処理追加
	 *
	 * @return 子カラムの表示パラメーター
	 * @og.rtnNotNull
	 */
	public String getRendParam() {
		final StringFormat sf = new StringFormat(
							rendParam
							,valParam		// 6.3.3.0 (2015/07/25)
							,name );
		// 5.10.4.0 (2018/10/05)
//		return sf.format();
//		if(flgEncrypt) {
//			return hc.encrypt(sf.format());
//		}else {
//			return sf.format();
//		}
		return flgEncrypt ? hc.encrypt( sf.format() ) : sf.format();
	}

	/**
	 * 子カラムの編集パラメーターを返します。
	 *
	 * @og.rev 5.10.4.0 (2018/10/05) 暗号化処理追加
	 *
	 * @return 子カラムの編集パラメーター
	 * @og.rtnNotNull
	 */
	public String getEditParam() {
		final StringFormat sf = new StringFormat(
							editParam
							,valParam		// 6.3.3.0 (2015/07/25)
							,name );
		// 5.10.4.0 (2018/10/05)
//		return sf.format();
//		if(flgEncrypt) {
//			return hc.encrypt(sf.format());
//		}else {
//			return sf.format();
//		}
		return flgEncrypt ? hc.encrypt( sf.format() ) : sf.format();
	}

	/**
	 * 子カラムの値SQLを返します。
	 *
	 * @og.rev 6.3.3.0 (2015/07/25) eventValue 追加
	 *
	 * @return 子カラムの値SQL
	 * @og.rtnNotNull
	 */
	public String getEventValue() {
		final StringFormat sf = new StringFormat(
							eventValue
							,valParam		// 6.3.3.0 (2015/07/25)
							,name );
		return sf.format();
	}

	/**
	 * カンマ区切りのカラム名から先頭のアンダースコアを外します。
	 *
	 * @og.rev 5.9.0.1 (2015/09/11) 新規作成
	 * @og.rev 6.8.5.0 (2018/01/09) StringUtil.csv2Array のデフォルトメソッドを使用します。
	 *
	 * @param inStr カンマ区切りイベントカラム
	 * @return 先頭アンダースコアを外したカンマ区切り文字列
	 */
	private String evColReplace( final String inStr ){
		final String[] to;
		if( inStr != null && inStr.indexOf( ',' ) >= 0 ) {
			to = StringUtil.csv2Array( inStr );					// 6.8.5.0 (2018/01/09)
		}
		else {
			to = new String[] { inStr };
		}

		for( int i=0; i<to.length; i++ ) {
			if( to[i].charAt( 0 ) == '_'){
				to[i] = to[i].substring( 1 );
			}
		}

		return StringUtil.array2csv( to );
	}

	/**
	 * 文字列から{&#064;XXX}のXXXを抜き出して、CSVに変換する。
	 * 
	 * @og.rev 5.10.4.0 (2018/10/05) 新規作成
	 *
	 * @param trg 変換対象文字列
	 * @return CSV文字列
	 */
	private String getTrgCsv( final String trg ) {
		if( trg == null || trg.length() == 0 ) { return ""; }

		final Matcher mtch = trgPattern.matcher( trg );
		final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE );
		while( mtch.find() ) {
			if( rtn.length() != 0 ) {
				rtn.append( ',' );
			}
			rtn.append( mtch.group() );
		}

		return rtn.toString();
	}

	/**
	 * レンデラーパラメータのキーリストを渡します。
	 * 復号化後の値設定に利用します。
	 *
	 * @og.rev 5.10.4.0 (2018/10/05) 新規作成
	 *
	 * @return レンデラーパラメータのキーリスト
	 */
	public String getRendParamKeys() {
		// 暗号化しない、またはrendParamが空の場合は、空文字を返す
		if( !flgEncrypt || rendParam == null || rendParam.length() == 0 ) { return ""; }

		final StringFormat sf = new StringFormat(
				rendParam
//				,"{@" + evColReplace(evCol).replace( ",", "}:{@" ) + "}"
				,valParam		// 6.3.3.0 (2015/07/25)
				,name );

		return getTrgCsv( sf.format() );
	}

	/**
	 * エディターパラメータのキーリストを渡します。
	 * 復号化後の値設定に利用します。
	 *
	 * @og.rev 5.10.4.0 (2018/10/05) 新規作成
	 *
	 * @return エディターパラメータのキーリスト
	 */
	public String getEditParamKeys() {
		// 暗号化しない、またはrendParamが空の場合は、空文字を返す
		if( !flgEncrypt || editParam == null || editParam.length() == 0 ) { return ""; }

		final StringFormat sf = new StringFormat(
				editParam
//				,"{@" + evColReplace(evCol).replace( ",", "}:{@" ) + "}"
				,valParam		// 6.3.3.0 (2015/07/25)
				,name );

		return getTrgCsv( sf.format() );
	}

	/**
	 * 暗号化フラグを渡します。
	 *
	 * @og.rev 5.10.4.0 (2018/10/05) 新規作成
	 *
	 * @return 暗号化フラグ
	 */
//	public Boolean isFlgEncrypt() {
	public boolean isFlgEncrypt() {
		return flgEncrypt;
	}
}
