/*
 * Aipo is a groupware program developed by Aimluck,Inc.
 * http://aipostyle.com/
 *
 * Copyright(C) 2011 avanza Co.,Ltd. All rights reserved.
 * http://www.avnz.co.jp/
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

package com.aimluck.eip.common;

import java.util.ArrayList;
import java.util.List;

import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;

import com.aimluck.eip.modules.actions.common.ALAction;
import com.aimluck.eip.services.accessctl.ALAccessControlConstants;
import com.aimluck.eip.util.ALEipUtils;

// 運用課題No.68
/**
 * 別ウインドウ表示フォーム用抽象クラス
 */
public abstract class ALAbstractFormWindow extends ALAbstractFormData {

  /** logger */
  private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(ALAbstractFormWindow.class.getName());

  // ログ用例外メッセージ
  /** ログ用例外メッセージ：権限エラー */
  public static final String LOG_EX_MSG_PERMISSION = "アクセス権限例外が発生しました。ログインユーザー:";

  /** ログ用例外メッセージ：ページエラー */
  public static final String LOG_EX_MSG_PAGE = "ページ例外が発生しました。ログインユーザー:";

  /** ログ用例外メッセージ：DBエラー */
  public static final String LOG_EX_MSG_DB = "DB例外が発生しました。ログインユーザー:";

  // JSONScreen用例外発生時のエラーメッセージ
  /** JSONScreen用例外メッセージ：セッションエラー */
  public static final String JSON_EX_MSG_SESSION = "セッションがタイムアウトしました。当ウインドウを閉じて操作をやり直してください。";

  /** JSONScreen用例外メッセージ：権限エラー */
  public static final String JSON_EX_MSG_PERMISSION = "アクセス権限がないため、処理を実行できません。当ウインドウを閉じて操作をやり直してください。";

  /** JSONScreen用例外メッセージ：ページエラー */
  public static final String JSON_EX_MSG_PAGE = "処理中のデータが削除されたか、データの取得に失敗しました。当ウインドウを閉じて操作をやり直してください。";

  /** JSONScreen用例外メッセージ：DBエラー */
  public static final String JSON_EX_MSG_DB = "データベース処理中にエラーが発生しました。当ウインドウを閉じて操作をやり直してください。";

  /**
   * データを新規登録します。
   * 
   * @param action
   *          呼び出し元Action
   * @param rundata
   *          実行データ
   * @param context
   *          Velocityコンテキスト
   * @return 正常終了の場合true、エラーの場合false
   */
  @Override
  public boolean doInsert(ALAction action, RunData rundata, Context context) {
    try {
      List<String> msgList = new ArrayList<String>();
      if (!doCheckSecurity(rundata, context)) {
        setErrorMessageForJSONScreen(context, JSON_EX_MSG_SESSION);
        return false;
      }

      init(action, rundata, context);

      doCheckAclPermission(rundata, context, ALAccessControlConstants.VALUE_ACL_INSERT);

      action.setMode(ALEipConstants.MODE_INSERT);
      setMode(action.getMode());
      rundata.getParameters().add(ALEipConstants.MODE, ALEipConstants.MODE_INSERT);
      setValidator();
      boolean res = (setFormData(rundata, context, msgList) && validate(msgList) && insertFormData(rundata, context, msgList));
      if (!res) {
        action.setMode(ALEipConstants.MODE_NEW_FORM);
        setMode(action.getMode());
      }
      action.setResultData(this);

      if (!msgList.isEmpty()) {
        action.addErrorMessages(msgList);
      }
      action.putData(rundata, context);

      return res;
    } catch (ALPermissionException e) {
      // 例外発生時、JSONScreen用にエラーメッセージを設定する
      logger.error(LOG_EX_MSG_PERMISSION + ALEipUtils.getUserId(rundata), e);
      setErrorMessageForJSONScreen(context, JSON_EX_MSG_PERMISSION);
      return false;
    } catch (ALPageNotFoundException e) {
      // 例外発生時、JSONScreen用にエラーメッセージを設定する
      logger.error(LOG_EX_MSG_PAGE + ALEipUtils.getUserId(rundata), e);
      setErrorMessageForJSONScreen(context, JSON_EX_MSG_PAGE);
      return false;
    } catch (ALDBErrorException e) {
      // 例外発生時、JSONScreen用にエラーメッセージを設定する
      logger.error(LOG_EX_MSG_DB + ALEipUtils.getUserId(rundata), e);
      setErrorMessageForJSONScreen(context, JSON_EX_MSG_DB);
      return false;
    }
  }

