/*
 * Aipo is a groupware program developed by Aimluck,Inc.
 * Copyright (C) 2004-2008 Aimluck,Inc.
 * http://aipostyle.com/
 * 
 * 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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.Attributes;

import org.apache.cayenne.access.DataContext;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.query.SelectQuery;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.turbine.services.TurbineServices;
import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;

import com.aimluck.commons.field.ALDateTimeField;
import com.aimluck.eip.cayenne.om.portlet.EipMFacility;
import com.aimluck.eip.cayenne.om.portlet.EipTCommonCategory;
import com.aimluck.eip.cayenne.om.portlet.EipTSchedule;
import com.aimluck.eip.cayenne.om.portlet.EipTScheduleMap;
import com.aimluck.eip.cayenne.om.security.TurbineUser;
import com.aimluck.eip.common.ALAbstractSelectData;
import com.aimluck.eip.common.ALDBErrorException;
import com.aimluck.eip.common.ALEipUser;
import com.aimluck.eip.common.ALPageNotFoundException;
import com.aimluck.eip.facilities.FacilityResultData;
import com.aimluck.eip.facilities.util.FacilitiesUtils;
import com.aimluck.eip.modules.actions.common.ALAction;
import com.aimluck.eip.orm.DatabaseOrmService;
import com.aimluck.eip.schedule.util.ScheduleUtils;
import com.aimluck.eip.services.accessctl.ALAccessControlConstants;
import com.aimluck.eip.services.accessctl.ALAccessControlFactoryService;
import com.aimluck.eip.services.accessctl.ALAccessControlHandler;
import com.aimluck.eip.util.ALEipUtils;

/**
 * スケジュール詳細表示の検索結果を管理するクラスです。
 * 
 */
public class ScheduleSelectData extends ALAbstractSelectData {

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

  /** <code>members</code> 共有メンバー */
  private List members;

  /** <code>statusList</code> メンバーの状態 */
  private Map statusList;

  /** <code>userid</code> ID（ユーザ or 施設） */
  private int userid;

  /** <code>type</code> マップ種別（ユーザ or 施設） */
  private String type;

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

  /** <code>viewDate</code> 表示する日 */
  private ALDateTimeField view_date;

  /** <code>facilities</code> 共有施設 */
  private List facilities;

  /** <code>hasAuthorityOtherEdit</code> アクセス権限 */
  private boolean hasAuthorityOtherEdit = false;

  /** <code>hasAuthorityOtherDelete</code> アクセス権限 */
  private boolean hasAuthorityOtherDelete = false;

  /** <code>hasAuthoritySelfEdit</code> アクセス権限 */
  private boolean hasAuthoritySelfEdit = false;

  /** <code>hasAuthoritySelfDelete</code> アクセス権限 */
  private boolean hasAuthoritySelfDelete = false;

  /** アクセスコントロール用の変数 */
  private String aclPortletFeature;

