/*********************************************************************
*  All Rights reserved,Copyright (c) K-Opticom						 *
**********************************************************************
*＜プログラム内容＞
*	システム名			：eo顧客基幹システム
*	モジュール名		：JKKSmtvRcvFile
*	ソースファイル名	：JKKSmtvRcvFile.java
*	作成者				：富士通　
*	作成日				：2012年08月25日
*＜機能概要＞
*　HTTPファイル受信用アクセスクラス
*＜修正履歴＞
*	バージョン	修正日		修正者		修正内容
*	v4.00.00	2012/08/25   富士通		新規作成
*********************************************************************/
package eo.business.common;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import eo.common.constant.JPCBatchMessageConstant;
import eo.framework.application.JBSbatBusinessException;

/**
 * スマートバリュー申込ファイル取得<p>
 * スマートバリュー申込情報ファイルを取り込む。
 * サイトよりフィル名のリストを取得し、ファイル名の一番大きなもの
 * （日付部分の比較が文字列辞書的に正しく判定されること前提）を取得し、
 * 取得したファイルを保存する。
 * 正常にファイルが作成された場合は、フラグファイルを作成する。
 * <br>
 * @author 富士通
 */

public class JKKSmtvRcvFile extends JKKHttpCommunicator {

	/** PROXYホストを取得するキー */
	private static final String S_KEY_PROXY_HOST = "KK_SMTV_DL_PROXY_HOST";

	/** PROXYポートを取得するキー */
	private static final String S_KEY_PROXY_PORT = "KK_SMTV_DL_PROXY_PORT";	

	/** リストを受信URLを取得するキー */
	private static final String S_KEY_URL_STR = "KK_SMTV_DL_URL";
	
	/** 認証ユーザを取得するキー */
	private static final String S_KEY_USER_STR = "KK_SMTV_DL_USERID";
	
	/** 認証パスワードを取得するキー */
	private static final String S_KEY_PASS_STR = "KK_SMTV_DL_PASSWD";
	
	/** タイムアウトを取得するキー */
	private static final String S_KEY_TIMEOUT_STR = "KK_SMTV_DL_TIMEOUT";
	
	/** リトライ数を取得するキー */
	private static final String S_KEY_RETRY_STR = "KK_SMTV_DL_RETRYCOUNT";
	
	/** リトライ後の待機時間を取得するキー */
	private static final String S_KEY_INTERVAL_STR = "KK_SMTV_DL_RETRYINTERVAL";
	
	/** ファイル名を取得するための正規表現 */
	private static final String S_FILE_NAME = "ft902003\\.[0-9]{12}";
	
	/** ファイルのレコード区分 ヘッダ*/
	private static final String S_REC_KBN_HEADER = "10";
	
	/** ファイルのレコード区分 明細 */
	private static final String S_REC_KBN_DETAIL = "20";
	
	/** ファイルのレコード区分 トレーラ */
	private static final String S_REC_KBN_TRAILER = "80";
	
	/** コンテンツリスト取得モード　*/
	private static final int I_LIST = 0;
	
	/** コンテンツファイル取得モード　*/
	private static final int I_FILE = 1;
	
	/** フラグファイルの拡張子 */
	private static final String FLAG_SUFFIX = ".flg";

	/** 受信コンテンツの処理モード */
	private int mode = I_LIST;
	
	/** 最新のファイル名 */
	private String lastFileName = null;
	
	/** ファイル名をチェックする正規表現 */
	private Pattern pattern = Pattern.compile(S_FILE_NAME);

	private static final String S_MSG_SETSUZOKU_SAKI = "接続先";
	
	private static final String S_MSG_SHUTSURYOKU_DIR = "出力先ディレクトリ";
	
	/** 書き込み用 */
	private BufferedWriter writer = null;
	
	/** レコード件数 */
	private int recordCount = 0;
	
	/** トレーラ レコード件数 */
	private int trRecordCount = -1;
	
	/**
	 * デフォルトコンストラクタ
	 */
	public JKKSmtvRcvFile()
	{
	}
	
	/**
	 * 実行する
	 * @param receiveDir ファイル受信ディレクトリ
	 * @throws Exception 例外を返す
	 */
	public void invoke(String receiveDir) throws Exception
	{

		// 出力先ディレクトリを取得
		String outFileDir = receiveDir;
		if (outFileDir == null || outFileDir.length() == 0)
		{
			throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0130CE, new String[] {S_MSG_SHUTSURYOKU_DIR});
		}
		
		// PROXYを取得する
		String proxyHost = getApplicationConst(S_KEY_PROXY_HOST, false);
		String proxyPort = getApplicationConst(S_KEY_PROXY_PORT, false);
		
		setProxy(proxyHost, proxyPort);
		
		// 接続先を指定する（必須）
		String urlStr = getApplicationConst(S_KEY_URL_STR, false);
		
