/*
 * 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.HybsSystem;
import org.opengion.fukurou.util.ToString;
import org.opengion.fukurou.util.TagBuffer;

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

/**
 * jQueryのdraggableを使用したｵﾌﾞｼﾞｪｸﾄの移動を行う、View を設定します。
 *
 * viewFormType="CustomData" の BODY 部に記述された、class="dragDiv"（固定） を持った、
 * DIV要素をﾄﾞﾗｯｸﾞするための、各種情報を提供します。
 * dragViewタグは、view タグの上位に記述し、class="dragView"（固定）のﾚｲｱｳﾄのCSS とともに、
 * 必要な情報を出力して、JQeury の引数が受け取れる形の DIVタグを生成します。
 * また、ｵﾌﾞｼﾞｪｸﾄの移動は、jQueryの ajax により、リアルタイムに JSP を呼び出すことで、
 * データベースの書き込みをサポートします。
 *
 * og:dragView ： viewタグの上位に位置して、cssと、パラメータ用のdivタグを生成します。
 * og:dragDiv  ： viewタグの tbody に書き込む、簡易的な文字列生成用のタグです。
 * common/dragSelect.jsp  ： GE18 の select文（scope="session"）
 * common/dragUpdate.jsp  ： jQueryからﾄﾞﾗｯｸﾞ終了時点でajxaで呼び出される、標準のjspファイル
 *                           この中で、GE18(位置情報管理ﾃｰﾌﾞﾙ)に位置情報が書き込まれます。
 * common/jquery/dragView.js ：jQueryのdraggable 本体。$(function(){$(".dragDiv").draggable({････})});
 *
 * dragBox.js と、dragUpdate.jsp を独自に修正すれば、自前のﾃｰﾌﾞﾙに位置情報を書き込むことも可能です。
 *
 * @og.formSample
 * ●形式：&lt;og:dragView&gt;&lt;og:view ・・・  /&gt;&lt;/og:dragView&gt;
 * ●body：あり(EVAL_BODY_INCLUDE:BODYをインクルードし、{&#064;XXXX} は解析しません)
 *
 * ●Tag定義：
 *   &lt;og:dragView
 *       url                 【TAG】ﾄﾞﾗｯｸﾞ後に呼び出す jspファイルのアドレス(初期値：/jsp/common/dragUpdate.jsp)
 *       grid                【TAG】ﾄﾞﾗｯｸﾞ時にｵﾌﾞｼﾞｪｸﾄが動けるｸﾞﾘｯﾄﾞを指定します(初期値：10,10)
 *       width               【CSS】Viewを囲うdivのCSS(dragView)のwidth属性(初期値:100%)
 *       height              【CSS】Viewを囲うdivのCSS(dragView)のheight属性(初期値:100%)
 *       image               【CSS】bgImage(background-image属性)のurlの引数の値
 *       background          【CSS】Viewを囲うdivのCSS(dragView)のbackground属性
 *       bgColor             【CSS】Viewを囲うdivのCSS(dragView)のbackground-color属性
 *       bgSize              【CSS】Viewを囲うdivのCSS(dragView)のbackground-size属性(初期値:800px)
 *       bgImage             【CSS】Viewを囲うdivのCSS(dragView)のbackground-image属性
 *       bgRepeat            【CSS】Viewを囲うdivのCSS(dragView)のbackground-repeat属性(初期値:no-repeat)
 *       bgPosition          【CSS】Viewを囲うdivのCSS(dragView)のbackground-position属性
 *       zoom                【CSS】ﾄﾞﾗｯｸﾞ要素のCSS(dragDiv)に適用する拡大、縮小の倍率
 *       id         (未使用) 【HTML】Viewを囲うdiv要素に対して固有の名前(id)をつける場合に設定します。7.2.6.2 (2020/07/29) 削除
 *       style      (未使用) 【HTML】Viewを囲うdiv要素に適用させるスタイルシート(style)を設定します。7.2.6.2 (2020/07/29) 削除
 *       optionAttributes    【TAG】Viewを囲うdiv要素にそのまま追記する属性
 *       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:dragView&gt;
 *
 * ●使用例
 *   ※ Select ･･･ from GE18 A {&#064;JOIN_SQL} where ･･･ をincludeします。
 *   &lt;og:value key="JOIN_SQL" &gt;
 *       left outer join DBXX B on A.LOC_GRP=B.GRP and A.LOC_KEY=B.KEY
 *   &lt;/og:value&gt;
 *   &lt;jsp:directive.include file="/jsp/common/dragSelect.jsp" /&gt;
 *
 *   ※ カラムに必要なﾏｰｶｰを追加します。ここでは、ICON にｲﾒｰｼﾞ画像を設定していますが、viewのBODY部でもかまいません。
 *   &lt;og:viewMarker command="{&#064;command}"&gt;
 *       &lt;og:columnMarker column="ICON"&gt;
 *           &lt;img src="image/[LOC_GRP]/[ICON]" width="50px" title="[LABEL_NAME]" /&gt;
 *       &lt;/og:columnMarker&gt;
 *   &lt;/og:viewMarker&gt;
 *
 *   ※ dragView のなかに、viewタグで、viewFormType="CustomData" のﾃﾞｰﾀを作成します。
 *    &lt;og:dragView&gt;
 *      &lt;og:view
 *          viewFormType	= "CustomData"
 *          command         = "{&#064;command}"
 *          writable        = "false"
 *          useScrollBar    = "false"
 *          numberType      = "delete"
 *          bgColorCycle    = "1"
 *          useHilightRow   = "false"
 *      &gt;
 *          ※ tbody のなかの、dibタグが、ドラッグ可能になり、left:[LOC_COL]px; top:[LOC_ROW]px; が位置になります。
 *          &lt;og:tbody rowspan="1" &gt;
 *              &lt;div class="dragDiv" id="[UNIQ]" style="left:[LOC_COL]px; top:[LOC_ROW]px;" &gt;[ICON]&lt;/div&gt;
 *          &lt;/og:tbody&gt;
 *      &lt;/og:view&gt;
 *    &lt;/og:dragView&gt;
 *
 * ●使用例
 *    ※ tbody の中を、og:dragDiv にした場合。
 *    &lt;og:dragView&gt;
 *      &lt;og:view
 *          viewFormType	= "CustomData"
 *          ･･･
 *      &gt;
 *          &lt;og:tbody rowspan="1" &gt;
 *              &lt;og:dragDiv &gt;[ICON]&lt;/og:dragDiv&gt;
 *          &lt;/og:tbody&gt;
 *      &lt;/og:view&gt;
 *    &lt;/og:dragView&gt;
 *
 * @og.rev 7.0.1.0 (2018/10/15) 新規作成
 * @og.group 画面部品
 *
 * @version  7.0
 * @author	 Kazuhiko Hasegawa
 * @since    JDK11.0,
 */
