/*
 * 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 java.util.Locale;
import java.util.Map ;
import java.util.LinkedHashMap ;

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;

/**
 * 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カラムID    (必須)                  元ファイルのコンテキストパスが登録されているカラムID
 *                   FILE_CLM      :  元ファイルのFILEカラムID    (必須)                  元ファイルのファイル名が登録されているカラムID
 *                   THUMB_CLM     :  サムネイルのカラムID                                サムネイルのPATH/FILEが登録、または書き戻し用のカラムID
 *                   THUMB_DIR     :  サムネイルの管理フォルダ            初期値 _thumb/  サムネイルを作成する中間管理フォルダ名
 *                   THUMB_SUFIX   :  サムネイルの拡張子                  初期値 AUTO     AUTOは元と同じ拡張子を使います。
 *                   OVERWRITE     :  上書きするかどうか                  初期値 false    サムネイルを作成する時、上書きするかどうかを指定します。
 *                   MAX_SIZE      :  サムネイルの最大ピクセル数          初期値 128      サムネイルを作成する時の画像ファイルの大きさ。比率はキープされます。
 *               }
 *         &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 = "5.6.6.1 (2013/07/12)" ;

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

	/**
	 * keys の整合性チェックを行うための初期設定を行います。
	 *
	 * @og.rev 5.6.6.1 (2013/07/12) keys の整合性チェック対応
	 *
	 * @param	keysMap keys の整合性チェックを行うための Map
	 */
	@Override
	protected void init( final Map<String,String> keysMap ) {
		keysMap.put( "PATH_CLM"		, "元ファイルのPATHカラムID (必須)"				);
		keysMap.put( "FILE_CLM"		, "元ファイルのFILEカラムID (必須)"				);
		keysMap.put( "THUMB_CLM"	, "サムネイルのカラムID"						);
		keysMap.put( "THUMB_DIR"	, "サムネイルの管理フォルダ   (初期値 _thumb/)"	);
		keysMap.put( "THUMB_SUFIX"	, "サムネイルの拡張子         (初期値 AUTO)"	);		// 5.6.6.1 (2013/07/12)
		keysMap.put( "OVERWRITE"	, "上書きするかどうか         (初期値 false"	);
		keysMap.put( "MAX_SIZE"		, "サムネイルの最大ピクセル数 (初期値 128"		);
	}

	/**
	 * DBTableModel処理を実行します。
	 *
	 * @og.rev 5.6.6.1 (2013/07/12) THUMB_SUFIXを追加
	 *
	 * @return 処理結果のDBTableModel
	 */
	public DBTableModel execute() {
		DBTableModel table = getDBTableModel();		// 5.5.2.6 (2012/05/25) インターフェースにgetterメソッド追加

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

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

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

				// ① サムネイル作成対象の拡張子の場合のみ処理します。よって、sufix は存在することが保障されます。
				if( ImageResizer.isReaderSuffix( fileClmVal ) ) {
					// サムネイルのファイルを構築します。
					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 ) {
						// 元ファイルの拡張子を取り出します。(小文字化も行います。)
						String sufix  = ImageResizer.getSuffix( fileClmVal );
						String thumbName = fileClmVal ;
						// 5.6.6.1 (2013/07/12) サムネイルの拡張子
						if( ! "AUTO".equalsIgnoreCase( thumb_sufix ) ) {	// AUTO以外が指定された場合
							thumbName = fileClmVal.substring( 0,fileClmVal.length()-sufix.length() ) + thumb_sufix ;
						}
						// 5.6.6.1 (2013/07/12) 拡張子が bmp の場合の、png に置き換えはしない。
//						if( "bmp".equalsIgnoreCase( sufix ) ) {
//							thumbName = fileClmVal.substring( 0,fileClmVal.length()-3 ) + "png" ;		// 拡張子が bmp の場合は、png に置き換えます。
//						}

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

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

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

					// 実際のサムネイルの作成処理
					ImageResizer imgRes = new ImageResizer( orgFile.getAbsolutePath() );		// 変換元のファイル名
					imgRes.resizeByPixel( thumbFile.getAbsolutePath() , max_size );				// 変換先のファイル名と画像の大きさ
				}
			}
			catch( RuntimeException ex ) {
				if( errMessage == null ) { errMessage = makeErrorMessage( "TableFilter_THUMBNAIL Error",ErrorMessage.NG ); }
				errMessage.addMessage( row+1,ErrorMessage.NG,ex.getMessage() );
			}
		}

		return table;
	}
}
