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

import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.resource.LabelInterface;
import org.opengion.fukurou.util.StringUtil;
import org.opengion.fukurou.util.ToString;						// 6.1.1.0 (2015/01/17)

import static org.opengion.fukurou.util.StringUtil.nval ;

/**
 * 画面にラベルリソース等のメッセージを表示させるタグです。
 *
 * lbl 属性に ラベルリソース のキーを与えることで、 ロケールにあわせたリソースを使用して、
 * 画面に表示します。
 * 違う値をセットした場合は、 セットした値が、そのまま出力されます。これは、ロケールが
 * 見つからなかった場合の標準の対応方法です。
 * ロケールは、ユーザー情報の lang 属性を初期値で使用し、 セットされていない場合は、
 * リクエスト情報のロケールから取得します。
 * lbl 属性を使用する場合、val0 ～ val9 までの引数を使用することができます。これは、
 * メッセージフォーマットの、引数 {0} ～ {9} に対応して割り付けられます。
 *
 * @og.formSample
 * ●形式：&lt;og:message lbl="…" val0=[…] … /&gt;
 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
 *
 * ●Tag定義：
 *   &lt;og:message
 *       lbl                【TAG】ラベルリソースのラベルIDを指定します
 *       language           【TAG】タグ内部で使用する言語コード[ja/en/zh/…]を指定します
 *       command            【TAG】コマンド (INSERT,COPY,MODIFY,DELETE)をセットします
 *       comment            【TAG】コメントを指定します
 *       type               【TAG】タイプを(Label,Short,Tips,Description)から指定します(初期値:Label)
 *       val0               【TAG】メッセージの引数{0}を指定します
 *       val1               【TAG】メッセージの引数{1}を指定します
 *       val2               【TAG】メッセージの引数{2}を指定します
 *       val3               【TAG】メッセージの引数{3}を指定します
 *       val4               【TAG】メッセージの引数{4}を指定します
 *       val5               【TAG】メッセージの引数{5}を指定します
 *       val6               【TAG】メッセージの引数{6}を指定します
 *       val7               【TAG】メッセージの引数{7}を指定します
 *       val8               【TAG】メッセージの引数{8}を指定します
 *       val9               【TAG】メッセージの引数{9}を指定します
 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:判定しない)
 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:判定しない)
 *       caseIf             【TAG】指定の値が、true/TRUE文字列の場合は、このタグは使用されます(初期値:判定しない)
 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
 *   &gt;   ... Body ...
 *   &lt;/og:message&gt;
 *
 * ●使用例
 *     &lt;og:message lbl=&quot;MSG0032&quot; language=&quot;ja&quot; /&gt;
 *
 *        lbl       : MessageResource.properties のキー
 *        language  : ロケール(オプション)
 *
 *     例１)
 *         &lt;og:message lbl=&quot;MSG0032&quot; &gt;検索条件&lt;/og:message&gt;
 *
 *        BODY 部分は、無視されます。コメント等に使用できます。
 *        HTMLファイルには、コメント部分は出力されません。
 *
 *        typeをTipsにした場合には出力をclass=ogmsgのspanタグで囲います。   5.9.22.2 (2017/07/21)
 *
 * @og.group 画面部品
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class MessageTag extends CommonTagSupport {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "6.4.2.0 (2016/01/29)" ;
	private static final long serialVersionUID = 642020160129L ;

	private String		comment	;
	private String[]	values	;
	// 4.0.0 (2005/01/31) メッセージの種類を指定できるようにします。
	private String		type	= "Label" ;	// Label,Short,Tips,Description が指定できます。
	private String		cmdMsg	;

	private static final String[] TYPE_LIST = { "Label","Short","Tips","Description" };

	private static final String tipsPre = "<span class=\"ogmsg\">"; // 5.9.22.2 (2017/07/21)
	private static final String tipsSuf = "</span>";

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

	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
	 *
	 * @return	後続処理の指示( EVAL_BODY_BUFFERED )
	 */
	@Override
	public int doStartTag() {
		// 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
		// 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method
		return useTag()
					? EVAL_BODY_BUFFERED		// Body を評価する。( extends BodyTagSupport 時)
					: SKIP_BODY ;				// Body を評価しない

//		if( useTag() ) {
//			return EVAL_BODY_BUFFERED ;	// Body を評価する。( extends BodyTagSupport 時)
//		}
//		return SKIP_BODY ;				// Body を評価しない
	}

	/**
	 * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
	 *
	 * @og.rev 3.1.1.0 (2003/03/28) ボディの内容を取得する処理を、CommonTagSupport で行う。
	 *
	 * @return	後続処理の指示(SKIP_BODY)
	 */
	@Override
	public int doAfterBody() {
		final String str = getBodyString();

		if( str != null && str.length() > 0 ) {
			comment = StringUtil.htmlFilter( str );
		}

		return SKIP_BODY ;
	}

	/**
	 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
	 * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();		// 4.0.0 (2005/02/28)
		// 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
		if( useTag() ) {
			jspPrint( makeTag() );
		}
		return EVAL_PAGE ;
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
	 * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
	 *
	 */
	@Override
	protected void release2() {
		super.release2();
		comment	= null;
		values	= null;
		type	= "Label" ;	// Label,Short,Tips,Description が指定できます。
		cmdMsg	= null;
	}

	/**
	 * 表示用の文字列を指定します。
	 *
	 * @og.rev 4.0.0.0 (2005/01/31) タイプ別メッセージ情報を返します。
	 * @og.rev 4.0.0.0 (2007/10/18) メッセージリソース統合( getResource().getMessage ⇒ getResource().getLabel )
	 * @og.ref 5.9.22.2 (2017/07/21) Tipsの場合のみ、前後をclass=ogmsg付きのspanで囲います。
	 *
	 * @return  変換後の文字列
	 */
	private String makeTag() {
		String val  = null;

		final LabelInterface label = getLabelInterface();

		final char ch = type.charAt(0);	// Label,Short,Tips,Description
		// 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
		if( label == null ) {
			val = cmdMsg == null ? comment : getResource().getLabel( cmdMsg );	// cmdMsg = INSERT,COPY,MODIFY,DELETE,null
		}
		else {
			switch( ch ) {
				case 'L': val = label.getMessage( values );	break;
				case 'S': val = label.getShortLabel();		break;
//				case 'T': val = label.getLongLabel();		break;
				case 'T': val = tipsPre + label.getLongLabel() + tipsSuf; break; // 5.9.22.2 (2017/07/21)
				case 'D': val = label.getDescription();		break;
				default :									break;
			}
		}

//		if( label != null ) {
//			switch( ch ) {
//				case 'L': val = label.getMessage( values ); break;
//				case 'S': val = label.getShortLabel(); break;
//				case 'T': val = label.getLongLabel(); break;
//				case 'D': val = label.getDescription(); break;
//				default : break;
//			}
//		}
//		else {
//			if( cmdMsg != null ) {
//				// cmdMsg = INSERT,COPY,MODIFY,DELETE,null
//				val = getResource().getLabel( cmdMsg );
//			}
//			else {
//				val = comment;
//			}
//		}

		return val;
	}

	/**
	 * 【TAG】コメントを指定します。
	 *
	 * @og.tag
	 * msg 属性でメッセージリソースから読み取りますが,開発途中で
	 * リソース登録を済ましていない状態でコメントを入れる場合に、
	 * 直接コメントをかけるようにします。
	 *
	 * @og.rev 2.2.0.0 (2002/12/17) 中国語(国際化)対応 エンコードの取得方法変更
	 * @og.rev 3.0.0.0 (2002/12/25) StringUtil#changeString 廃止
	 *
	 * @param   cmnt コメント文字列
	 */
	public void setComment( final String cmnt ) {
		comment = cmnt;
	}

	/**
	 * 【TAG】タイプ[Label/Short/Tips/Description]を指定します(初期値:Label)。
	 *
	 * @og.tag
	 * タイプは、ラベル／メッセージリソースのどの情報を取得したいかを指定できます。
	 * 従来のラベル／メッセージは、Label に相当します。
	 * なお、指定は、それぞれの頭文字('L','S','T','D')のみでも可能です。
	 * 初期値は、"Label" です。
	 * ・Label  : ラベル／メッセージ表示
	 * ・Short  : 表形式で使用する短いラベル表示
	 * ・Tips   : ラベルの上にTips表示
	 * ・Description : 概要説明を表示
	 *
	 * @og.rev 4.0.0.0 (2005/01/31) 新規登録
	 *
	 * @param   tp タイプ文字列 [Label/Short/Tips/Description]
	 */
	public void setType( final String tp ) {
		type = nval( getRequestParameter( tp ),type );

		final char ch = type.charAt(0);	// Label,Short,Tips,Description

		if( "LSTD".indexOf( ch ) < 0 ) {
			final String errMsg = "type に、指定不可能な文字が設定されました。type=[" + type
					+ "] TYPE_LIST=[" + StringUtil.array2csv( TYPE_LIST ) + "]";
			throw new HybsSystemException( errMsg );
		}
	}

	/**
	 * 【TAG】メッセージの引数{0}を指定します。
	 *
	 * @og.tag メッセージの引数を指定します。
	 *
	 * @param   value メッセージの引数
	 */
	public void setVal0( final String value ) { setValues( 0, value ); }

	/**
	 * 【TAG】メッセージの引数{1}を指定します。
	 *
	 * @og.tag メッセージの引数を指定します。
	 *
	 * @param   value メッセージの引数
	 */
	public void setVal1( final String value ) { setValues( 1, value ); }

	/**
	 * 【TAG】メッセージの引数{2}を指定します。
	 *
	 * @og.tag メッセージの引数を指定します。
	 *
	 * @param   value メッセージの引数
	 */
	public void setVal2( final String value ) { setValues( 2, value ); }

	/**
	 * 【TAG】メッセージの引数{3}を指定します。
	 *
	 * @og.tag メッセージの引数を指定します。
	 *
	 * @param   value メッセージの引数
	 */
	public void setVal3( final String value ) { setValues( 3, value ); }

	/**
	 * 【TAG】メッセージの引数{4}を指定します。
	 *
	 * @og.tag メッセージの引数を指定します。
	 *
	 * @param   value メッセージの引数
	 */
	public void setVal4( final String value ) { setValues( 4, value ); }

	/**
	 * 【TAG】メッセージの引数{5}を指定します。
	 *
	 * @og.tag メッセージの引数を指定します。
	 *
	 * @param   value メッセージの引数
	 */
	public void setVal5( final String value ) { setValues( 5, value ); }

	/**
	 * 【TAG】メッセージの引数{6}を指定します。
	 *
	 * @og.tag メッセージの引数を指定します。
	 *
	 * @param   value メッセージの引数
	 */
	public void setVal6( final String value ) { setValues( 6, value ); }

	/**
	 * 【TAG】メッセージの引数{7}を指定します。
	 *
	 * @og.tag メッセージの引数を指定します。
	 *
	 * @param   value メッセージの引数
	 */
	public void setVal7( final String value ) { setValues( 7, value ); }

	/**
	 * 【TAG】メッセージの引数{8}を指定します。
	 *
	 * @og.tag メッセージの引数を指定します。
	 *
	 * @param   value メッセージの引数
	 */
	public void setVal8( final String value ) { setValues( 8, value ); }

	/**
	 * 【TAG】メッセージの引数{9}を指定します。
	 *
	 * @og.tag メッセージの引数{9}を指定します。
	 *
	 * @param   value メッセージの引数
	 */
	public void setVal9( final String value ) { setValues( 9, value ); }

	/**
	 * メッセージの引数を指定します。
	 *
	 * @param   no    メッセージの引数の配列番号
	 * @param   value メッセージの引数
	 */
	private void setValues( final int no,final String val ) {
		if( values == null ) { values = new String[10]; }
		values[no] = getRequestParameter( val );
	}

	/**
	 * 【TAG】コマンド (INSERT,COPY,MODIFY,DELETE)をセットします。
	 *
	 * @og.tag
	 * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
	 * フィールド定数値のいづれかを、指定できます。
	 * コマンド (INSERT,COPY,MODIFY,DELETE)に対応したメッセージを表示します。
	 * INSERT : MSG0044  追加処理を行います。
	 * COPY   : MSG0045  複写処理を行います。
	 * MODIFY : MSG0046  変更処理を行います。
	 * DELETE : MSG0047  削除処理を行います。
	 *
	 * なお、command によるメッセージの自動選択は、lbl ともにセットされていない
	 * 場合にのみ有効になります。
	 *
	 * @og.rev 4.0.0.0 (2006/11/31) 新規登録
	 *
	 * @param	cmd コマンド (public static final 宣言されている文字列)
	 */
	public void setCommand( final String cmd ) {
		final String cmd2 = nval( getRequestParameter( cmd ),null );
		if(      "INSERT".equalsIgnoreCase( cmd2 ) ) { cmdMsg = "MSG0044"; }
		else if( "COPY".equalsIgnoreCase(   cmd2 ) ) { cmdMsg = "MSG0045"; }
		else if( "MODIFY".equalsIgnoreCase( cmd2 ) ) { cmdMsg = "MSG0046"; }
		else if( "DELETE".equalsIgnoreCase( cmd2 ) ) { cmdMsg = "MSG0047"; }
		else { cmdMsg = null; }
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @return このクラスの文字列表現
	 * @og.rtnNotNull
	 */
	@Override
	public String toString() {
		return ToString.title( this.getClass().getName() )
				.println( "VERSION"		,VERSION	)
				.println( "comment"		,comment	)
				.println( "values"		,values		)
				.println( "type"		,type		)
				.println( "TYPE_LIST"	,TYPE_LIST	)
				.println( "Other..."	,getAttributes().getAttribute() )
				.fixForm().toString() ;
	}
}