public class DragViewTag extends CommonTagSupport {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "7.0.1.0 (2018/10/15)" ;
	private static final long serialVersionUID = 701020181015L ;

	private static final String CSS_START = "<style type=\"text/css\">" ;
	private static final String CSS_END   = "</style>" ;

	private String	sysJsp			= HybsSystem.sys( "JSP" );

	private String	url				= sysJsp + "/common/dragUpdate.jsp";		// dragView の div要素として作成します。
	private String	grid			= "10,10" ;									// dragView の div要素として作成します。

	private String	width			= "100%"  ;
	private String	height 			= "100%"  ;
	private String	image			;					// background-image属性の、url( 'XXXX' ) の 中身になります。
	private String	background 		;					// background属性
	private String	bgColor			;					// background-color属性
	private String	bgSize 			= "800px" ;			// background-size属性
	private String	bgImage			;					// background-image属性
	private String	bgRepeat		= "no-repeat" ;		// background-repeat属性
	private String	bgPosition 		;					// background-position属性
	private String	zoom 			;					// 拡大、縮小の倍率
	// id , style は、CommonTagSupport で定義され、get(キー) メソッドで取得可能です。

	/**
	 * デフォルトコンストラクター
	 *
	 * @og.rev 7.0.1.0 (2018/10/15) 新規作成
	 */
	public DragViewTag() { super(); }		// これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。

	/**
	 * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
	 *
	 * @og.rev 7.0.1.0 (2018/10/15) 新規作成
	 *
	 * @return	後続処理の指示( EVAL_BODY_INCLUDE )
	 */
	@Override
	public int doStartTag() {
		if( useTag() ) {
			jspPrint( makeStyleAndDiv() );	// style属性と、開始の divタグを出力します。
			return EVAL_BODY_INCLUDE ;		// Body インクルード( extends TagSupport 時)
		}
		return SKIP_BODY ;					// Body を評価しない
	}

