/*
 * 携帯ＳＣＯＲＭエントリ
 * 
 * 作成日: 2006/10/23
 *
 * 変更履歴
 *   ユーザーエージェント判定機能追加 ntc-hagiwara '07/06/08
 *
 */
package jp.co.ntt.lms.imode.xms.servlet;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import jp.co.ntt.lms.imode.common.MobConst;
import jp.co.ntt.lms.imode.common.MobileUtl;
import jp.co.ntt.lms.imode.extension.PageSequence;
import jp.co.ntt.lms.imode.lo.scorm.engine.MobSCORMBean;
import jp.co.ntt.lms.xmo.util.DebugLog;
import jp.co.ntt.lms.xms.framework.XmsException;
import jp.co.ntt.lms.xms.framework.XmsRequest;
import jp.co.ntt.lms.xms.framework.XmsSystemException;
import jp.co.ntt.lms.xms.framework.XmsWarningException;

//ユーザーエージェント判定機能
import jp.co.ntt.lms.imode.common.UserAgentCheck;

/**
 * 携帯ＳＣＯＲＭエントリ
 * 
 * @author ntc-sakai
 *
 */
public class MobSCORMEntry extends HttpServlet {
	/**
	 * GET形式リクエスト処理メソッド。<br>
	 * 
	 * @param request HTTPリクエスト。
	 * @param response HTTPレスポンス。
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		this.doRequest(request, response);
	}

	/**
	 * POST形式リクエスト処理メソッド。
	 * 
	 * @param request HTTPリクエスト。
	 * @param response HTTPレスポンス。
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		this.doRequest(request, response);
	}

	/**
	 * リクエスト処理メソッド。<br>
	 * GET/POST共通で呼び出される。<br>
	 * <ol>
	 * <li>ページSEQチェック処理を行ないます。</li>
	 * <li>ページSEQチェック結果が正常の場合、<br>
	 * <ul>
	 * <li>後処理スクリプト処理を行ないます。</li>
	 * <li>前処理スクリプト処理を行ないます。</li>
	 * </ul>
	 * <li>ページSEQチェック結果がエラーの場合、<br>
	 * <ul>
	 * <li>エラー画面を表示します。</li>
	 * </ul>
	 * </li>
	 * </ol>
	 * 
	 * @param request  HTTPリクエスト
	 * @param response HTTPレスポンス
	 */
	protected void doRequest(HttpServletRequest request,
			HttpServletResponse response) {
		XmsRequest xmsRequest = null;

		response.setContentType("text/html; charset=shift_jis");
		//20070707 ADD Start ntc higuchi キャッシュを無効にする処理を追加
		response.setHeader("Expires", "Sat, 01 Jan 2005 01:00:00 GMT");
		response.setHeader("Pragma", "no-cache");
		response.setHeader("Cache-Control", "no-cache");
		//20070707 ADD End

		try {
			request.setCharacterEncoding("shift_jis");
		} catch (UnsupportedEncodingException e1) {
		}
		try {
			
			// リクエスト・レスポンスオブジェクトの生成
			xmsRequest = new XmsRequest(request, response);

			// 入力パラメータの頁ＳＥＱ取得
			String inPageSeq = xmsRequest.getParameter("page_seq");
			
			// 頁ＳＥＱ有無チェック
			if (MobileUtl.isEmpty(inPageSeq)) {
				throw new XmsSystemException(
						"parameter not found Error(page_seq)");
			}

			// セッションからカレント頁SEQ取得
			HttpSession session = xmsRequest.getRequest().getSession();
			PageSequence pageSeq = (PageSequence) session.getAttribute(MobConst.S_PAGE_SEQ);

			if (pageSeq == null) {
				// セッションタイムアウトエラー
				throw new XmsWarningException("SessionTimeout");
			}

			// 頁ＳＥＱチェック
			if (!pageSeq.isCheck(inPageSeq)) {
				// SEQエラー時は、エラー画面表示へ遷移
				throw new XmsWarningException("PageSequenceError");
			}

			// 頁ＳＥＱ管理番号＋１
			pageSeq.next();

			// セッションから携帯ＳＣＯＲＭＢｅａｎクラス取得
			MobSCORMBean scormBean = (MobSCORMBean) session.getAttribute(MobConst.S_SCORM_BEAN);
			
			if (scormBean == null) {
				// セッションタイムアウトエラー
				throw new XmsWarningException("SessionTimeout");
			}

			// HttpServletRequest設定
			scormBean.setReq(request);

			// 前処理スクリプトＵＲＬクリア
			scormBean.setDispUrl("");

			// 後処理スクリプトＵＲＬ取得
			String postUrl = scormBean.getPostUrlPath();

			// 後処理スクリプトＵＲＬ未設定？
			if (postUrl == null || postUrl.equals("")) {
				// 入力パラメータの後処理スクリプト取得
				postUrl = xmsRequest.getParameter("post_url");
				// 後処理スクリプトＵＲＬファイル名を設定
				scormBean.setPostUrl(postUrl);
				// 後処理スクリプトＵＲＬ（Path付)取得
				postUrl =  scormBean.getPostUrlPath();

				// 入力パラメータ後処理スクリプト未設定？
				if (postUrl == null || postUrl.equals("")) {
					// デフォルト後処理スクリプトＵＲＬ設定
					postUrl = MobConst.C_DEFAULT_POSTURL;
					// 後処理スクリプトＵＲＬファイル名を設定
					scormBean.setPostUrl(postUrl);
				}
			}
			// 後処理スクリプトファイル有無
			if (!scormBean.isPostUrl()) {
				// 後処理スクリプトファイルが存在しない
				DebugLog.write(getClass(), "[MobSCORMEntry] PostUrl not found(" + postUrl + ")", DebugLog.HIGHT);
				throw new XmsSystemException("PostUrl not found error");
			}
			// 後処理スクリプトインクルード処理実行
			PostUrlInclude(xmsRequest, postUrl);

			// 後処理スクリプトＵＲＬクリア
			scormBean.setPostUrl("");

			// 学習状態終了？
			if (scormBean.isEndlearn()) {
				// 後処理スクリプト内で学習終了又は中断のナビゲーション要求が
				// 行なわれた場合、戻り先ＵＲＬへリダイレクトする。
				endlearn(xmsRequest);
			} else {
				// 後処理スクリプトでナビゲーション要求した場合、ナビゲーション状態をイニシャライズする
				scormBean.NaviInitialize();
				// 学習終了以外の場合、前処理スクリプトＵＲＬへフォワードする。
				// 前処理スクリプトＵＲＬ取得
				String dispUrl = scormBean.getDispUrlPath();
				if (dispUrl == null || dispUrl.equals("")) {
					// 後処理スクリプト内でエラー
					DebugLog.write(getClass(), "Postprocess Error PostUrl = [" + postUrl + "]", DebugLog.HIGHT);
				} else {
					// 後処理スクリプト正常終了時
					if (!scormBean.isDispUrl()) {
						// 前処理スクリプトファイルが存在しない
						DebugLog.write(getClass(), "[MobSCORMEntry] DispUrl not found(" + dispUrl + ")", DebugLog.HIGHT);
						throw new XmsSystemException("PostUrl not found error");
					}
					String forwardUrl = dispUrl;
					// フォワード先ＵＲＬ拡張子判定
					if (dispUrl.toLowerCase().endsWith(".htm") ||
						dispUrl.toLowerCase().endsWith(".html")) {
						// ｈｔｍｌファイルの場合、ＨＴＭＬ共通表示処理へフォワードする。
						// ForWardUrlにＨＴＭＬ共通表示処理Urlを設定
						dispUrl = MobConst.C_COM_HTML_PATH;
						// 前処理スクリプトファイル名設定
						xmsRequest.getRequest().setAttribute("MOBILE.DISP.URL", forwardUrl);
					}

					// フォワード処理
					forward(xmsRequest, dispUrl);
				}

			}
		} catch (XmsSystemException e) {
			// システムエラー画面へ
			terminateWithSystemException(xmsRequest, e);
		} catch (XmsWarningException e) {
			// ワーニングエラー画面へ
			terminateWithWarningException(xmsRequest, e);
		} catch (Exception e) {
			// その他エラー画面へ
			terminateWithThrowable(xmsRequest, e);
		}

		
	}

