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

import java.io.File;

import org.opengion.hayabusa.common.HybsSystemException;
import org.opengion.hayabusa.common.HybsSystem;
import org.opengion.hayabusa.db.AbstractTableFilter;
import org.opengion.hayabusa.db.DBTableModel;

import org.opengion.fukurou.util.ErrorMessage;
import org.opengion.fukurou.util.StringUtil;
import org.opengion.fukurou.util.ImageResizer;
import org.opengion.fukurou.util.ImageUtil;			// 6.0.2.3 (2014/10/10) ImageUtil 使用

/**
 * TableFilter_THUMBNAIL は、TableFilter インターフェースを継承した、DBTableModel 処理用の
 * 実装クラスです。
 *
 * ここでは、オリジナルファイルのサムネイルファイルを作成します。
 * keys と vals に指定する値を以下に示します。
 *
 * <table border="1" frame="box" rules="all" >
 *   <caption>keys と vals に指定する値</caption>
 *   <tr><th>KEY        </th><th>VAL                        </th><th>(必須) </th><th>初期値 </th><th>解説                                                                   </th></tr>
 *   <tr><td>PATH_CLM   </td><td>元ファイルのPATHカラムID   </td><td>必須   </td><td>       </td><td>元ファイルのコンテキストパスが登録されているカラムID                   </td></tr>
 *   <tr><td>FILE_CLM   </td><td>元ファイルのFILEカラムID   </td><td>必須   </td><td>       </td><td>元ファイルのファイル名が登録されているカラムID                         </td></tr>
 *   <tr><td>THUMB_CLM  </td><td>サムネイルのカラムID       </td><td>       </td><td>       </td><td>サムネイルのPATH/FILEが登録、または書き戻し用のカラムID                </td></tr>
 *   <tr><td>THUMB_DIR  </td><td>サムネイルの管理フォルダ   </td><td>       </td><td>_thumb/</td><td>サムネイルを作成する中間管理フォルダ名                                 </td></tr>
 *   <tr><td>THUMB_SUFIX</td><td>サムネイルの拡張子         </td><td>       </td><td>AUTO   </td><td>サムネイルの拡張子を指定します。AUTOは、元のままです。                 </td></tr>
 *   <tr><td>OVERWRITE  </td><td>上書きするかどうか         </td><td>       </td><td>false  </td><td>サムネイルを作成する時、上書きするかどうかを指定します。               </td></tr>
 *   <tr><td>MAX_SIZE   </td><td>サムネイルの最大ピクセル数 </td><td>       </td><td>128    </td><td>サムネイルを作成する時の画像ファイルの大きさ。比率はキープされます。   </td></tr>
 * </table>
 *
 * 【解説】
 * １．PATH_CLM ＋ FILE_CLMのカラム列の値が、元ファイルのコンテキストパス以下のファイルのアドレスになります。
 * ２．サムネイルは通常、元フォルダに管理フォルダを作成し、その下に、元ファイルと同じ名前のサムネイルファイルを作成します。
 *     つまり、PATH_CLM ＋ THUMB_DIR ＋ FILE_CLM ＋ 拡張子が、サムネイルのファイル名になります。
 * ３．THUMB_SUFIX を指定した場合は、サムネイルの拡張子を変更できます。初期値は、AUTOです。
 *     AUTOの場合は、元ファイルと同じ拡張子が使われます。自分で指定する場合は、拡張子違いの元ファイルがあれば重複しますので注意が必要です。
 * ４．サムネイルを作成できるのは、bmp/jpeg/png/gif/tif だけです。それ以外のファイルについては、ICONレンデラー等を使用して、自分でサムネイル表示するようにして下さい。
 *     ただし、将来的には、xls/ppt/doc/pdf などの主要なファイルフォーマットのサムネイルは作成したいと考えています。
 * ５．THUMB_CLM にサムネイルのファイル名が記述されている場合、その名前でサムネイルを作成します。このとき、OVERWRITE=true の場合は、既存ファイルの有無に関係なく
 *     上書き（再作成）されます。OVERWRITE=false(初期値)の場合は、すでに存在していれば、そのままとします。
 * ６．THUMB_CLM にサムネイルのファイル名が記述されていない場合は、標準のファイル名でサムネイルを作成して、THUMB_CLMカラムに書き戻します。
 *     この場合、既存ファイルの有無に関係なく、上書き（再作成）されます。
 * ７．THUMB_CLM が指定されていない場合は、カラムに書き戻し処理を行いません。(６．と同じで、書き戻しを行いません。)
 * ８．MAX_SIZE は、サムネイルを作成する場合、縦、横の最大ピクセルに、縮小されます。比率は変わりません。これは物理的なサムネイルファイルのサイズです。
 *
 * なお、ドキュメント管理系で、自動スキャン取込みで、ファイルやフォルダの先頭に、アンダーバーがついている場合は、スキャン対象から外します。
 * ドキュメントシステムから見た場合の、隠しファイルの扱いです。サムネイルも、デフォルトでは、アンダーバー付のフォルダに作成します。
 * これは、自動スキャンで、サムネイルのサムネイルを作成することを避ける意味合いもあります。
 * また、サムネイルの一括削除などに都合が良いと思います。
 *
 * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか、BODY 部にCSS形式で記述します。
 * @og.formSample
 * ●形式：
 *      ① &lt;og:tableFilter classId="THUMBNAIL" keys="PATH_CLM,FILE_CLM" vals="PATH,NMFILE" /&gt;
 *
 *      ② &lt;og:tableFilter classId="THUMBNAIL" &gt;
 *               {
 *                   PATH_CLM      :  PATH ;
 *                   FILE_CLM      :  NMFILE ;
 *               }
 *         &lt;/og:tableFilter&gt;
 *
 * @og.rev 5.6.5.1 (2013/06/14) 新規追加
 * @og.rev 5.6.6.0 (2013/07/05) keys の整合性チェックを追加
 *
 * @version  0.9.0  2000/10/17
 * @author   Kazuhiko Hasegawa
 * @since    JDK1.1,
 */