	/**
	 * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
	 *
	 * @og.rev 7.0.1.0 (2018/10/15) 新規作成
	 *
	 * @return	後続処理の指示
	 */
	@Override
	public int doEndTag() {
		debugPrint();
		if( useTag() ) {
			jspPrint( "</div>" );	// 最後の divタグを出力します。
		}

		return EVAL_PAGE ;		// ページの残りを評価する。( extends TagSupport 時)
	}

	/**
	 * タグリブオブジェクトをリリースします。
	 * キャッシュされて再利用されるので、フィールドの初期設定を行います。
	 *
	 * @og.rev 7.0.1.0 (2018/10/15) 新規作成
	 */
	@Override
	protected void release2() {
		super.release2();
		sysJsp			= HybsSystem.sys( "JSP" );
		url				= sysJsp + "/common/dragUpdate.jsp";
		grid			= "10,10" ;
		width			= "100%"  ;
		height 			= "100%"  ;
		image			= null ;			// url( 'image/{@LOC_GRP}.png' ) の 中身になります。
		background 		= null ;
		bgColor			= null ;
		bgSize 			= "800px" ;
		bgImage			= null ;
		bgRepeat		= "no-repeat" ;
		bgPosition 		= null ;
		zoom	 		= null ;
	}

	/**
	 * style属性と、開始の divタグを生成します。
	 *
	 * ﾄﾞﾗｯｸﾞ処理に必要な、CSS 情報と、view を囲う DIV要素の開始タグを出力します。
	 *
	 * @return  style属性と、開始の divタグ
	 */
	private String makeStyleAndDiv() {
		final String trzoom = zoom == null ? null : "scale(" + zoom + ")" ;
		final String origin = zoom == null ? null : "top left" ;

		// CSS 作成
		final TagBuffer tagBuf = new TagBuffer()
				.addBuffer( CSS_START						)
				.startCss( ".dragDiv"						)
				.add( "position"			, "absolute"	)
				.add( "margin"				, "0px"			)
				.add( "padding"				, "0px"			)
				.add( "zoom"					, zoom		)			// null の場合、登録されない
				.add( "transform"				, trzoom	)			//   同上
				.add( "transform-origin"		, origin	)			//   同上
				.add( "-moz-transform"			, trzoom	)			//   同上
				.add( "-moz-transform-origin"	, origin	)			//   同上
				.make()													// ここで、一旦完成
				.startCss( ".dragView"						)
				.add( "width"				, width			)
				.add( "height" 				, height		)
				.add( "background"			, background	)
				.add( "background-color"	, bgColor		)
				.add( "background-size"		, bgSize		)
				.add( "background-image"	, nval( bgImage , image ) )	// bgImage があれば優先されます。
				.add( "background-repeat"	, bgRepeat		)
				.add( "background-position"	, bgPosition	)
				.make()													// ここで、一旦完成
				.addBuffer( CSS_END							)
				.startTag( "div"							)
				.add( "class"				, "dragView"	)
				.add( "url"					, url			)
				.add( "grid"				, grid			)
				.addOptions( get( "optionAttributes" )		) ;			// id,style など

		return tagBuf.toBefore();										// <div ････ > まで先行して作成します。
	}

	/**
	 * 【TAG】ﾄﾞﾗｯｸﾞ後に呼び出す jspファイルのアドレス(初期値：/jsp/common/dragUpdate.jsp)。
	 *
	 * @og.tag
	 * ﾄﾞﾗｯｸﾞ後に ajax で、jspファイルを呼び出します。
	 * 初期値は、/jsp/common/dragUpdate.jsp に設定されており、GE18 ﾃｰﾌﾞﾙに状態を書き込みます。
	 *
	 * @param   url ﾄﾞﾗｯｸﾞ後に呼び出す jspファイル
	 */
	public void setUrl( final String url ) {
		this.url = nval( getRequestParameter( url ),this.url );
	}