	/**
	 * 後処理スクリプトインクルード処理
	 * 
	 * @param xmsRequest
	 * @param postUrl
	 * @throws XmsSystemException
	 */
	private void PostUrlInclude(XmsRequest xmsRequest, String postUrl)
		throws XmsSystemException {
		RequestDispatcher dispatcher = null;
		HttpServletRequest request = null;
		HttpServletResponse response = null;

		try {
			request = xmsRequest.getRequest();
			response = xmsRequest.getResponse();
			dispatcher = request.getRequestDispatcher(postUrl);
			dispatcher.include(request, response);
		} catch (Exception e) {
			// 後処理スクリプトincludeエラー
			DebugLog.write(getClass(),"[PostUrlInclude] RequestDispatcher(include) error postUrl = [" + postUrl + "]", DebugLog.HIGHT);
			throw new XmsSystemException(e);
		}

	}

	/**
	 * 学習終了処理。<br>
	 * <br>
	 * ユーザーエージェント判定処理<br>
	 * 学習終了時の遷移先を決定します。<br>
	 * <ol>
	 * <li>ユーザーエージェントが携帯の場合、<br>
	 * <ul>
	 * <li>戻り先URLへリダイレクトします。</li>
	 * </ul>
	 * <li>ユーザーエージェントが携帯以外の場合、<br>
	 * <ul>
	 * <li>ウインドウを閉じます。</li>
	 * </ul>
	 * </li>
	 * </ol>
	 * 
	 * @param xmsRequest リクエスト
	 * @throws XmsSystemException
	 * @throws XmsWarningException
	 */
	private void endlearn(XmsRequest xmsRequest)
		throws XmsSystemException, XmsWarningException {
		// セッションから戻り先URL取得
		HttpSession session = xmsRequest.getRequest().getSession();
		String returnURL = (String) session.getAttribute(MobConst.S_RETURN_URL);

		HttpServletRequest request = xmsRequest.getRequest();
		UserAgentCheck userCarrier = new UserAgentCheck(request);
				
		// ユーザーエージェント判定 
		if (userCarrier.getMobileCarrier() == UserAgentCheck.PC) {
			// PC windowclose処理
			returnURL = MobConst.C_WINDOWCLOSE_URI;
		} else {
			// NULL判定
			if (returnURL == null || returnURL.equals("")) {
				// TimeOut エラー
				DebugLog.write(getClass(),"[endlearn] session is null "
						+ "MOBILE.RETURN_URL" , DebugLog.HIGHT);
				throw new XmsWarningException("SessionTimeout");
			}
		}

		// セッション削除
		session.removeAttribute(MobConst.S_PAGE_SEQ);
		session.removeAttribute(MobConst.S_RETURN_URL);
		session.removeAttribute(MobConst.S_SCORM_BEAN);

		// レスポンス取得
		HttpServletResponse response = xmsRequest.getResponse();
		try {
			// 戻り先ＵＲＬへリダイレクト
			response.sendRedirect(returnURL);
			
		} catch (IOException e) {
			// ＬＯＧ出力
			DebugLog.write(getClass(), "[endlearn]sendRedirect Error returnURL = "
					+ returnURL, DebugLog.HIGHT);
			throw new XmsSystemException("sendRedirect error");
		}

	}

