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

import java.text.DecimalFormat;

import org.opengion.fukurou.util.StringUtil;
import org.opengion.hayabusa.db.AbstractRenderer;
import org.opengion.hayabusa.db.CellRenderer;
import org.opengion.hayabusa.db.DBColumn;

/**
 * UNIT レンデラーは、カラムのデータの単位変換を行う場合に使用するクラスです。
 *
 * マイナス表示はありません。
 * 単位は、RendererParam で指定します。
 * 単位の自動変換を（ある程度）サポートします。
 * KB,MB,GB,TB は、それぞれを、1024の倍数で割り算して求めます。
 * それ以外では、K*,M*,G* に対して、先頭文字で判断して、1000の倍数で割り算します。
 * それ以外の単位変換は、サポートしていません。
 * (数値の後ろに変換なしで文字列を付けるだけです。)
 *
 * 負数の場合はspanタグclass="minus"を付けて出力します。
 *
 * 単位変換時の小数点は切り上げします。ただし、データが nullかゼロ文字列か、0 の場合は、0 になります。
 * 1Byteのﾌｧｲﾙの場合は、1 KB という表示になります。
 *
 * カラムの表示に必要な属性は, DBColumn オブジェクト より取り出します。
 * このクラスは、DBColumn オブジェクト毎に１つ作成されます。
 *
 * @og.group データ表示
 * @og.rev 7.2.3.1 (2020/04/17) 新規追加
 *
 * @version  7.2
 * @author	 Kazuhiko Hasegawa
 * @since    JDK11.0,
 */
public class Renderer_UNIT extends AbstractRenderer {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "7.2.3.1 (2020/04/17)" ;

	private static final DecimalFormat FMT1 = new DecimalFormat( "#,##0" );

	private final String	unit ;
	private final long		division ;

	/**
	 * デフォルトコンストラクター。
	 * このコンストラクターで、基本オブジェクトを作成します。
	 *
	 * @og.rev 7.2.3.1 (2020/04/17) Renderer_UNIT 新規追加
	 *
	 */
	public Renderer_UNIT() {
		this( "",1L );
	}

	/**
	 * コンストラクター
	 *
	 * @og.rev 7.2.3.1 (2020/04/17) Renderer_UNIT 新規追加
	 *
	 * @param	tani	単位記号
	 * @param	div		単位換算の除数
	 */
	private Renderer_UNIT( final String tani,final long div ) {
		super();
		unit		 = tani;
		division	 = div;
	}

	/**
	 * 各オブジェクトから自分のインスタンスを返します。
	 * 自分自身をキャッシュするのか、新たに作成するのかは、各サブクラスの実装に
	 * まかされます。
	 *
	 * @og.rev 7.2.3.1 (2020/04/17) Renderer_UNIT 新規追加
	 *
	 * @param	clm	DBColumnオブジェクト
	 *
	 * @return	CellRendererオブジェクト
	 * @og.rtnNotNull
	 */
	public CellRenderer newInstance( final DBColumn clm ) {
		// 単位は、RendererParamから取得
		final String tani = StringUtil.nval( clm.getRendererParam() , "" );

		long div = 1L;

		// KB,MB,GB,TB は、それぞれを、1024の倍数で割り算して求めます。
		// それ以外では、K*,M*,G* に対して、先頭文字で判断して、1000の倍数で割り算します。
		if( !tani.isEmpty() ) {
			final char ch1 = tani.charAt(0);		// 最初の文字(K,M,G,T)
			final int base = tani.length() >= 2 && tani.charAt(1) == 'B' ? 1024 : 1000 ;

			switch( ch1 ) {
				case 'K' : div = base; break;
				case 'M' : div = base*base; break;
				case 'G' : div = base*base*base; break;
				case 'T' : div = base*base*base*base; break;
				default  : div = 1L; break;
			}
		}

		return new Renderer_UNIT( tani,div );
	}

	/**
	 * データの表示用文字列を返します。
	 *
	 * @og.rev 7.2.3.1 (2020/04/17) Renderer_UNIT 新規追加
	 *
	 * @param	value 入力値(『数字型文字列』)
	 *
	 * @return	データの表示用文字列
	 * @og.rtnNotNull
	 */
	@Override
	public String getValue( final String value ) {
		return getValue( value , true );
	}

	/**
	 * データ出力用の文字列を作成します。
	 * ファイル等に出力する形式を想定しますので、HTMLタグを含まない
	 * 生データを返します。
	 * 基本は、#getValue( String ) をそのまま返します。
	 *
	 * @og.rev 7.2.3.1 (2020/04/17) Renderer_UNIT 新規追加
	 *
	 * @param	value 入力値(『数字型文字列』)
	 *
	 * @return  データ出力用の文字列(数字型文字列 のみ)
	 * @og.rtnNotNull
	 * @see		#getValue( String )
	 */
	@Override
	public String getWriteValue( final String value ) {
		return getValue( value , false );
	}

	/**
	 * データ表示用/出力用の文字列を作成します。
	 * 第二引数の isView == true で、データ表示用文字列を、false で
	 * データ出力用の文字列を作成します。
	 * 処理の共通化を行うためのメソッドです。
	 *
	 * @og.rev 7.2.3.1 (2020/04/17) Renderer_UNIT 新規追加
	 *
	 * @param	value 入力値(『数字型文字列』)
	 * @param   isView データ表示用かどうか(true:表示用/false:出力用)
	 *
	 * @return  データ表示用/出力用の文字列
	 * @og.rtnNotNull
	 * @see		#getValue( String )
	 */
	private String getValue( final String value , final boolean isView ) {
		String rtn = value == null || value.trim().isEmpty() ? "0" : value ;

		final long val = ( Long.parseLong( rtn ) + division - 1 ) / division ;		// 切り上げ

		synchronized( FMT1 ) {							// 7.2.9.5 (2020/11/28)
			rtn = FMT1.format( val ) + " " + unit ;
		}

 		if( !isView ) { return rtn; }					// 6.2.0.0 (2015/02/27) マイナス記号のまま

		if( StringUtil.startsChar( rtn , '-' ) ) {
			rtn = "<span class=\"minus\">" + rtn + "</span>";
		}
		return rtn;
	}
}