public class TableFilter_THUMBNAIL extends AbstractTableFilter {
	/** このプログラムのVERSION文字列を設定します。	{@value} */
	private static final String VERSION = "6.5.0.1 (2016/10/21)" ;

	private static final String REAL_PATH = HybsSystem.sys( "REAL_PATH" );

	/**
	 * デフォルトコンストラクター
	 *
	 * @og.rev 6.4.1.1 (2016/01/16) keysMap を、サブクラスから設定させるように変更。
	 */
	public TableFilter_THUMBNAIL() {
		super();
		initSet( "PATH_CLM"		, "元ファイルのPATHカラムID (必須)"				);
		initSet( "FILE_CLM"		, "元ファイルのFILEカラムID (必須)"				);
		initSet( "THUMB_CLM"	, "サムネイルのカラムID"						);
		initSet( "THUMB_DIR"	, "サムネイルの管理フォルダ   (初期値 _thumb/)"	);
		initSet( "THUMB_SUFIX"	, "サムネイルの拡張子         (初期値 AUTO)"	);		// 5.6.6.1 (2013/07/12)
		initSet( "OVERWRITE"	, "上書きするかどうか         (初期値 false"	);
		initSet( "MAX_SIZE"		, "サムネイルの最大ピクセル数 (初期値 128"		);
	}