	/**
	 * 【TAG】ﾄﾞﾗｯｸﾞ時にｵﾌﾞｼﾞｪｸﾄが動けるｸﾞﾘｯﾄﾞを指定します(初期値：10,10)。
	 *
	 * @og.tag
	 * ﾄﾞﾗｯｸﾞ時に、ｵﾌﾞｼﾞｪｸﾄが、このｸﾞﾘｯﾄﾞ単位で移動します。
	 * ある程度、ｸﾞﾘｯﾄﾞで制約をかけると、縦や横に、きれいに配置させることができます。
	 * 1,1 にすると、1ピクセル毎に滑らかに動きます。
	 * また、10,0 を設定すると、x軸(横方向)には、10px単位で動きますが、y軸(縦方向)には動きません。
	 * 初期値は、10,10 で、10px単位に、動きます。
	 *
	 * @param   grid ﾄﾞﾗｯｸﾞ時にｵﾌﾞｼﾞｪｸﾄが動けるｸﾞﾘｯﾄﾞ
	 */
	public void setGrid( final String grid ) {
		this.grid = nval( getRequestParameter( grid ),this.grid );
	}

	/**
	 * 【CSS】Viewを囲うdivのCSS(dragView)のwidth属性(初期値:100%)。
	 *
	 * @og.tag
	 * div要素のwidth属性を指定します。
	 * これは、.dragView セレクタの style に書き込まれます。
	 *
	 * 初期値は、100% です。
	 *
	 * @param   width width属性(初期値:100%)
	 */
	public void setWidth( final String width ) {
		this.width = nval( getRequestParameter( width ),this.width );
	}

	/**
	 * 【CSS】Viewを囲うdivのCSS(dragView)のheight属性(初期値:100%)。
	 *
	 * @og.tag
	 * div要素のheight属性を指定します。
	 * これは、.dragView セレクタの style に書き込まれます。
	 *
	 * 初期値は、100% です。
	 *
	 * @param   height height属性(初期値:100%)
	 */
	public void setHeight( final String height ) {
		this.height = nval( getRequestParameter( height ),this.height );
	}

	/**
	 * 【CSS】Viewを囲うdivのCSS(dragView)のbackground-image属性のurlの引数の値。
	 *
	 * @og.tag
	 * div要素のbackground-image属性を簡易的に指定するのに使用します。
	 * background-image属性は、url( 'image/SAMPLE.png' ) のような書き方になりますが
	 * ここで指定するのは、'image/SAMPLE.png' の部分です。
	 * ｼﾝｸﾞﾙｸｵｰﾄは、タグ内で付けますので、引数につける必要はありません。
	 * background-image と同時に指定された場合は、background-image が優先されます。
	 *
	 * 初期値は、ありません。
	 *
	 * @param   image background-image属性のurlの引数の値
	 * @see		#setBgImage(String)
	 */
	public void setImage( final String image ) {
		final String img = nval( getRequestParameter( image ),this.image );

		if( img != null ) {
			this.image = "url('" + img + "')" ;
		}
	}

	/**
	 * 【CSS】Viewを囲うdivのCSS(dragView)のbackground属性。
	 *
	 * @og.tag
	 * div要素のbackground属性を指定します。
	 * 例：background = "top left/800px url( 'image/{&#064;LOC_GRP}.png' ) no-repeat;"
	 * これは、.dragView セレクタの style に書き込まれます。
	 *
	 * 初期値は、ありません。
	 *
	 * @param   background background属性
	 */
	public void setBackground( final String background ) {
		this.background = nval( getRequestParameter( background ),this.background );
	}

	/**
	 * 【CSS】Viewを囲うdivのCSS(dragView)のbackground-color属性。
	 *
	 * @og.tag
	 * div要素のbackground-color属性を指定します。
	 * これは、.dragView セレクタの style に書き込まれます。
	 *
	 * 初期値は、ありません。
	 *
	 * @param   bgColor background-color属性
	 */
	public void setBgColor( final String bgColor ) {
		this.bgColor = nval( getRequestParameter( bgColor ),this.bgColor );
	}

	/**
	 * 【CSS】Viewを囲うdivのCSS(dragView)のbackground-size属性(初期値:800px)。
	 *
	 * @og.tag
	 * div要素のbackground-size属性を指定します。
	 * これは、.dragView セレクタの style に書き込まれます。
	 *
	 * 初期値:800px。
	 *
	 * @param   bgSize background-size属性
	 */
	public void setBgSize( final String bgSize ) {
		this.bgSize = nval( getRequestParameter( bgSize ),this.bgSize );
	}