  /**
   * データを更新します。
   * 
   * @param action
   *          呼び出し元Action
   * @param rundata
   *          実行データ
   * @param context
   *          Velocityコンテキスト
   * @return 正常終了の場合true、エラーの場合false
   */
  @Override
  public boolean doUpdate(ALAction action, RunData rundata, Context context) {
    try {
      List<String> msgList = new ArrayList<String>();
      if (!doCheckSecurity(rundata, context)) {
        setErrorMessageForJSONScreen(context, JSON_EX_MSG_SESSION);
        return false;
      }

      init(action, rundata, context);

      doCheckAclPermission(rundata, context, ALAccessControlConstants.VALUE_ACL_UPDATE);

      action.setMode(ALEipConstants.MODE_UPDATE);
      setMode(action.getMode());
      rundata.getParameters().add(ALEipConstants.MODE, ALEipConstants.MODE_UPDATE);
      setValidator();
      boolean res = (setFormData(rundata, context, msgList) && validate(msgList) && updateFormData(rundata, context, msgList));
      if (!res) {
        action.setMode(ALEipConstants.MODE_EDIT_FORM);
        setMode(action.getMode());
      }
      action.setResultData(this);
      if (!msgList.isEmpty()) {
        action.addErrorMessages(msgList);
      }
      action.putData(rundata, context);

      return res;
    } catch (ALPermissionException e) {
      // 例外発生時、JSONScreen用にエラーメッセージを設定する
      logger.error(LOG_EX_MSG_PERMISSION + ALEipUtils.getUserId(rundata), e);
      setErrorMessageForJSONScreen(context, JSON_EX_MSG_PERMISSION);
      return false;
    } catch (ALPageNotFoundException e) {
      // 例外発生時、JSONScreen用にエラーメッセージを設定する
      logger.error(LOG_EX_MSG_PAGE + ALEipUtils.getUserId(rundata), e);
      setErrorMessageForJSONScreen(context, JSON_EX_MSG_PAGE);
      return false;
    } catch (ALDBErrorException e) {
      // 例外発生時、JSONScreen用にエラーメッセージを設定する
      logger.error(LOG_EX_MSG_DB + ALEipUtils.getUserId(rundata), e);
      setErrorMessageForJSONScreen(context, JSON_EX_MSG_DB);
      return false;
    }
  }

  /**
   * データを削除します。
   * 
   * @param action
   *          呼び出し元Action
   * @param rundata
   *          実行データ
   * @param context
   *          Velocityコンテキスト
   * @return 正常終了の場合true、エラーの場合false
   */
  @Override
  public boolean doDelete(ALAction action, RunData rundata, Context context) {

    try {

      List<String> msgList = new ArrayList<String>();
      if (!doCheckSecurity(rundata, context)) {
        setErrorMessageForJSONScreen(context, JSON_EX_MSG_SESSION);
        return false;
      }

      init(action, rundata, context);

      doCheckAclPermission(rundata, context, ALAccessControlConstants.VALUE_ACL_DELETE);

      action.setMode(ALEipConstants.MODE_DELETE);
      setMode(action.getMode());
      rundata.getParameters().add(ALEipConstants.MODE, ALEipConstants.MODE_DELETE);
      boolean res = deleteFormData(rundata, context, msgList);
      action.setResultData(this);
      if (!msgList.isEmpty()) {
        action.addErrorMessages(msgList);
      }
      action.putData(rundata, context);
      return res;
    } catch (ALPermissionException e) {
      // 例外発生時、JSONScreen用にエラーメッセージを設定する
      logger.error(LOG_EX_MSG_PERMISSION + ALEipUtils.getUserId(rundata), e);
      setErrorMessageForJSONScreen(context, JSON_EX_MSG_PERMISSION);
      return false;
    } catch (ALPageNotFoundException e) {
      // 例外発生時、JSONScreen用にエラーメッセージを設定する
      logger.error(LOG_EX_MSG_PAGE + ALEipUtils.getUserId(rundata), e);
      setErrorMessageForJSONScreen(context, JSON_EX_MSG_PAGE);
      return false;
    } catch (ALDBErrorException e) {
      // 例外発生時、JSONScreen用にエラーメッセージを設定する
      logger.error(LOG_EX_MSG_DB + ALEipUtils.getUserId(rundata), e);
      setErrorMessageForJSONScreen(context, JSON_EX_MSG_DB);
      return false;
    }
  }

  /**
   * JSONScreeen実行時エラーのエラーメッセージをコンテキストに設定します。
   * 
   * @param context
   *          Velocityコンテキスト
   * @param msg
   *          エラーメッセージ
   */
  private void setErrorMessageForJSONScreen(Context context, String msg) {
    List<String> errMsgList = new ArrayList<String>(0);
    errMsgList.add(msg);
    context.put(ALEipConstants.ERROR_MESSAGE_LIST, errMsgList);
  }
}