		if (urlStr == null || urlStr.length() == 0)
		{
			throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0130CE, new String[] {S_MSG_SETSUZOKU_SAKI});
		}

		// URLに変換
		URL url = new URL(urlStr);
		
		// SSLの場合は証明書関係の初期化を行う
		if (url.getProtocol().equalsIgnoreCase(JKKHttpCommunicator.S_HTTPS))
		{
			JKKHttpCommunicator.initializeSSL();
		}
		
		// 認証情報の取得
		String user   = getApplicationConst(S_KEY_USER_STR, false);
		String passwd = getApplicationConst(S_KEY_PASS_STR, true);	// パスワードは暗号化

		if (user != null && user.length() > 0)
		{
			initializeAuthentication(user, passwd);
		}
		
		// その他の属性を設定
		setTimeout(Integer.parseInt(getApplicationConst(S_KEY_TIMEOUT_STR, false)));
		setRetryCount(Integer.parseInt(getApplicationConst(S_KEY_RETRY_STR, false)));
		setRetryInterval(Integer.parseInt(getApplicationConst(S_KEY_INTERVAL_STR, false)));
		
		// モードをリスト取得に設定する
		mode = I_LIST;
		
		// 接続URLの設定
		setTargetURL(url);
					
		// 実行する。
		if (execute()) 
		{
			// ファイルが取得できなかった場合は正常終了
			if (lastFileName == null)
			{
				return;
			}
			// -------------------------------------------------------------
			File outFile = new File(outFileDir, lastFileName);
			File flagFile = new File(outFileDir, lastFileName + FLAG_SUFFIX);
			
			// ファイル受信モードに指定
			mode = I_FILE; 
			// URLの作成
			url = new URL(url,  lastFileName);
			// 新しいURLを指定
			setTargetURL(url);
			try {
				writer = new BufferedWriter(new FileWriter(outFile));
				// 20130415 ST1-2013-0000522 ADD START
				// 2回目のリクエストをすぐ出すとHTTPステータス502が返却されて接続できない(原因は未調査)
				// 一定時間待ってから2回目のリクエストをだす
				try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
				}
				// 20130415 ST1-2013-0000522 MOD END
				// 実行する。
				if (execute()) 
				{
					// フラグファイルを作成する
					if (!flagFile.createNewFile())
					{
						throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0140CE);
					}
				}
				else 
				{
					throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0140CE);
				}
			} 
			finally 
			{
				if (writer != null)
				{
					writer.close();
					writer = null;
				}
			}
		}
		else 
		{
			throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0140CE);
		}
	}

	/**
	 * コンテンツ受信データを処理する
	 */
	@Override
	protected void receiveContentAtLine(String val) throws IOException 
	{
		if (mode == I_LIST)
		{
			// 指定ファイル名を探す
			Matcher m = pattern.matcher(val);
			while (m.find())
			{
				int start = m.start();
				int end   = m.end();
				String work = val.substring(start, end);
				if (lastFileName == null || lastFileName.compareTo(work) < 0)
				{
					lastFileName = work;
				}
				
			}
			
		}
		else 
		{
			// 行データを書き込む
			writer.write(val + "\n");
			String kbn = val.substring(0, 2);
			if (S_REC_KBN_DETAIL.equals(kbn))
			{
				recordCount ++; // レコード件数をカウント
			}
			else if (S_REC_KBN_HEADER.equals(kbn))
			{
				recordCount = 0; 	// レコード件数を初期化
				trRecordCount = -1; // 
			}
			else if (S_REC_KBN_TRAILER.equals(kbn))
			{
				// トレーラの件数を返す
				// OM-2013-0000423 スマートバリュー申込情報取込反映の純バッチ化対応 2013/08/26 START
//				String work = val.substring(2, 10);
				String work = val.substring(2, 11);
				// OM-2013-0000423 スマートバリュー申込情報取込反映の純バッチ化対応 2013/08/26 END
				if (work != null)
				{
					trRecordCount = Integer.parseInt(work);
				}
			}
		}
	}
	
	/**
	 * 受信ファイルの存在を返す
	 * <br>
	 * @return 存在する場合はtrue
	 */
	public boolean existReceiveFile() 
	{
		return lastFileName != null;
	}
	
	/**
	 * 受信ファイルをチェックする。
	 * <br>
	 * @return 受信ファイルの整合結果
	 */
	public boolean validReceiveFile()
	{
		return recordCount == trRecordCount;
	}

	/**
	 * 最新のファイル名を返します。
	 * @return 最新のファイル名
	 */
	// OM-2013-0000423 スマートバリュー申込情報取込反映の純バッチ化対応 2013/08/26 START
	public String getLastFileName()
	{
		return lastFileName;
	}
	// OM-2013-0000423 スマートバリュー申込情報取込反映の純バッチ化対応 2013/08/26 END

}
