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

import java.util.Arrays;

import org.opengion.fukurou.util.StringUtil;
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.html.AbstractViewForm;
import org.opengion.hayabusa.html.ViewJsonParam;

/**
 * 検索結果をJSON形式で出力します。
 * 以下の形式で出力されます
 * { "DATA":[{"カラム名":"値(1行目)",...},{"カラム名":"値(2行目)",...}]
 *	 ,"HEAD":{"カラム名":"ラベル",...}
 *	 ,"INFO":{{"COUNT":"件数","COLUMN":"出力カラム名（カンマ区切り）"} }
 *	}
 *
 * AbstractViewForm を継承している為,ロケールに応じたラベルを出力させる事が出来ます。
 *
 * @og.group 画面表示
 * @og.rev 5.1.7.0 (2016/04/01) 新規作成
 *
 * @version  5.0
 * @author	 Takahashi Masakazu
 * @since    JDK5.0,
 */
public class ViewForm_JSON extends AbstractViewForm {
	//* このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "5.5.4.2 (2012/07/13)" ;

	private int		clmCnt		= -1;		

	private String	viewClms	= null;	
	
	private String dataName;
	private boolean useHead;
	private boolean useInfo;
	private boolean useRenderer;
	private boolean useUtfEncode; // '\u0000'形式への変換は仕様上必須ではないので現時点では実装しない
	
	private String rendererCols; // 5.9.27.0 (2017/12/01)
	
	/** ヘッダー部分のキャッシュ変数 */
	protected String	headerLine	 = null;

	/**
	 * DBTableModel から HTML文字列を作成して返します。
	 * startNo(表示開始位置)から、pageSize(表示件数)までのView文字列を作成します。
	 * 表示残りデータが pageSize 以下の場合は,残りのデータをすべて出力します。
	 *
	 * @og.rev 5.5.4.2 (2012/07/13) editName指定時の編集対応
	 * @og.rev 5.9.17.0 (2017/12/01) レンデラー利用カラム追加
	 *
	 * @param  startNo	  表示開始位置
	 * @param  pageSize   表示件数
	 *
	 * @return	DBTableModelから作成された HTML文字列
	 */
	@Override
	public String create( final int startNo, final int pageSize )  {
		//if( getRowCount() == 0 ) { return ""; }	// 暫定処置
		
		paramInit();
		
		// 5.9.27.0 (2017/12/01) レンデラー利用カラムの指定（JSONのみの特殊判定）
		boolean[] rendCols = new boolean[clmCnt];
		// Arrays.fill( rendCols ,false );  // falseの場合は不要なので削除しておく
		setBooleanArray( rendererCols,true,rendCols );

		headerLine	 = null;
		int lastNo = getLastNo( startNo, pageSize );

		StringBuilder out = new StringBuilder( HybsSystem.BUFFER_LARGE );

		//JSON開始
		out.append("{").append( HybsSystem.CR );
		
			
		int rowcnt = 0;
		out.append( "\"" + dataName + "\"" ).append(":[");
		for( int row=startNo; row<lastNo; row++ ) {
			if( isSkip( row ) || isSkipNoEdit( row ) ) { continue; } 
			if(rowcnt > 0 ){ out.append(","); }
			rowcnt++;
			out.append( "{" );

			int clmcount = 0;
			for(int clm = 0; clm < clmCnt; clm++) {
				if( isColumnDisplay( clm ) ) {
					if( clmcount > 0 ){ out.append( "," );}
					clmcount++;
					
					out.append("\"" + getColumnName( clm ) + "\":")
					.append( "\"" );
					if( useRenderer || rendCols[clm] ){
						out.append( StringUtil.jsonFilter( getValueLabel(row,clm) ) );
					}
					else{
						out.append( StringUtil.jsonFilter( getValue(row,clm)) );
					}
					out.append( "\"" );
				}
			}
			out.append( "}" );
		}
		out.append("]").append( HybsSystem.CR );
		
		
		if( useHead ){
			out.append(",").append( getHeader() ).append( HybsSystem.CR );
		}
		if( useInfo ){
			out.append(",").append( getInfo(rowcnt) ).append( HybsSystem.CR );
		}
		
		//JSON終わり
		out.append("}").append( HybsSystem.CR );

		return out.toString();
	}
	
