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

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

import com.aimluck.commons.field.ALDateTimeField;
import com.aimluck.eip.common.ALData;
import com.aimluck.eip.schedule.util.ScheduleUtils;

/**
 * 週間スケジュールのコンテナです。
 * 
 */
public class ScheduleWeekContainer implements ALData {

  /** <code>dayList</code> スケジュールリスト */
  private List<ScheduleDayContainer> dayList;

  /*
   * 
   */
  public void initField() {
    dayList = new ArrayList<ScheduleDayContainer>();
  }

  /**
   * 表示開始する日付を設定します。
   * 
   * @param cal
   */
  public void setViewStartDate(Calendar cal) {
    for (int i = 1; i <= 7; i++) {
      // 日付を1日ずつずらす
      ScheduleDayContainer con = new ScheduleDayContainer();
      con.initField();
      con.setDate(cal.getTime());
      dayList.add(con);
      cal.add(Calendar.DATE, 1);
    }
  }

  /**
   * スケジュールをコンテナに格納します。
   * 
   * @param rd
   */
  public boolean addResultData(ScheduleResultData rd) {
    int size = dayList.size();

    for (int i = 0; i < size; i++) {
      ScheduleDayContainer con = dayList.get(i);
      ALDateTimeField field = con.getDate();
      if (rd.getPattern().equals("Z")) {
        setDay2DayCrossoverSchedule(con, rd, con.getDate().getValue(), rd.getStartDate().getValue(), rd.getEndDate().getValue());

      } else /* add end */if (!rd.getPattern().equals("N")) {
        // 繰り返しスケジュール
        if (ScheduleUtils.isView(con.getDate(), rd.getPattern(), rd.getStartDate().getValue(), rd.getEndDate().getValue())) {
          Calendar temp = Calendar.getInstance();
          temp.setTime(field.getValue());
          temp.set(Calendar.HOUR, Integer.parseInt(rd.getStartDate().getHour()));
          temp.set(Calendar.MINUTE, Integer.parseInt(rd.getStartDate().getMinute()));
          temp.set(Calendar.SECOND, 0);
          temp.set(Calendar.MILLISECOND, 0);
          Calendar temp2 = Calendar.getInstance();
          temp2.setTime(field.getValue());
          temp2.set(Calendar.HOUR, Integer.parseInt(rd.getEndDate().getHour()));
          temp2.set(Calendar.MINUTE, Integer.parseInt(rd.getEndDate().getMinute()));
          temp2.set(Calendar.SECOND, 0);
          temp2.set(Calendar.MILLISECOND, 0);

          // mod by motegi 共通化
          // ScheduleResultData rd3 = new ScheduleResultData();
          // rd3.initField();
          // rd3.setScheduleId((int) rd.getScheduleId().getValue());
          // rd3.setParentId((int) rd.getParentId().getValue());
          // rd3.setName(rd.getName().getValue());
          // // 開始日を設定し直す
          // rd3.setStartDate(temp.getTime());
          // // 終了日を設定し直す
          // rd3.setEndDate(temp2.getTime());
          // rd3.setTmpreserve(rd.isTmpreserve());
          // rd3.setPublic(rd.isPublic());
          // rd3.setHidden(rd.isHidden());
          // rd3.setDummy(rd.isDummy());
          // rd3.setLoginuser(rd.isLoginuser());
          // rd3.setOwner(rd.isOwner());
          // rd3.setMember(rd.isMember());
          // rd3.setType(rd.getType());
          // // 繰り返しはON
          // rd3.setRepeat(true);
          // // add by motegi start 印刷用スケジュール画面対応
          // // 場所
          // rd3.setPlace(rd.getPlace().getValue());
          // // add end
          // con.addResultData(rd3);
          con.addResultData(resultData2resultData(rd, temp, temp2, true));
          // mod end
        }
      } else if (field.getYear().equals(rd.getStartDate().getYear())
        && field.getMonth().equals(rd.getStartDate().getMonth())
        && field.getDay().equals(rd.getStartDate().getDay())) {
        con.addResultData(rd);
        return true;
      }
    }
    return false;
  }

  // add start
  /**
   * (携帯)期間スケジュールをコンテナに格納します。
   * 
   * @param rd
   */
  public boolean addResultDataCellSpanSchedule(ScheduleResultData rd) {
    int size = dayList.size();

    for (int i = 0; i < size; i++) {
      ScheduleDayContainer con = dayList.get(i);
      ALDateTimeField field = con.getDate();
      Calendar viewDate = Calendar.getInstance();
      viewDate.setTime(field.getValue());
      viewDate.set(Calendar.HOUR_OF_DAY, 0);
      viewDate.set(Calendar.MINUTE, 0);
      if (!((viewDate.getTime().compareTo(rd.getStartDate().getValue()) < 0) || (viewDate.getTime().compareTo(rd.getEndDate().getValue()) > 0))) {
        con.addResultData(rd);
      }
    }
    return false;
  }

  // add end

  /**
   * 期間スケジュールをコンテナに格納します。
   * 
   * @param rd
   */

  /*
   * public void addSpanResultData(int index, ScheduleResultData rd) { int span =
   * rd.getRowspan(); ScheduleDayContainer con = (ScheduleDayContainer)
   * dayList.get(index); con.setHasspan(true); con.setSpanResultData(rd); for
   * (int i = 1; i < span; i++) { con = (ScheduleDayContainer) dayList.get(index +
   * i); con.setHasspan(true); } }
   */

  /**
   * スケジュールリストを取得します。
   * 
   * @return
   */
  public List<ScheduleDayContainer> getDayList() {
    return dayList;
  }