  /*
   * @see com.aimluck.eip.common.ALAbstractSelectData#init(com.aimluck.eip.modules.actions.common.ALAction,
   *      org.apache.turbine.util.RunData, org.apache.velocity.context.Context)
   */
  public void init(ALAction action, RunData rundata, Context context)
      throws ALPageNotFoundException, ALDBErrorException {
    // 展開されるパラメータは以下の通りです。
    // ・userid 形式 int

    // スーパークラスのメソッドを呼び出す。
    super.init(action, rundata, context);
    view_date = new ALDateTimeField("yyyy-MM-dd");
    if (ALEipUtils.isMatch(rundata, context)) {
      if (rundata.getParameters().containsKey("view_date")) {
        String tmpViewDate = rundata.getParameters().getString("view_date");
        view_date.setValue(tmpViewDate);
        if (!view_date.validate(new ArrayList())) {
          logger.debug("[ScheduleSelectData] Parameter cannot validate");
          ALEipUtils.redirectPageNotFound(rundata);
          return;
        }
      }
    }

    loginuserid = ALEipUtils.getUserId(rundata);
    statusList = new HashMap();

    if (rundata.getParameters().containsKey("userid")) {
      String tmpid = rundata.getParameters().getString("userid");
      if (tmpid != null && tmpid.startsWith(ScheduleUtils.TARGET_FACILITY_ID)) {
        userid = Integer.parseInt(tmpid.substring(
            ScheduleUtils.TARGET_FACILITY_ID.length(), tmpid.length()));
        type = ScheduleUtils.SCHEDULEMAP_TYPE_FACILITY;
      } else {
        userid = rundata.getParameters().getInt("userid");
        type = ScheduleUtils.SCHEDULEMAP_TYPE_USER;
      }
    } else if (rundata.getParameters().containsKey("facilityid")) {
      userid = Integer
          .parseInt(rundata.getParameters().getString("facilityid"));
      type = ScheduleUtils.SCHEDULEMAP_TYPE_FACILITY;
    } else {
      userid = loginuserid;
      type = ScheduleUtils.SCHEDULEMAP_TYPE_USER;
    }

    // 自分に関係のある予定なのかどうか判断する
    if (!ScheduleUtils.hasRelation(rundata)) {
      aclPortletFeature = ALAccessControlConstants.POERTLET_FEATURE_SCHEDULE_OTHER;
    } else {
      aclPortletFeature = ALAccessControlConstants.POERTLET_FEATURE_SCHEDULE_SELF;
    }

    // アクセス権限
    ALAccessControlFactoryService aclservice = (ALAccessControlFactoryService) ((TurbineServices) TurbineServices
        .getInstance()).getService(ALAccessControlFactoryService.SERVICE_NAME);
    ALAccessControlHandler aclhandler = aclservice.getAccessControlHandler();

    hasAuthorityOtherEdit = aclhandler.hasAuthority(loginuserid,
        ALAccessControlConstants.POERTLET_FEATURE_SCHEDULE_OTHER,
        ALAccessControlConstants.VALUE_ACL_UPDATE);

    hasAuthorityOtherDelete = aclhandler.hasAuthority(loginuserid,
        ALAccessControlConstants.POERTLET_FEATURE_SCHEDULE_OTHER,
        ALAccessControlConstants.VALUE_ACL_DELETE);

    hasAuthoritySelfEdit = aclhandler.hasAuthority(loginuserid,
        ALAccessControlConstants.POERTLET_FEATURE_SCHEDULE_SELF,
        ALAccessControlConstants.VALUE_ACL_UPDATE);

    hasAuthoritySelfDelete = aclhandler.hasAuthority(loginuserid,
        ALAccessControlConstants.POERTLET_FEATURE_SCHEDULE_SELF,
        ALAccessControlConstants.VALUE_ACL_DELETE);

  }

  /*
   * @see com.aimluck.eip.common.ALAbstractSelectData#selectList(org.apache.turbine.util.RunData,
   *      org.apache.velocity.context.Context)
   */
  protected List selectList(RunData rundata, Context context) {
    // このメソッドは利用されません。
    return null;
  }

  /*
   * @see com.aimluck.eip.common.ALAbstractSelectData#selectDetail(org.apache.turbine.util.RunData,
   *      org.apache.velocity.context.Context)
   */
  protected Object selectDetail(RunData rundata, Context context)
      throws ALPageNotFoundException, ALDBErrorException {
    return ScheduleUtils.getEipTScheduleDetail(rundata, context, false, userid,
        type);
  }

  /*
   * @see com.aimluck.eip.common.ALAbstractSelectData#getResultData(java.lang.Object)
   */
  protected Object getResultData(Object obj) {
    // このメソッドは利用されません。
    return null;
  }