	/**
	 * 【CSS】Viewを囲うdivのCSS(dragView)のbackground-image属性。
	 *
	 * @og.tag
	 * div要素のbackground-image属性を指定します。
	 * background-image属性は、url( 'image/SAMPLE.png' ) のような書き方になります。
	 * これは、.dragView セレクタの style に書き込まれます。
	 *
	 * 初期値は、ありません。
	 *
	 * @param   bgImage background-image属性
	 * @see		#setImage(String)
	 */
	public void setBgImage( final String bgImage ) {
		this.bgImage = nval( getRequestParameter( bgImage ),this.bgImage );
	}

	/**
	 * 【CSS】Viewを囲うdivのCSS(dragView)のbackground-repeat属性(初期値:no-repeat)。
	 *
	 * @og.tag
	 * div要素のbackground-repeat属性を指定します。
	 * これは、.dragView セレクタの style に書き込まれます。
	 *
	 * 初期値:no-repeat。
	 *
	 * @param   bgRepeat background-repeat属性
	 */
	public void setBgRepeat( final String bgRepeat ) {
		this.bgRepeat = nval( getRequestParameter( bgRepeat ),this.bgRepeat );
	}

	/**
	 * 【CSS】Viewを囲うdivのCSS(dragView)のbackground-position属性。
	 *
	 * @og.tag
	 * div要素のbackground-position属性を指定します。
	 * これは、.dragView セレクタの style に書き込まれます。
	 *
	 * 初期値は、ありません。
	 *
	 * @param   bgPosition background-position属性
	 */
	public void setBgPosition( final String bgPosition ) {
		this.bgPosition = nval( getRequestParameter( bgPosition ),this.bgPosition );
	}

	/**
	 * 【CSS】ﾄﾞﾗｯｸﾞ要素のCSS(dragDiv)に適用する拡大、縮小の倍率。
	 *
	 * @og.tag
	 * 要素を拡大、縮小するCSSを、dragDiv に書き込みます。
	 * 1.0 が標準で、1以下が縮小、1以上が拡大になります。
	 *
	 *		zoom					: {&#064;ZOOM};
	 *		transform				: scale({&#064;ZOOM});
	 *		transform-origin		: top left;
	 *		-moz-transform			: scale({&#064;ZOOM});
	 *		-moz-transform-origin	: top left;
	 *
	 * 初期値は、ありません。
	 *
	 * @param   zoom ﾄﾞﾗｯｸﾞ要素の拡大、縮小の倍率
	 */
	public void setZoom( final String zoom ) {
		this.zoom = nval( getRequestParameter( zoom ),this.zoom );
	}

	/**
	 * 【TAG】JavaScript などの HTML基本タグ以外の属性を、そのままタグとして使用します。
	 *
	 * @og.tag
	 * JavaScript などの HTML基本タグ以外の属性を、そのままタグとして使用します。
	 *
	 * @param   optionAttributes オプション属性
	 */
	public void setOptionAttributes( final String optionAttributes ) {
		final String optAttri = getRequestParameter( optionAttributes );
		if( optAttri != null && optAttri.length() > 0 ) {
			set( "optionAttributes",optAttri );
		}
	}

	/**
	 * このオブジェクトの文字列表現を返します。
	 * 基本的にデバッグ目的に使用します。
	 *
	 * @return このクラスの文字列表現
	 * @og.rtnNotNull
	 */
	@Override
	public String toString() {
		return ToString.title( this.getClass().getName() )
				.println( "VERSION"			,VERSION	)
				.println( "url"				,url		)
				.println( "grid"			,grid		)
				.println( "width"			,width		)
				.println( "height"			,height 	)
				.println( "image"			,image	 	)		// url文字列と合成済み
				.println( "background"		,background )
				.println( "bgColor"			,bgColor	)
				.println( "bgSize"			,bgSize 	)
				.println( "bgImage"			,bgImage	)
				.println( "bgRepeat"		,bgRepeat	)
				.println( "bgPosition"		,bgPosition )
	//			.println( "id"				,get("id" 	 ) )
	//			.println( "style"			,get("style" ) )
				.println( "Other..."	,getAttributes().getAttribute() )
				.fixForm().toString() ;
	}
}