  /**
   * 日跨ぎスケジュールをコンテナに格納する。
   * 
   * @param con
   *            スケジュール 日コンテナ
   * @param rd
   *            予定データ
   * @param targetDate
   *            処理対象日
   * @param startDate
   *            開始日
   * @param endDate
   *            終了日
   * @author motegi-takeshi
   */
  private void setDay2DayCrossoverSchedule(ScheduleDayContainer con, ScheduleResultData rd, Date targetDate, Date startDate, Date endDate) {

    // 処理対象日の00：00（比較用の処理対象日）
    Calendar cal1 = Calendar.getInstance();
    cal1.setTime(targetDate);
    cal1.set(Calendar.HOUR_OF_DAY, 0);
    cal1.set(Calendar.MINUTE, 0);
    cal1.set(Calendar.SECOND, 0);
    cal1.set(Calendar.MILLISECOND, 0);
    Date borderStartDate = cal1.getTime();

    // 処理対象日の23：59
    Calendar cal2 = Calendar.getInstance();
    cal2.setTime(targetDate);
    cal2.set(Calendar.HOUR_OF_DAY, 23);
    cal2.set(Calendar.MINUTE, 59);
    cal2.set(Calendar.SECOND, 0);
    cal2.set(Calendar.MILLISECOND, 0);
    Date borderEndDate = cal2.getTime();

    // 開始日
    Calendar calStart = Calendar.getInstance();
    calStart.setTime(startDate);
    calStart.set(Calendar.HOUR_OF_DAY, 0);
    calStart.set(Calendar.MINUTE, 0);
    calStart.set(Calendar.SECOND, 0);
    calStart.set(Calendar.MILLISECOND, 0);
    Date tmpStartDate = calStart.getTime();

    // 終了日
    Calendar calEnd = Calendar.getInstance();
    calEnd.setTime(endDate);
    calEnd.set(Calendar.HOUR_OF_DAY, 0);
    calEnd.set(Calendar.MINUTE, 0);
    calEnd.set(Calendar.SECOND, 0);
    calEnd.set(Calendar.MILLISECOND, 0);
    Date tmpEndDate = calEnd.getTime();

    Calendar temp = Calendar.getInstance();
    Calendar temp2 = Calendar.getInstance();
    if (borderStartDate.compareTo(tmpStartDate) == 0) {
      // 対象日が日またぎの開始日
      // 開始日はそのまま、終了日は23：59
      temp.setTime(startDate);
      temp2.setTime(borderEndDate);
    } else if (tmpStartDate.before(borderStartDate) && borderStartDate.before(tmpEndDate)) {
      // 開始日<処理対象日 かつ 処理対象日<終了日
      // 開始日は00：00、終了日は23：59
      temp.setTime(borderStartDate);
      temp2.setTime(borderEndDate);
    } else if (borderStartDate.compareTo(tmpEndDate) == 0) {
      // 対象日が日またぎの終了日
      // 開始日は00：00、終了日はそのまま
      temp.setTime(borderStartDate);
      temp2.setTime(endDate);
    } else {
      // いずれの条件にも合致しなければ処理対象外
      return;
    }
    con.addResultData(resultData2resultData(rd, temp, temp2, false));
  }

  /**
   * 表示用予定データへデータを乗せかえる
   * 
   * @param rd
   *            元データ
   * @param temp
   *            開始日時
   * @param temp2
   *            終了日時
   * @param isRepeat
   *            繰り返しフラグ
   * @return 表示用予定データ
   * 
   * @author motegi-takeshi
   */
  private ScheduleResultData resultData2resultData(ScheduleResultData rd, Calendar temp, Calendar temp2, boolean isRepeat) {
    ScheduleResultData rd3 = new ScheduleResultData();
    rd3.initField();
    rd3.setScheduleId((int) rd.getScheduleId().getValue());
    rd3.setParentId((int) rd.getParentId().getValue());
    rd3.setName(rd.getName().getValue());
    // 開始日を設定し直す
    rd3.setStartDate(temp.getTime());
    // 終了日を設定し直す
    rd3.setEndDate(temp2.getTime());
    rd3.setTmpreserve(rd.isTmpreserve());
    rd3.setPublic(rd.isPublic());
    rd3.setHidden(rd.isHidden());
    rd3.setDummy(rd.isDummy());
    rd3.setLoginuser(rd.isLoginuser());
    rd3.setOwner(rd.isOwner());
    rd3.setMember(rd.isMember());
    rd3.setType(rd.getType());
    // // 繰り返しフラグ
    rd3.setRepeat(isRepeat);
    // 場所
    rd3.setPlace(rd.getPlace().getValue());
    // add start
    // 状態
    rd3.setStatus(rd.getStatus());
    // 重要フラグ
    rd3.setPriority(rd.getPriority());
    // 必須／任意フラグ
    rd3.setRequired(rd.getRequired());
    // 繰り返しフラグ(携帯表示判定用)
    rd3.setPattern(rd.getPattern());
    // add end
    // add start 要件No.9 スケジュール表示 （仮の予定、確定した予定）
    rd3.setTemporaryFlag(rd.getTemporaryFlag());
    // add end
    // add start 要件No.26 スケジュール個別色換え
    rd3.setIndividualColor(rd.getIndividualColor());
    // add end
    // add start 要件No.16 スケジュール画面（月単位／週単位／日単位）右クリックメニュー
    rd3.setShare(rd.isShare());
    // add end
    // add start 結合試験障害16-01対応
    rd3.setOrganizer(rd.isOrganizer());
    // add end
    return rd3;
  }

}