  /*
   * @see com.aimluck.eip.common.ALAbstractSelectData#getResultDataDetail(java.lang.Object)
   */
  protected Object getResultDataDetail(Object obj)
      throws ALPageNotFoundException, ALDBErrorException {
    EipTSchedule record = (EipTSchedule) obj;
    ScheduleDetailResultData rd = new ScheduleDetailResultData();
    rd.initField();
    try {
      // List list = (List) record.getEipTScheduleMaps();

      DataContext dataContext = DatabaseOrmService.getInstance()
          .getDataContext();
      SelectQuery mapquery = new SelectQuery(EipTScheduleMap.class);
      Expression mapexp1 = ExpressionFactory.matchExp(
          EipTScheduleMap.SCHEDULE_ID_PROPERTY, record.getScheduleId());
      mapquery.setQualifier(mapexp1);
      List list = dataContext.performQuery(mapquery);

      List users = new ArrayList();
      List facilityIds = new ArrayList();
      int size = list.size();
      for (int i = 0; i < size; i++) {
        EipTScheduleMap map = (EipTScheduleMap) list.get(i);
        if (ScheduleUtils.SCHEDULEMAP_TYPE_USER.equals(map.getType())) {
          statusList.put(map.getUserId(), map.getStatus());
          // 表示するユーザーの場合
          if (map.getUserId().intValue() == userid) {
            // 仮スケジュールかどうか
            rd.setTmpreserve("T".equals(map.getStatus()));
            // 確定スケジュールかどうか
            rd.setConfirm("C".equals(map.getStatus()));
          }
          users.add(map.getUserId());

          if (userid == map.getUserId().intValue()) {
            EipTCommonCategory category = map.getEipTCommonCategory();
            if (category == null) {
              rd.setCommonCategoryName(null);
            } else {
              rd.setCommonCategoryName(category.getName());
            }
          }

        } else {
          facilityIds.add(map.getUserId());
        }
      }
      SelectQuery query = new SelectQuery(TurbineUser.class);
      Expression exp = ExpressionFactory.inDbExp(TurbineUser.USER_ID_PK_COLUMN,
          users);
      query.setQualifier(exp);
      members = ALEipUtils.getUsersFromSelectQuery(query);
      // members = ALEipUtils.getUsersFromCriteria(rundata, new
      // Criteria().addIn(
      // TurbineUserConstants.USER_ID, users));

      if (facilityIds.size() > 0) {
        SelectQuery fquery = new SelectQuery(EipMFacility.class);
        Expression fexp = ExpressionFactory.inDbExp(
            EipMFacility.FACILITY_ID_PK_COLUMN, facilityIds);
        fquery.setQualifier(fexp);
        facilities = FacilitiesUtils.getFacilitiesFromSelectQuery(fquery);
      }
      // facilities = FacilitiesUtils.getFacilitiesFromCriteria(org_id,
      // new Criteria().addIn(EipMFacilityConstants.FACILITY_ID, facilityIds));

      if (ScheduleUtils.SCHEDULEMAP_TYPE_FACILITY.equals(type)) {
        ALEipUser facilityuser = new ALEipUser();
        facilityuser.initField();
        facilityuser.setUserId(-1);
        facilityuser.setName("");
        facilityuser.setAliasName("", getFacilityName(facilities, userid));
        rd.setUser(facilityuser);
      } else {
        // ユーザー
        rd.setUser(ALEipUtils.getALEipUser(userid));
      }
      // 開始日時
      rd.setStartDate(record.getStartDate());
      // オーナー
      rd.setOwner(record.getOwnerId().intValue() == loginuserid);
      // 終了日時
      rd.setEndDate(record.getEndDate());
      // 予定
      rd.setName(record.getName());
      // ID
      rd.setScheduleId(record.getScheduleId().intValue());
      // 場所
      rd.setPlace(record.getPlace());
      // 内容
      rd.setNote(record.getNote());
      // 公開するかどうか
      rd.setPublic("O".equals(record.getPublicFlag()));
      // 非表示にするかどうか
      rd.setHidden("P".equals(record.getPublicFlag()));
      // 共有メンバーによる編集／削除フラグ
      rd.setEditFlag("T".equals(record.getEditFlag()));

      // DN -> 毎日 (A = N -> 期限なし A = L -> 期限あり)
      // WnnnnnnnN W01111110 -> 毎週(月～金用)
      // MnnN M25 -> 毎月25日
      // S -> 期間での指定
      String ptn = record.getRepeatPattern();
      int count = 0;
      boolean is_repeat = true;
      rd.setRepeat(true);
      boolean is_span = false;
      // 毎日
      if (ptn.charAt(0) == 'D') {
        rd.addText("毎日");
        count = 1;
        // 毎週
      } else if (ptn.charAt(0) == 'W') {
        rd.addText(new StringBuffer().append("毎週 ").append(
            ptn.charAt(1) != '0' ? "日" : "").append(
            ptn.charAt(2) != '0' ? "月" : "").append(
            ptn.charAt(3) != '0' ? "火" : "").append(
            ptn.charAt(4) != '0' ? "水" : "").append(
            ptn.charAt(5) != '0' ? "木" : "").append(
            ptn.charAt(6) != '0' ? "金" : "").append(
            ptn.charAt(7) != '0' ? "土" : "").append(" 曜日").toString());
        count = 8;
        // 毎月
      } else if (ptn.charAt(0) == 'M') {
        rd.addText(new StringBuffer().append("毎月 ").append(
            Integer.parseInt(ptn.substring(1, 3))).append("日").toString());
        count = 3;
        // 期間
      } else if (ptn.charAt(0) == 'S') {
        rd.setSpan(true);
        rd.setRepeat(false);
        is_repeat = false;
      } else {
        rd.setRepeat(false);
        is_repeat = false;

      }
      if (is_repeat) {
        if (ptn.charAt(count) == 'N') {
          rd.setLimit(false);
        } else {
          rd.setLimit(true);
          // 期限
          rd.addText(new StringBuffer().append(" （").append(
              rd.getStartDate().getYear()).append("年").append(
              rd.getStartDate().getMonth()).append("月").append(
              rd.getStartDate().getDay()).append("日 から ").append(
              rd.getEndDate().getYear()).append("年").append(
              rd.getEndDate().getMonth()).append("月").append(
              rd.getEndDate().getDay()).append("日 まで）").toString());
        }
      }
      // 登録者
      rd.setCreateUser(ALEipUtils.getALEipUser(record.getCreateUserId()
          .intValue()));
      // 更新者
      rd.setUpdateUser(ALEipUtils.getALEipUser(record.getUpdateUserId()
          .intValue()));
      // 登録日時
      rd.setCreateDate(record.getCreateDate());
      // 更新日時
      rd.setUpdateDate(record.getUpdateDate());
      // ログインユーザーID
      rd.setLoginuser(loginuserid == userid);
      // Calendar cal = Calendar.getInstance();
      // cal.setTime(record.getStartDate());
      // cal.set(Calendar.HOUR, 0);
      // cal.set(Calendar.MINUTE, 0);
      // view_date.setValue(cal.getTime());
    } catch (Exception e) {

      // TODO: エラー処理
      logger.error("Exception", e);

      return null;
    }
    return rd;
  }

