/*
 * Aipo is a groupware program developed by Aimluck,Inc.
 * Copyright (C) 2004-2011 Aimluck,Inc.
 * http://www.aipo.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.aimluck.eip.modules.actions.schedule;

import java.net.URLEncoder;
import java.text.SimpleDateFormat;
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.portal.portlets.VelocityPortlet;
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.portlet.AvzTScheduleAcl;
import com.aimluck.eip.cayenne.om.security.TurbineUser;
import com.aimluck.eip.common.ALDBErrorException;
import com.aimluck.eip.common.ALEipConstants;
import com.aimluck.eip.common.ALEipUser;
import com.aimluck.eip.modules.actions.common.ALBaseAction;
import com.aimluck.eip.orm.Database;
import com.aimluck.eip.orm.query.SelectQuery;
import com.aimluck.eip.schedule.ScheduleConst;
import com.aimluck.eip.schedule.beans.ScheduleLocationUserBean;
import com.aimluck.eip.schedule.util.ScheduleUtils;
import com.aimluck.eip.services.orgutils.ALOrgUtilsService;
import com.aimluck.eip.user.beans.UserGroupPositionLiteBean;
import com.aimluck.eip.user.util.UserUtils;
import com.aimluck.eip.userfacility.beans.UserFacilityLiteBean;
import com.aimluck.eip.userfacility.util.UserFacilityUtils;
import com.aimluck.eip.util.ALCommonUtils;
import com.aimluck.eip.util.ALEipUtils;

/**
 * カレンダーのアクションクラスです。
 * 
 */
public class AjaxScheduleAction extends ALBaseAction {

  /** <code>logger</code> logger */
  private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(AjaxScheduleAction.class.getName());

  private boolean isMax = false;

  // add start
  /** <code>loginUserName</code> ログインユーザー名 */
  private String loginUserName;

