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

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
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.cayenne.om.account.AvzMGroupsend;
import com.aimluck.eip.cayenne.om.portlet.AvzTScheduleAcl;
import com.aimluck.eip.cayenne.om.security.TurbineUser;
import com.aimluck.eip.common.ALAbstractFormData;
import com.aimluck.eip.common.ALDBErrorException;
import com.aimluck.eip.common.ALEipConstants;
import com.aimluck.eip.common.ALEipGroupSend;
import com.aimluck.eip.common.ALEipPost;
import com.aimluck.eip.common.ALEipUser;
import com.aimluck.eip.common.ALPageNotFoundException;
import com.aimluck.eip.modules.actions.common.ALAction;
import com.aimluck.eip.orm.Database;
import com.aimluck.eip.orm.query.SQLTemplate;
import com.aimluck.eip.orm.query.SelectQuery;
import com.aimluck.eip.util.ALEipUtils;

/**
 * スケジュール公開・秘書設定のファイルフォームデータを管理するクラス <BR>
 * 
 */
public class ScheduleAuthorityFormData extends ALAbstractFormData {

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

  /** <code>loginuserid</code> ログインユーザーID */
  private int loginuserid;

  /** 秘書設定プルダウンの初期値選択用のグループ送信ID */
  private static String init_groupsend_id;

  /** 秘書設定メンバーリスト */
  private List<ALEipUser> secretaryMemberList;

  /** 公開設定メンバーリスト */
  private List<ALEipUser> publicMemberList;

  /** 公開設定グループ送信リスト */
  private List<ALEipGroupSend> publicGroupSendList;

  /** 秘書設定プルダウンの初期値取得用の定義 */
  private static String INIT_GROUPSEND_NAME = "全秘書";

  /**
   * 初期処理
   * 
   * @param action
   *            アクションクラス
   * @param rundata
   *            JetSpeedランデータ
   * @param context
   *            JetSpeedコンテキスト
   * @see com.aimluck.eip.common.ALAbstractFormData#init(com.aimluck.eip.modules.actions.common.ALAction,
   *      org.apache.turbine.util.RunData, org.apache.velocity.context.Context)
   */
  @Override
  public void init(ALAction action, RunData rundata, Context context)
      throws ALPageNotFoundException, ALDBErrorException {
    super.init(action, rundata, context);

    loginuserid = ALEipUtils.getUserId(rundata);

  }

  /**
   * 各フィールドを初期化します。 <BR>
   * 
   * @see com.aimluck.eip.common.ALData#initField()
   */
  public void initField() {
    secretaryMemberList = new ArrayList<ALEipUser>();
    publicMemberList = new ArrayList<ALEipUser>();
    publicGroupSendList = new ArrayList<ALEipGroupSend>();
  }

