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

import org.opengion.fukurou.util.FileUtil;
import org.opengion.fukurou.util.Closer;

import java.io.File;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Date;
import java.util.Locale;
import java.text.DateFormat;
import java.text.SimpleDateFormat;


/**
 * FileLineModel は、LineModel を継承した ファイルリスト専用の
 * LineModel の実装クラスです。
 *
 * FileLineModel オブジェクトには、ファイル属性(Level,File,Length,Modify)
 * が設定されます。
 *
 * データの１行分を FileLineModel に割り当てます。
 * カラム番号は、0 から始まります。カラム名よりカラム番号を求める場合に、
 * 存在しない場合は、-1 を返します。
 * カラム番号が -1 の場合は、処理を行いません。
 *
 * 注意：このクラスは、同期処理されていません。
 *
 * @version  4.0
 * @author   Kazuhiko Hasegawa
 * @since    JDK5.0,
 */
public class FileLineModel extends LineModel {
	private static final String[] KEYS = new String[] { "Level","File","Length","Modify","LineCnt","Biko" };

	private static final int LEVEL    = 0;
	private static final int FILE     = 1;
	private static final int LENGTH   = 2;
	private static final int MODIFY   = 3;
	private static final int LINECNT  = 4;
	private static final int BIKO     = 5;

	private final DateFormat formatter = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss",Locale.JAPAN );

	private final boolean useLineCnt ;

	/**
	 * コンストラクターです。
	 *
	 */
	public FileLineModel() {
		this( false );
//		super();
//		init( KEYS );
	}

	/**
	 * コンストラクターです。
	 *
	 * @og.rev 4.2.2.0 (2008/05/10) 行数カウントの使用有無
	 *
	 * @param   isLineCnt	boolean	行数カウントの使用有無
	 */
	public FileLineModel( final boolean isLineCnt ) {
		// 4.3.4.4 (2009/01/01)
//		super();
		useLineCnt = isLineCnt;
		init( KEYS );
	}

	/**
	 * LineModel を元に、FileLineModel を構築します。
	 * これは、一旦ファイル等にセーブされた FileLineModel 形式を
	 * 元に戻す簡易コンストラクタです。
	 *
	 * @og.rev 4.2.3.0 (2008/05/26) 新規追加
	 *
	 * @param   model	LineModel	元のLineModel
	 */
	public FileLineModel( final LineModel model ) {
		// 4.3.4.4 (2009/01/01)
//		super();
		init( model.getNames() );

		Object[] obj = model.getValues();

		setValue( LEVEL   ,Integer.valueOf( (String)obj[LEVEL] ) );
		setValue( FILE    ,new File((String)obj[FILE]) );
		setValue( LENGTH  ,Long.valueOf( (String)obj[LENGTH] ) );
		setValue( MODIFY  ,(String)obj[MODIFY] );

		String cnt = (String)obj[LINECNT] ;
		useLineCnt = ( cnt != null && cnt.length() > 0 && ! "null".equals( cnt ) );
		if( useLineCnt ) { setValue( LINECNT ,cnt ); }

		setValue( BIKO  ,(String)obj[BIKO] );
	}

	/**
	 * File属性値をセットします。
	 * LEVEL,FILE,LENGTH,MODIFY の各属性を設定します。
	 *
	 * @og.rev 4.2.2.0 (2008/05/10) 行数カウントの使用有無
	 *
	 * @param   level	int		ファイルのディレクトリ階層
	 * @param   file	File	ファイルオブジェクト
	 */
	public void setFileVals( final int level, final File file ) {
		setValue( LEVEL  ,Integer.valueOf( level ) );
		setValue( FILE   ,file );
		setValue( LENGTH ,Long.valueOf( file.length() ) );
		setValue( MODIFY ,formatter.format( new Date( file.lastModified() ) ) );
		if( useLineCnt ) { setValue( LINECNT ,getLineCnt( file ) ); }
	}

	/**
	 * File属性値をセットします。
	 *
	 * @param   file	File	ファイルオブジェクト
	 */
	public void setFile( final File file ) {
		setValue( FILE,file );
	}

	/**
	 * 備考情報属性値をセットします。
	 *
	 * @og.rev 4.2.2.0 (2008/05/10) 行数カウントの使用有無
	 *
	 * @param   biko	String	備考情報
	 */
	public void setBiko( final String biko ) {
		setValue( BIKO,biko );
	}

	/**
	 * レベル File属性値を取得します。
	 *
	 * @return   int	ファイルのディレクトリ階層
	 */
	public int getLebel() {
		return ((Integer)getValue( LEVEL )).intValue();
	}

	/**
	 * ファイルを取得します。
	 *
	 * @return   File	ファイル
	 */
	public File getFile() {
		return (File)getValue( FILE );
	}

	/**
	 * ファイルサイズ File属性値を取得します。
	 *
	 * @return   long	ファイルサイズ
	 */
	public long getLength() {
		return ((Long)getValue( LENGTH )).longValue();
	}

	/**
	 * 更新日時 File属性値を取得します。
	 *
	 * @return   String	更新日時(yyyy/MM/dd HH:mm:ss)
	 */
	public String getModify() {
		return (String)getValue( MODIFY );
	}

	/**
	 * 行数を取得します。
	 *
	 * @param  file  File	行数を数えるファイルオブジェクト
	 * @return  行数
	 */
	private String getLineCnt( final File file ) {
		int cnt = 0;

		BufferedReader reader = FileUtil.getBufferedReader( file,"JISAutoDetect" );

		try {
			if( ! file.isDirectory() ) {
//				String line ;	// findbugs で、意味の無い代入チェックがかかりますが、OKです。
//				while((line = reader.readLine()) != null) {
//					cnt++;
//				}
				while( reader.readLine() != null) {
					cnt++;
				}
			}
		}
		catch( IOException ex ) {
			String errMsg = "ファイルカウント中に例外が発生しました。[" + file + "]" ;
			throw new RuntimeException( errMsg,ex );
		}
		finally {
			Closer.ioClose( reader ) ;
		}

		return String.valueOf( cnt );
	}
}