  // add end
  /**
   * 
   * @param portlet
   * @param context
   * @param rundata
   */
  @Override
  protected void buildNormalContext(VelocityPortlet portlet, Context context, RunData rundata) {

    // セッション情報をクリアする
    clearAjaxScheduleSession(rundata, context);

    String tab;

    try {
      context.put("theme", ALOrgUtilsService.getTheme());

      // 表示開始時間を取得する．
      String time_start = portlet.getPortletConfig().getInitParameter("p1a-rows");
      context.put("time_start", time_start);

      // 表示終了時間を取得する．
      String time_end = portlet.getPortletConfig().getInitParameter("p1b-rows");
      context.put("time_end", time_end);

      // 表示時間間隔を取得する．
      String time_interval = portlet.getPortletConfig().getInitParameter("p1c-rows");
      context.put("time_interval", time_interval);

      // 表示日数を取得する.
      String weekly_days = portlet.getPortletConfig().getInitParameter("p2a-days");
      context.put("weekly_days", weekly_days);

      // 初期選択グループを取得する.
      String weekly_group = portlet.getPortletConfig().getInitParameter("p3a-group");
      context.put("weekly_group", weekly_group);

      // 初期選択ユーザー／施設を取得する
      String init_user = portlet.getPortletConfig().getInitParameter("p3a-user");
      context.put("init_user", init_user);

      // 初期選択メンバーリストを取得する
      List<UserFacilityLiteBean> memberList = new ArrayList<UserFacilityLiteBean>();
      String selected_user = portlet.getPortletConfig().getInitParameter("p6a-uids");
      if (selected_user == null || "".equals(selected_user)) {
        UserFacilityLiteBean login_user = UserFacilityUtils.getUserFacilityLiteBean(rundata);
        memberList.add(login_user);
      } else {
        String selected_users[] = selected_user.split(",");
        List<UserFacilityLiteBean> ulist = ScheduleUtils.getALEipUserFacility(selected_users, rundata);
        if (ulist == null || ulist.size() == 0) {
          UserFacilityLiteBean login_user = UserFacilityUtils.getUserFacilityLiteBean(rundata);
          memberList.add(login_user);
        } else {
          memberList.addAll(ulist);
        }
      }
      context.put("member_list", memberList);

      // 初期共有メンバー表示フラグを取得する
      String showAll = portlet.getPortletConfig().getInitParameter("p7d-schk");
      if (!("t".equals(showAll))) {
        showAll = "f";
      }
      context.put("init_s_all", showAll);

      // 現在のユーザー名を取得する
      ALEipUser loginuser = ALEipUtils.getALEipUser(rundata);
      // add start
      loginUserName = loginuser.getAliasName().getValue();
      // add end
      String current = loginuser.getAliasName().toString();
      context.put("current_user", current);
      context.put("current_user_ln", loginuser.getName());
      context.put("current_user_id", loginuser.getUserId());

      // add by motegi start
      // ログインユーザーの所属部署1,部署2を取得する
      List<UserGroupPositionLiteBean> list = UserUtils.getPostPositionBeanList((int) loginuser.getUserId().getValue());
      if (list != null && list.size() > 0) {
        UserGroupPositionLiteBean b = list.get(0);
        String current_parent_group_name = b.getPost1GroupName();
        String current_group_name = b.getPost2GroupName();
        context.put("current_group_name", current_group_name);
        context.put("current_parent_group_name", current_parent_group_name);
      }
      // add end
      // add start
      // ログインユーザーの予定登録先一覧を取得・設定する
      List<ScheduleLocationUserBean> scheduleLocationList = getScheduleLocationListBean((int) loginuser.getUserId().getValue());
      context.put("scheduleLocationList", scheduleLocationList);
      // 予定登録先の選択値を決定する。
      if (null == ALEipUtils.getTemp(rundata, context, ScheduleConst.SCHEDULE_LOCATION_USER_ID)) {

        // セッションに予定登録先が無い場合、ログインユーザーIDを画面とセッションに設定する
        context.put(ScheduleConst.SCHEDULE_LOCATION_USER_ID, loginuser.getUserId().getValueAsString());

        ALEipUtils.setTemp(rundata, context, ScheduleConst.SCHEDULE_LOCATION_USER_ID, loginuser.getUserId().getValueAsString());

      } else {

        // セッションに予定登録先が有る場合、取得値を画面へ設定する
        String scheduleLocationUserId = ALEipUtils.getTemp(rundata, context, ScheduleConst.SCHEDULE_LOCATION_USER_ID);

        context.put(ScheduleConst.SCHEDULE_LOCATION_USER_ID, scheduleLocationUserId);

      }
      // add end
      // 表示時間を取得する．
      /*
       * ALDateTimeField view_date = AjaxScheduleUtils.getViewDate(rundata,
       * context); context.put("view_date", view_date);
       */

      // add start 要件No.15 スケジュール画面（月単位）カレンダー追加
      // セッションに保持している基準日付を取得し、
      // カレンダーの初期日付として利用する。
      Calendar baseCalendar = Calendar.getInstance();
      String baseDateString = ALEipUtils.getTemp(rundata, context, "base_date");
      if (baseDateString != null && baseDateString.length() > 0) {
        try {
          SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy'-'MM'-'dd");
          Date tmpDate = dateFormat.parse(baseDateString);
          baseCalendar.setTime(tmpDate);
        } catch (Exception e) {
          // 異常時は、当日とする
          logger.error("基準日付の取得に失敗しました（取得値：" + baseDateString + "）。 基準日付に当日を使用します", e);
        }
      }
      SimpleDateFormat stringFormat = new SimpleDateFormat("yyyy'/'MM'/'dd");
      context.put("base_date", stringFormat.format(baseCalendar.getTime()));
      // add end

      // Velocity テンプレートを読み込む
      String template = portlet.getPortletConfig().getInitParameter("template");
      if (template.equals("ajax-schedule-oneday")) {
        tab = "oneday";
      } else if (template.equals("ajax-schedule-oneday-group")) {
        tab = "oneday-group";
      } else if (template.equals("ajax-schedule-monthly")) {
        tab = "monthly";
      } else if (template.equals("ajax-calendar-weekly")) {
        tab = "weekly";
      } else {
        tab = "weekly-group";
      }

      // アクセスコントロール
      context.put("hasAcl", ScheduleUtils.hasAuthOther(rundata));

      if (isMax) {
        this.putData(rundata, context);
        setTemplate(rundata, "ajax-calendar-list");
      } else {
        if ("ajax-schedule-weekly".equals(template)) {
          setTemplate(rundata, "ajax-calendar-weekly");
        } else {
          setTemplate(rundata, template);
        }
      }
      ALEipUtils.setTemp(rundata, context, "tab", tab);

      // For security
      context.put(ALEipConstants.SECURE_ID, URLEncoder
        .encode((String) rundata.getUser().getTemp(ALEipConstants.SECURE_ID), ALEipConstants.DEF_CONTENT_ENCODING));

      // For sanitizing
      context.put("utils", new ALCommonUtils());

      // add start 要件No.26 スケジュール個別色換え
      // 色分類名一覧を設定
      context.put("scheduleCategoryNameList", ScheduleUtils.SCHEDULE_CATEGORY_NAME_LIST);
      // 色コード一覧を設定
      context.put("scheduleCategoryColorList", ScheduleUtils.SCHEDULE_CATEGORY_COLOR_LIST);
      // add end

    } catch (Exception ex) {
      // change start
      // logger.error("[AjaxScheduleAction] Exception.", ex);
      logger.error("予定一覧画面の表示に失敗しました。ログインユーザー:" + loginUserName, ex);
      ALEipUtils.redirectDBError(rundata);
      // change end
    }
  }