	/**
	 * DBTableModel処理を実行します。
	 *
	 * @og.rev 5.6.6.1 (2013/07/12) THUMB_SUFIXを追加
	 * @og.rev 6.0.2.3 (2014/10/10) ImageResizer → ImageUtil に変更
	 * @og.rev 6.5.0.1 (2016/10/21) ErrorMessage をまとめるのと、直接 Throwable を渡します。
	 *
	 * @return 処理結果のDBTableModel
	 */
	public DBTableModel execute() {
		final DBTableModel table = getDBTableModel();		// 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加

		final String  path_clm		= StringUtil.nval( getValue( "PATH_CLM"		) , null		);		// 必須項目
		final String  file_clm		= StringUtil.nval( getValue( "FILE_CLM"		) , null		);		// 必須項目
		final String  thumb_clm		= StringUtil.nval( getValue( "THUMB_CLM"	) , null		);		// なければ、値戻しをしない。
		final String  thumb_dir		= StringUtil.nval( getValue( "THUMB_DIR"	) , "_thumb/"	);		// サムネイルフォルダ
		final String  thumb_sufix		= StringUtil.nval( getValue( "THUMB_SUFIX"	) , "AUTO"		);		// 5.6.6.1 (2013/07/12) サムネイルの拡張子
		final boolean isOverwrite		= StringUtil.nval( getValue( "OVERWRITE"	) , false		);		// サムネイルの再作成有無
		final int     max_size		= StringUtil.nval( getValue( "MAX_SIZE"		) , 128			);

		final int path_clmNo  = table.getColumnNo( path_clm , true  );		// 存在しない場合は、エラー
		final int file_clmNo  = table.getColumnNo( file_clm , true  );		// 存在しない場合は、エラー
		final int thumb_clmNo = table.getColumnNo( thumb_clm , false );		// 存在しない場合は、-1 を返す。

		ErrorMessage errMessage = null;
		final int rowCnt = table.getRowCount();
		for( int row=0; row<rowCnt; row++ ) {
			try {
				// オリジナルのファイルを構築します。
				final String pathClmVal = table.getValue( row,path_clmNo );
				final String fileClmVal = table.getValue( row,file_clmNo );
				final File orgFile = new File( StringUtil.urlAppend( REAL_PATH , pathClmVal ),fileClmVal );		// オリジナルファイル名
				if( !orgFile.exists() ) {
		//		final String errMsg = "元ファイルが存在しません。[" + orgFile.toString() + "]" ;				// ファイルがなければエラー
		//			throw new OgRuntimeException( errMsg );
					continue;																				// 5.6.6.0 (2013/07/05) なければ無視
				}

				// ① サムネイル作成対象の拡張子の場合のみ処理します。よって、sufix は存在することが保障されます。
				if( ImageUtil.isReaderSuffix( fileClmVal ) ) {			// 6.0.2.3 (2014/10/10) ImageResizer → ImageUtil に変更
					// サムネイルのファイルを構築します。
					File thumbFile = null;
					String thumbClmVal = null;
					if( thumb_clmNo >= 0 ) {
						thumbClmVal = table.getValue( row,thumb_clmNo );
						if( thumbClmVal != null && thumbClmVal.length() > 0 ) {			// サムネイルファイル名が指定された場合
							thumbFile = new File( REAL_PATH , thumbClmVal );
							if( !isOverwrite && thumbFile.exists() ) { continue; }		// ファイルが存在した場合は、処理しない
						}
						else {
							thumbClmVal = null;
						}
					}

					// ①-1 thumbClmVal が未定義(=null)の場合は、自分でファイル名を構築する
					if( thumbClmVal == null ) {
						// 元ファイルの拡張子を取り出します。(小文字化も行います。)
						final String sufix  = ImageUtil.getSuffix( fileClmVal );				// 6.0.2.3 (2014/10/10) ImageResizer → ImageUtil に変更
						// 6.3.9.1 (2015/11/27) Found 'DD'-anomaly for variable(PMD)
						final String thumbName = "AUTO".equalsIgnoreCase( thumb_sufix ) ? fileClmVal : fileClmVal.substring( 0,fileClmVal.length()-sufix.length() ) + thumb_sufix ;

						thumbClmVal = StringUtil.urlAppend( pathClmVal,thumb_dir,thumbName );			// サムネイルのアドレス/ファイル名
						thumbFile = new File( REAL_PATH , thumbClmVal );

						if( thumb_clmNo >= 0) {
							table.setValueAt( thumbClmVal,row,thumb_clmNo );			// サムネイルファイル名の書き戻し
						}
					}

					// サムネイル保存先のディレクトリ作成
					final File parent = thumbFile.getParentFile();
					if( !parent.exists() && !parent.mkdirs() ) {
						final String errMsg = "サムネイル保存先のディレクトリ作成に失敗しました。file=[" + parent.toString() + "]";
						throw new HybsSystemException( errMsg );
					}

					// 実際のサムネイルの作成処理
					final ImageResizer imgRes = new ImageResizer( orgFile.getAbsolutePath() );		// 変換元のファイル名
					imgRes.resizeByPixel( thumbFile.getAbsolutePath() , max_size );				// 変換先のファイル名と画像の大きさ
				}
			}
			catch( final RuntimeException ex ) {
				// 6.5.0.1 (2016/10/21) ErrorMessage をまとめるのと、直接 Throwable を渡します。
				if( errMessage == null ) { errMessage = makeErrorMessage( "TableFilter_THUMBNAIL Error",ErrorMessage.NG ); }
				errMessage.addMessage( row+1,ErrorMessage.NG,"THUMBNAIL" )
					.addMessage( ex );
			}
		}

		return table;
	}
}