	/**
	 * 警告エラー画面を表示します。
	 * 
	 * @param xmsRequest リクエスト
	 * @param exception 警告例外
	 */
	private void terminateWithWarningException(XmsRequest xmsRequest,
			XmsWarningException exception) {
		try {
			String uri = null;

			if (exception.getKey() != null &&
				exception.getKey().equals("SessionTimeout")) {
				// Timeoutエラー
				uri = MobConst.C_TIMEOUT_URI;
			} else if (exception.getKey() != null &&
						exception.getKey().equals("PageSequenceError")) {
				// 頁SEQエラー
				uri = MobConst.C_SEQERR_URI;
			} else {
				// その他警告エラー
				uri = MobConst.C_WARN_ERR_URI;
			}

			forward(xmsRequest, uri);
		} catch (XmsException e) {
			terminateWithThrowable(xmsRequest, exception);
		}

	}

	/**
	 * システムエラー画面を表示します。
	 * 
	 * @param xmsRequest リクエスト
	 * @param exception システム例外
	 */
	private void terminateWithSystemException(XmsRequest xmsRequest,
			XmsSystemException exception) {
		try {
			DebugLog.write(getClass(), exception, DebugLog.HIGHT);
			forward(xmsRequest, MobConst.C_SYS_ERR_URI);
		} catch (XmsException e) {
			terminateWithThrowable(xmsRequest, exception);
		}

	}

	/**
	 * その他エラー画面を表示します。
	 * 
	 * @param xmsRequest リクエスト
	 * @param th Throwable その他例外
	 */
	private void terminateWithThrowable(XmsRequest xmsRequest, Throwable th) {
		try {
			forward(xmsRequest, MobConst.C_THROW_ERR_URI);
		} catch (XmsException e) {
			DebugLog.write(getClass(), e, DebugLog.HIGHT);
		}

	}

	/**
	 * 移動先URLへフォワードします。
	 * 
	 * @param xmsRequest リクエスト
	 * @param uri 移動先URL
	 * @throws XmsException
	 */
	private void forward(XmsRequest xmsRequest, String uri)
		throws XmsException {
		// HTTP リクエスト
		HttpServletRequest request = null;
		// HTTPレスポンス
		HttpServletResponse response = null;
		RequestDispatcher dispatcher = null;

		try {
			request = xmsRequest.getRequest();
			response = xmsRequest.getResponse();
			dispatcher = request.getRequestDispatcher(uri);
			dispatcher.forward(request, response);
		} catch (Exception e) {
			throw new XmsSystemException(e);
		}
	}

}