  /**
   * 
   * @param portlet
   * @param context
   * @param rundata
   */
  @Override
  protected void buildMaximizedContext(VelocityPortlet portlet, Context context, RunData rundata) {
    isMax = true;
    buildNormalContext(portlet, context, rundata);
  }

  /**
   * スケジュールを一覧表示します。
   * 
   * @param rundata
   * @param context
   */
  public void doSchedule_list(RunData rundata, Context context) {
    isMax = true;

  }

  private void clearAjaxScheduleSession(RunData rundata, Context context) {
    ALEipUtils.removeTemp(rundata, context, "entityid");
  }

  // add start
  /**
   * ユーザーの予定登録先情報取得
   * 
   * ユーザーの予定登録先一覧を取得します
   * 
   * @param uid
   *          ユーザーID
   * @return ユーザーの予定登録先リスト
   * @throws ALDBErrorException
   */
  private static List<ScheduleLocationUserBean> getScheduleLocationListBean(int uid) throws ALDBErrorException {
    ArrayList<ALEipUser> memberList = new ArrayList<ALEipUser>();
    List<ScheduleLocationUserBean> scheduleLocationList = new ArrayList<ScheduleLocationUserBean>();
    SelectQuery<AvzTScheduleAcl> query = Database.query(AvzTScheduleAcl.class);
    // 抽出条件
    // スケジュール制御.権限種類 = [編集]
    Expression exp1 = ExpressionFactory.matchExp(AvzTScheduleAcl.ACL_TYPE_PROPERTY,
    // change start
      // 条件設定誤りのため修正（内部レビュー指摘事項修正[No.1]）
      // ScheduleConst.SCHEDULEACL_ACL_REF);
      ScheduleConst.SCHEDULEACL_ACL_UPDATE);
    // change end
    // スケジュール制御.適用タイプ = [ユーザー]
    Expression exp2 = ExpressionFactory.matchExp(AvzTScheduleAcl.TARGET_TYPE_PROPERTY, ScheduleConst.SCHEDULEACL_TARGET_USER);
    // スケジュール制御.適用ID = [ログインユーザーID]
    Expression exp3 = ExpressionFactory.matchExp(AvzTScheduleAcl.TARGET_ID_PROPERTY, uid);
    query.setQualifier(exp1.andExp(exp2).andExp(exp3));

    List<AvzTScheduleAcl> scheduleAcls = query.fetchList();
    int scheduleAclssize = scheduleAcls.size();
    List<Number> memberIds = new ArrayList<Number>();
    for (int i = 0; i < scheduleAclssize; i++) {
      AvzTScheduleAcl record = scheduleAcls.get(i);
      memberIds.add(record.getUserId());
    }
    // ログインユーザーIDを最後に追加
    memberIds.add(uid);
    // ユーザー情報、ユーザ表示順位でソートをかける
    SelectQuery<TurbineUser> turbinQuery = Database.query(TurbineUser.class);
    Expression exp = ExpressionFactory.inDbExp(TurbineUser.USER_ID_PK_COLUMN, memberIds);
    turbinQuery.setQualifier(exp);
    memberList.addAll(ALEipUtils.getUsersFromSelectQuery(turbinQuery));

    // 結果分beanにセット
    for (int i = 0; i < memberList.size(); i++) {
      ALEipUser record = memberList.get(i);
      ScheduleLocationUserBean bean = new ScheduleLocationUserBean();
      bean.initField();
      bean.setDisplayName(record.getAliasName().getValue());
      bean.setUserId((int) record.getUserId().getValue());
      scheduleLocationList.add(bean);
    }
    return scheduleLocationList;
  }
  // add end
}