  /**
   * 設定画面初期表示処理、登録処理時のリクエストパラメータ取得を行なう。
   * 
   * @param rundata
   *            JetSpeedランデータ
   * @param context
   *            JetSpeedコンテキスト
   * @param msgList
   *            エラーメッセージリスト
   * @return 処理結果(正常：true、異常:false)
   * @see com.aimluck.eip.common.ALAbstractFormData#setFormData(org.apache.turbine
   *      .util.RunData, org.apache.velocity.context.Context,
   *      java.util.ArrayList)
   */
  @Override
  protected boolean setFormData(RunData rundata, Context context,
      List<String> msgList) throws ALPageNotFoundException, ALDBErrorException {

    boolean res = super.setFormData(rundata, context, msgList);

    if (res) {
      if (ALEipConstants.MODE_NEW_FORM.equals(getMode())) {
        // 設定画面表示時
        try {

          // 公開グループ
          final String publicGroupSendSql =
            "SELECT DISTINCT "
              + "  B.GROUPSEND_ID, B.GROUPSEND_NAME, C.POSITION "
              + " FROM avz_t_schedule_acl as A "
              + " INNER JOIN avz_m_groupsend as B "
              + "  on A.TARGET_ID = B.GROUPSEND_ID "
              + " INNER JOIN avz_m_groupsend_position as C "
              + " on B.GROUPSEND_ID = C.GROUPSEND_ID "
              + " WHERE A.USER_ID = #bind($userId 'INTEGER') "
              + "   AND A.TARGET_TYPE = 'G' "
              + "   AND A.ACL_TYPE = 'R' "
              + " ORDER BY C.POSITION ";

          SQLTemplate<AvzMGroupsend> query =
            new SQLTemplate<AvzMGroupsend>(
              AvzMGroupsend.class,
              publicGroupSendSql);

          List<AvzMGroupsend> groupSendList =
            query.param("userId", loginuserid).fetchList();
          if (groupSendList != null && groupSendList.size() > 0) {
            for (AvzMGroupsend e : groupSendList) {
              ALEipGroupSend gs = new ALEipGroupSend();
              gs.initField();
              gs.setGroupSendId(e.getGroupsendId());
              gs.setGroupSendName(e.getGroupsendName());
              publicGroupSendList.add(gs);
            }
          }

          // 公開先メンバー
          final String memberSql =
            "SELECT DISTINCT "
              + "  B.USER_ID, B.LOGIN_NAME, B.FIRST_NAME, B.LAST_NAME, B.DISPLAY_NAME, C.POSITION "
              + " FROM avz_t_schedule_acl as A "
              + " INNER JOIN turbine_user as B "
              + "  on A.TARGET_ID = B.USER_ID "
              + " INNER JOIN eip_m_user_position as C "
              + " on B.USER_ID = C.USER_ID "
              + " WHERE A.USER_ID = #bind($userId 'INTEGER') "
              + "   AND A.TARGET_TYPE = #bind($targetType 'VARCHAR') "
              + "   AND A.ACL_TYPE = #bind($aclType 'VARCHAR') "
              + " ORDER BY B.DISPLAY_NAME, C.POSITION ";

          SQLTemplate<TurbineUser> publicMemberQuery =
            new SQLTemplate<TurbineUser>(TurbineUser.class, memberSql);

          List<TurbineUser> turbineUserList =
            publicMemberQuery.param("userId", loginuserid).param(
              "targetType",
              ScheduleConst.SCHEDULEACL_TARGET_USER).param(
              "aclType",
              ScheduleConst.SCHEDULEACL_ACL_REF).fetchList();
          if (turbineUserList != null && turbineUserList.size() > 0) {
            for (TurbineUser e : turbineUserList) {
              ALEipUser u = new ALEipUser();
              u.initField();
              u.setUserId(e.getUserId());
              u.setName(e.getLoginName());
              u.setAliasName(e.getFirstName(), e.getLastName());
              publicMemberList.add(u);
            }
          }

          // 秘書設定メンバー
          SQLTemplate<TurbineUser> secretaryMemberQuery =
            new SQLTemplate<TurbineUser>(TurbineUser.class, memberSql);

          List<TurbineUser> turbineSecretaryUserList =
            secretaryMemberQuery.param("userId", loginuserid).param(
              "targetType",
              ScheduleConst.SCHEDULEACL_TARGET_USER).param(
              "aclType",
              ScheduleConst.SCHEDULEACL_ACL_UPDATE).fetchList();
          if (turbineSecretaryUserList != null
            && turbineSecretaryUserList.size() > 0) {
            for (TurbineUser e : turbineSecretaryUserList) {
              ALEipUser u = new ALEipUser();
              u.initField();
              u.setUserId(e.getUserId());
              u.setName(e.getLoginName());
              u.setAliasName(e.getFirstName(), e.getLastName());
              secretaryMemberList.add(u);
            }
          }

          // 秘書設定プルダウンの初期値（”全秘書”）のグループ送信IDを取得
          // AvzMGroupsend gs =
          // Database.get(
          // AvzMGroupsend.class,
          // AvzMGroupsend.GROUPSEND_NAME_COLUMN,
          // INIT_GROUPSEND_NAME);
          SelectQuery<AvzMGroupsend> queryAvzMGroupsend =
            Database.query(AvzMGroupsend.class);
          Expression exp =
            ExpressionFactory.matchExp(
              AvzMGroupsend.GROUPSEND_NAME_PROPERTY,
              INIT_GROUPSEND_NAME);
          queryAvzMGroupsend.setQualifier(exp);
          AvzMGroupsend gs = queryAvzMGroupsend.fetchSingle();
          if (gs != null) {
            init_groupsend_id = gs.getGroupsendId().toString();
          }

        } catch (Exception e) {
          String msg =
            "スケジュール公開・秘書設定画面の表示に失敗しました。["
              + ALEipUtils.getBaseUser(loginuserid).getUserName()
              + "]";
          logger.error(msg, e);
          throw new ALDBErrorException();
        }
      } else if (ALEipConstants.MODE_INSERT.equals(getMode())) {
        // /////////////////////////////////////////////
        // 登録処理
        // /////////////////////////////////////////////

        try {
          // 秘書設定ユーザー情報リストを取得する。
          String[] secretary_member_ids =
            rundata.getParameters().getStrings("secretary_member_to");
          if (secretary_member_ids != null && secretary_member_ids.length != 0) {
            SelectQuery<TurbineUser> query = Database.query(TurbineUser.class);
            Expression exp =
              ExpressionFactory.inExp(
                TurbineUser.LOGIN_NAME_PROPERTY,
                secretary_member_ids);
            query.setQualifier(exp);
            List<ALEipUser> tmp = ALEipUtils.getUsersFromSelectQuery(query);
            for (ALEipUser u : tmp) {
              secretaryMemberList.add(u);
            }
          }

          // 公開設定ユーザー情報リストを取得する。
          String[] public_member_ids =
            rundata.getParameters().getStrings("public_member_to");
          if (public_member_ids != null && public_member_ids.length != 0) {
            SelectQuery<TurbineUser> query = Database.query(TurbineUser.class);
            Expression exp =
              ExpressionFactory.inExp(
                TurbineUser.LOGIN_NAME_PROPERTY,
                public_member_ids);
            query.setQualifier(exp);
            List<ALEipUser> tmp = ALEipUtils.getUsersFromSelectQuery(query);
            for (ALEipUser u : tmp) {
              publicMemberList.add(u);
            }
          }

          // 公開設定グループ送信リストを取得する。
          String[] groupsend_ids =
            rundata.getParameters().getStrings("groupsend_to");
          if (groupsend_ids != null && groupsend_ids.length != 0) {

            for (String id : groupsend_ids) {
              ALEipGroupSend tmp =
                ALEipUtils.getGroupSend(Integer.parseInt(id));
              publicGroupSendList.add(tmp);
            }
          }
        } catch (Exception e) {
          String msg =
            "スケジュール公開・秘書設定の更新に失敗しました。["
              + ALEipUtils.getBaseUser(loginuserid).getUserName()
              + "]";
          logger.error(msg, e);
          msgList.add(msg);
        }
      }
    }

    return res;
  }