  /*
   * @see com.aimluck.eip.common.ALAbstractSelectData#getColumnMap()
   */
  protected Attributes getColumnMap() {
    // このメソッドは利用されません。
    return null;
  }

  private String getFacilityName(List list, int id) {
    FacilityResultData rd = null;
    int size = list.size();
    for (int i = 0; i < size; i++) {
      rd = (FacilityResultData) list.get(i);
      if (rd.getFacilityId().getValue() == id) {
        return rd.getFacilityName().getValue();
      }
    }
    return "";
  }

  /**
   * 共有メンバーを取得します。
   * 
   * @return
   */
  public List getMemberList() {
    return members;
  }

  /**
   * 状態を取得します。
   * 
   * @param id
   * @return
   */
  public String getStatus(long id) {
    return (String) statusList.get(Integer.valueOf((int) id));
  }

  /**
   * 
   * @return
   */
  public ALDateTimeField getViewDate() {
    return view_date;
  }

  public List getFacilityList() {
    return facilities;
  }

  /**
   * アクセス権限チェック用メソッド。<br />
   * アクセス権限の機能名を返します。
   * 
   * @return
   */
  public String getAclPortletFeature() {
    return aclPortletFeature;
  }

  /**
   * アクセス権限用メソッド。<br />
   * アクセス権限の有無を返します。
   * 
   * @return
   */
  public boolean hasAuthorityOtherEdit() {
    return hasAuthorityOtherEdit;
  }

  public boolean hasAuthorityOtherDelete() {
    return hasAuthorityOtherDelete;
  }

  public boolean hasAuthoritySelfEdit() {
    return hasAuthoritySelfEdit;
  }

  public boolean hasAuthoritySelfDelete() {
    return hasAuthoritySelfDelete;
  }

}