	/**
	 * パラメータ内容を初期化します。
	 *
	 * @og.rev 5.9.27.0 (2017/12/01) レンデラー利用カラム追加
	 */
	private void paramInit() {
		useHead		= StringUtil.nval( getParam( ViewJsonParam.JSON_HEAD_KEY      ,  ViewJsonParam.USE_JSON_HEAD ), true);	
		useInfo		= StringUtil.nval( getParam( ViewJsonParam.JSON_INFO_KEY      ,  ViewJsonParam.USE_JSON_INFO ), true);
		useRenderer	= StringUtil.nval( getParam( ViewJsonParam.JSON_RENDERER_KEY      ,  ViewJsonParam.USE_JSON_RENDERER ), false);
		useUtfEncode= StringUtil.nval( getParam( ViewJsonParam.JSON_UTF_ENCODE      ,  ViewJsonParam.USE_JSON_UTFENC ), false);
		dataName	= getParam( ViewJsonParam.JSON_DATANAME_KEY     ,  ViewJsonParam.JSON_DATANAME );	
		
		rendererCols= StringUtil.nval( getParam( ViewJsonParam.JSON_RENDERER_COLS_KEY      ,  ViewJsonParam.JSON_RENDERER_COLS ), "");	 // 5.9.27.0 (2017/12/01)
		
		clmCnt = getColumnCount();
	}

	/**
	 * DBTableModel から テーブルのヘッダータグ文字列を作成して返します。
	 *
	 *
	 * @return	テーブルのヘッダータグ文字列
	 */
	protected String getHeader() {
		return "\"HEAD\":{" + getTableHead() + "}";
	}
	
	/**
	 * DBTableModel から テーブルのタグ文字列を作成して返します。
	 *
	 *
	 * @return	テーブルのタグ文字列
	 */
	protected String getTableHead() {
		StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
		
		buf.append( getHeadLine() );

		return buf.toString();
	}

	/**
	 * ヘッダー繰り返し部を、getTableHead()メソッドから分離。
	 *
	 *
	 * @return	テーブルのタグ文字列
	 */
	protected String getHeadLine() {
		if( headerLine != null ) { return headerLine; }		// キャッシュを返す。

		StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );

		for(int clm = 0; clm < clmCnt; clm++) {
			if( isColumnDisplay( clm ) ) {
				if( buf.length() > 0 ){ buf.append(","); }
				buf.append( "\"" + getColumnName( clm ) + "\"" );
				buf.append(":");
				buf.append( "\"" + StringUtil.jsonFilter( getColumnLabel( clm ) ) + "\"" );
			}
		}
		
		headerLine = buf.toString();
		return headerLine;
	}
	
	/**
	 * DBTableModelの情報を出力します。
	 *
	 * @og.rev  5.9.21.0 (2017/06/02) COLUMN追加
	 *
	 * @return	テーブルのヘッダータグ文字列
	 */
	protected String getInfo( final int rowcount) {
		StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
		
		buf.append( "\"INFO\":{" )
		.append( "\"COUNT\":").append( "\"" + rowcount + "\"" )
		.append( ",\"COLUMN\":" ).append( "\"" + getViewClms() + "\"") // 5.9.21.0 (2017/06/02)
		.append( "}");
		return buf.toString();
	}



	/**
	 * ビューで表示したカラムの一覧をカンマ区切りで返します。
	 *
	 * @og.rev 5.1.6.0 (2010/05/01) 新規追加
	 * @og.rev 5.8.6.0 (2015/04/03) オリジナルカラム対応
	 *
	 * @return	ビューで表示したカラムの一覧
	 */
	@Override
	public String getViewClms() {
		if( viewClms == null ) { return super.getViewClms(); }
		return viewClms;
	}
	
	/**
	 * フォーマットメソッドを使用できるかどうかを問い合わせます。
	 *
	 * @return  使用可能(true)/ 使用不可能(false)
	 */
	public boolean canUseFormat() {
		return false;
	}
}