  /**
   * ※未使用
   */
  @Override
  protected void setValidator() {
  }

  /**
   * ※未使用
   */
  @Override
  protected boolean validate(List<String> msgList) {
    return (msgList.size() == 0);
  }

  /**
   * ※未使用
   */
  @Override
  protected boolean loadFormData(RunData rundata, Context context,
      List<String> msgList) {
    return true;
  }

  /**
   * ※未使用
   */
  @Override
  protected boolean deleteFormData(RunData rundata, Context context,
      List<String> msgList) {
    return true;
  }

  /**
   * 公開先と秘書設定先を上書き登録する。 <BR>
   * 
   * @param rundata
   * @param context
   * @param msgList
   * @return TRUE 成功 FALSE 失敗
   * @see com.aimluck.eip.common.ALAbstractFormData#insertFormData(org.apache.turbine.util.RunData,
   *      org.apache.velocity.context.Context, java.util.ArrayList)
   */
  @Override
  protected boolean insertFormData(RunData rundata, Context context,
      List<String> msgList) {
    try {
      Date now = Calendar.getInstance().getTime();

      // スケジュール制御を一旦削除する。
      String deleteAvzTScheduleAclSql =
        "DELETE FROM AVZ_T_SCHEDULE_ACL WHERE USER_ID = #bind($userId 'INTEGER')";
      Database.sql(AvzTScheduleAcl.class, deleteAvzTScheduleAclSql).param(
        "userId",
        loginuserid).execute();

      // 公開グループを設定する。
      for (ALEipGroupSend gs : publicGroupSendList) {
        AvzTScheduleAcl acl = Database.create(AvzTScheduleAcl.class);
        acl.setUserId(loginuserid);
        acl.setAclType(ScheduleConst.SCHEDULEACL_ACL_REF);
        acl.setTargetType(ScheduleConst.SCHEDULEACL_TARGET_GROUP);
        acl.setTargetId((int) gs.getGroupSendId().getValue());
        acl.setCreateDate(now);
        acl.setUpdateDate(now);
      }

      // 公開ユーザーを設定する。
      for (ALEipUser u : publicMemberList) {
        AvzTScheduleAcl acl = Database.create(AvzTScheduleAcl.class);
        acl.setUserId(loginuserid);
        acl.setAclType(ScheduleConst.SCHEDULEACL_ACL_REF);
        acl.setTargetType(ScheduleConst.SCHEDULEACL_TARGET_USER);
        acl.setTargetId((int) u.getUserId().getValue());
        acl.setCreateDate(now);
        acl.setUpdateDate(now);
      }

      // 秘書設定ユーザーを設定する。
      for (ALEipUser u : secretaryMemberList) {
        AvzTScheduleAcl acl = Database.create(AvzTScheduleAcl.class);
        acl.setUserId(loginuserid);
        acl.setAclType(ScheduleConst.SCHEDULEACL_ACL_UPDATE);
        acl.setTargetType(ScheduleConst.SCHEDULEACL_TARGET_USER);
        acl.setTargetId((int) u.getUserId().getValue());
        acl.setCreateDate(now);
        acl.setUpdateDate(now);
      }

      Database.commit();

      // System.out.println(ALEipUtils.getBaseUser(loginuserid).getName());

    } catch (Exception ex) {
      Database.rollback();
      String msg =
        "スケジュール公開・秘書設定の更新に失敗しました。["
          + ALEipUtils.getBaseUser(loginuserid).getUserName()
          + "]";
      logger.error(msg, ex);
      msgList.add(msg);
      return false;
    }
    return true;
  }

  /**
   * ※未使用
   */
  @Override
  protected boolean updateFormData(RunData rundata, Context context,
      List<String> msgList) {
    return true;
  }

  /**
   * ※未使用
   */
  @Override
  public String getAclPortletFeature() {
    return null;
  }

  /**
   * 部署1リストを取得する。
   * 
   * @return
   */
  public List<ALEipPost> getPostMap() {
    return ALEipUtils.getPostMap();
  }

  /**
   * 秘書設定メンバーリストを取得します。
   * 
   * @return
   */
  public List<ALEipUser> getSecretaryMemberList() {
    return secretaryMemberList;
  }

  /**
   * 公開設定メンバーリストを取得します。
   * 
   * @return
   */
  public List<ALEipUser> getPublicMemberList() {
    return publicMemberList;
  }

  /**
   * 公開設定グループ送信を取得します。
   * 
   * @return
   */
  public List<ALEipGroupSend> getPublicGroupSendList() {
    return publicGroupSendList;
  }

  /**
   * グループ送信プルダウンの初期値を取得する。
   * 
   * @return グループ送信プルダウンの初期値（”全秘書”）
   */
  public static String getInitGroupsendId() {
    return init_groupsend_id;
  }

}
