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

import java.io.File;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.ParseException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import org.apache.cayenne.DataRow;
import org.apache.cayenne.access.DataContext;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.query.SelectQuery;
import org.apache.jetspeed.daemon.Daemon;
import org.apache.jetspeed.daemon.DaemonConfig;
import org.apache.jetspeed.daemon.DaemonEntry;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.jetspeed.services.resources.JetspeedResources;
import com.aimluck.commons.field.ALDateTimeField;
import com.aimluck.eip.cayenne.om.portlet.ImwMPaidHolidayList;
import com.aimluck.eip.cayenne.om.portlet.ImwTPaidHoliday;
import com.aimluck.eip.cayenne.om.security.TurbineUser;
import com.aimluck.eip.orm.DatabaseOrmService;
import com.aimluck.eip.util.ALEipUtils;
import java.text.DateFormat;
import com.aimluck.eip.mail.util.ALEipUserAddr;
import com.aimluck.eip.mail.util.ALMailUtils;

/**
 * 文書管理用の日時バッチを管理するためのクラスです。 <br />
 */
public class MonthlyBatchPaidHolidayDaemon implements Daemon {

  private int status = Daemon.STATUS_NOT_PROCESSED;

  private int result = Daemon.RESULT_UNKNOWN;

  private DaemonConfig config = null;

  private DaemonEntry entry = null;

  private static int endNum = 24;

  List serveUserList = null;

  int serveYear = 0;

  int paidHolidayDays = 0;

  int sYear = 0;

  int sMonth = 0;

  int sDay = 0;

  Date enterCompanyDate = null;

  int userId = 0;

  String email = null;

  // 日時バッチ最終処理日を保持するpropertiesファイルのパス
  private final String FILEPATH_PROPERTIES = JetspeedResources.getString(
      "aipo.conf", "")
      + "/MonthlyBatchPaidHoliday.properties";

  /**
   * 実行可能かを判定．サーバー起動時のみfalse． それ以降はtrueにする．
   */
  private boolean enable_run = false;

  private DataContext dataContext;

  private Calendar lastmonth = Calendar.getInstance();

  private Calendar today = Calendar.getInstance();

  private String lineSeparator = System.getProperty("line.separator");
  
  /** Add 2011/02/14 小濵　Start--- */
  private FileOutputStream fs;
  /** Add 2011/02/14 小濵　End--- */

  /**
   * Static initialization of the logger for this class
   */
  private static final JetspeedLogger logger = JetspeedLogFactoryService
      .getLogger(MonthlyBatchPaidHolidayDaemon.class.getName());

  /**
   * 日時バッチ処理
   */
  public void run() {

    // ASP版のときは正しいorgidを設定すること。
    String org_id = DatabaseOrmService.getInstance().getDefaultOrgId();

    if (!enable_run) {
      // サーバー起動時は実行しないようにする．
      enable_run = true;
      return;
    }
    
    /** Add 2011/02/14 小濵　Start--- */
    File lockFile = new File(JetspeedResources.getString("aipo.conf", "") + "/BatchTemp.lock");
    lockFile.deleteOnExit();

    try {
      fs = new FileOutputStream(lockFile);
      FileChannel fc = fs.getChannel();
  
      FileLock lock = fc.tryLock();
  
      if (lock == null) {
          return;
      }
      try {
    /** Add 2011/02/14 小濵　End--- */
       // 実行時刻の判定
        int runhour = JetspeedResources.getInt("monthlyBatchPaidHoliday.runhour");
        int nowHour = today.get(Calendar.HOUR_OF_DAY);
        if (nowHour < runhour) {
          return;
        }
        // システム日付
        today = Calendar.getInstance();
        /** Add 2010/08/09 チョウコウ Start */
    
        // バッチ最終処理日
        String maildmonth = getMonthlyBatchPaidHolidayProperty("monthlybatch.lastmonth");
        
        /** Delete 2010/09/02 チョウコウ Start */
        // if (today.get(Calendar.DATE) != 1) {
        // return;
        // }
        /** Delete 2010/09/02 チョウコウ End */
        
        if (maildmonth != null) {
          try {
            lastmonth.setTime(DateFormat.getDateInstance().parse(maildmonth));
            // 既に処理済の場合は中止
    
            if (today.get(Calendar.YEAR) == lastmonth.get(Calendar.YEAR)
                && today.get(Calendar.MONTH) == lastmonth.get(Calendar.MONTH)) {
    //          file.delete();
              return;
            }
          } catch (ParseException e) {
            lastmonth.setTime(today.getTime());
            lastmonth.add(Calendar.DATE, -1);
          }
        } else {
          lastmonth.setTime(today.getTime());
          lastmonth.add(Calendar.DATE, -1);
        }
    
        try {
    
          /** Add 2011/02/07 小濵　Start--- */
          //現在は有効・無効ごとに処理を変える部分が存在しないため、コメントアウト
          //適用終了日を過ぎているレコードを無効化する。
    //      SelectQuery query2 = new SelectQuery(ImwTPaidHoliday.class);
    //      Expression exp21 = ExpressionFactory.matchExp(
    //          ImwTPaidHoliday.DISABLED_PROPERTY, "F");
    //      query2.setQualifier(exp21);
    //      SimpleDateFormat listFormat = new SimpleDateFormat("yyyy-MM-dd");
    //      Expression exp22 = ExpressionFactory.lessExp(
    //          ImwTPaidHoliday.VALID_END_DATE_PROPERTY.toString(), listFormat.format(today.getTime()));
    //      query2.andQualifier(exp22);
    //      
    //      List paidHolidayList = dataContext.performQuery(query2);
    //      
    //      for(int i = 0;i < paidHolidayList.size();i++){
    //        ImwTPaidHoliday record = (ImwTPaidHoliday)paidHolidayList.get(i);
    //        record.setDisabled("N");
    //        dataContext.commitChanges();
    //      }
          /** Add 2011/02/07 小濵　End--- */
    
          
          SelectQuery query = new SelectQuery(ImwMPaidHolidayList.class);
          List userList = dataContext.performQuery(query);
    
          for (int i = 0; i < userList.size(); i++) {
    
            ImwMPaidHolidayList obj = (ImwMPaidHolidayList) userList.get(i);
            serveYear = obj.getServeYears();
            paidHolidayDays = obj.getPaidHolidayDays();
    
            String query1 = "select t.email , t.user_id , t.enter_company_date as enter_company_date_property "
                + "from turbine_user t "
                + "where t.user_id >3 "
                /** Update 2010-09-02 チョウコウ Start */
                + "and (date_part('year',current_date)-date_part('year',enter_company_date))*12 + (date_part('month',current_date)-date_part('month',enter_company_date)) = "
                /** Update 2010-09-02 チョウコウ End */
                + serveYear + " and t.disabled = 'F'";
    
            SQLTemplate rawSelect = new SQLTemplate(TurbineUser.class, query1, true);
            rawSelect.setFetchingDataRows(true);
            serveUserList = dataContext.performQuery(rawSelect);
            DataRow dataRow;
            ALEipUserAddr email = null;
            int serveNum = serveUserList.size();
            if (serveNum != 0) {
              for (int j = 0; j < serveNum; j++) {
                dataRow = (DataRow) serveUserList.get(j);
                email = new ALEipUserAddr();
                userId = (Integer) ALEipUtils.getObjFromDataRow(dataRow,
                    TurbineUser.USER_ID_PK_COLUMN);
                enterCompanyDate = (Date) ALEipUtils.getObjFromDataRow(dataRow,
                    TurbineUser.ENTER_COMPANY_DATE_PROPERTY_COLUMN);
    
                email.setPcMailAddr((String) ALEipUtils.getObjFromDataRow(dataRow,
                    TurbineUser.EMAIL_COLUMN));
    
                ImwTPaidHoliday paidHoliday = (ImwTPaidHoliday) dataContext
                    .createAndRegisterNewObject(ImwTPaidHoliday.class);
    
                paidHoliday.setUserId(userId);
                paidHoliday.setPaidHolidayDays(paidHolidayDays);
                paidHoliday.setDisabled("F");
    
                Calendar c = Calendar.getInstance();
                c.setTime(enterCompanyDate);
                sYear = c.get(Calendar.YEAR);
                sMonth = c.get(Calendar.MONTH) + 1;
                sDay = c.get(Calendar.DATE);
                c.set(sYear, sMonth + serveYear - 1, sDay);
                Date startDate = c.getTime();
    
                /** Update 2010-09-02 チョウコウ Start */
                // c.set(sYear, sMonth + serveYear - 1 + endNum, sDay);
                c.set(sYear, sMonth + serveYear - 1 + endNum, sDay - 1);
                /** Update 2010-09-02 チョウコウ End */
    
                Date endDate = c.getTime();
                paidHoliday.setValidStartDate(startDate);
                paidHoliday.setValidEndDate(endDate);
                Date now = new Date();
                paidHoliday.setCreateDate(now);
                paidHoliday.setUpdateDate(now);
    
                if (!email.equals(null) && !email.equals("")) {
                  List userEmailList = new ArrayList();
                  userEmailList.add(email);
                  // メール送信
                  ALMailUtils.sendMailDelegate(org_id, 1, userEmailList, this
                      .getSubject(), "subject", createMessage(paidHolidayDays,
                      startDate), "msg", ALMailUtils
                      .getSendDestType(ALMailUtils.KEY_MSGTYPE_SCHEDULE),
                      new ArrayList());
                }
              }
              dataContext.commitChanges();
            }
          }
    
          // バッチ最終処理日を設定
          ALDateTimeField date = new ALDateTimeField("yyyy/MM/dd");
          date.setValue(today.getTime());
    
          // メール最終送信日を設定
          setMonthlyBatchPaidHolidayProperty("monthlybatch.lastmonth", date
              .toString());
          
    //      file.delete();
          logger.info("MonthlyBatchPaidHolidayDaemon End");
          this.setResult(Daemon.RESULT_SUCCESS);
        } catch (Exception e) {
          this.setResult(Daemon.RESULT_FAILED);
          logger.error("MonthlyBatchPaidHolidayDaemon", e);
        }
    /** Add 2011/02/14 小濵　Start--- */
      } finally {
        // ロックの開放
        lock.release();
      }

    }catch (Exception e) {
      logger.error("MonthlyBatchPaidHolidayDaemon", e);
    } finally {
      try {
        fs.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    /** Add 2011/02/14 小濵　End--- */
  }

  /**
   * properties ファイル書込み
   * 
   * @param key
   * @param value
   * @return
   */
  private boolean setMonthlyBatchPaidHolidayProperty(String key, String value) {
    try {
      Properties prop = new Properties();

      prop.setProperty(key, value);

      prop.store(new FileOutputStream(FILEPATH_PROPERTIES),
          "MonthlyBatchPaidHoliday properties");

      return true;
    } catch (Exception e) {
      logger.error("MonthlyBatchPaidHolidayDaemon", e);
      return false;
    }
  }

  /**
   * propertiesファイル読み込み
   * 
   * @param key
   * @return
   */
  private String getMonthlyBatchPaidHolidayProperty(String key) {
    try {
      Properties prop = new Properties();

      // ファイルが存在しない場合はnullを返す。
      File file = new File(FILEPATH_PROPERTIES);
      if (!file.exists()) {
        return null;
      }

      prop.load(new FileInputStream(FILEPATH_PROPERTIES));
      String value = prop.getProperty(key);

      return value;
    } catch (Exception e) {
      logger.error("MonthlyBatchPaidHolidayDaemon", e);
      return null;
    }

  }

  /**
   * メッセージ作成
   */
  private String createMessage(int days, Date date) {

    Calendar c = Calendar.getInstance();
    c.setTime(date);
    int year = c.get(Calendar.YEAR);
    int month = c.get(Calendar.MONTH) + 1;
    int day = c.get(Calendar.DATE);
    int week = c.get(Calendar.DAY_OF_WEEK) - 1;
    String weekarr[] = { "日", "月", "火", "水", "木", "金", "土" };

    String msg = "有給残日数の更新をしました。" + "\n" + "付与日数、使用開始日、有効期間は以下の通りです。" + "\n"
        + "付与日数：" + days + "日" + "\n" + "使用開始日：" + year + "年" + month + "月"
        + day + "日(" + weekarr[week] + "曜日)" + "\n" + "有効期間：2年間" + "\n"
        + "本メールは有給残日数更新者に対し自動送信されています。" + "\n";
    return msg;
  }

  /**
   * サブジェクトの取得
   */

  private String getSubject() {
    String subject = "有給残日数の更新";
    return subject;
  }

  /* *** Daemon interface *** */

  /**
   * Init this Daemon from the DaemonFactory
   */
  public void init(DaemonConfig config, DaemonEntry entry) {
    this.config = config;
    this.entry = entry;
    dataContext = DatabaseOrmService.getInstance().getDataContext();
    enable_run = false;
  }

  /**
   */
  public DaemonConfig getDaemonConfig() {
    return this.config;
  }

  /**
   */
  public DaemonEntry getDaemonEntry() {
    return this.entry;
  }

  /**
   * Return the status for this Daemon
   * 
   * @see Daemon#STATUS_NOT_PROCESSED
   * @see Daemon#STATUS_PROCESSED
   * @see Daemon#STATUS_PROCESSING
   */
  public int getStatus() {
    return this.status;
  }

  /**
   * Set the status for this Daemon
   * 
   * @see #STATUS_NOT_PROCESSED
   * @see #STATUS_PROCESSED
   * @see #STATUS_PROCESSING
   */
  public void setStatus(int status) {
    this.status = status;
  }

  /**
   * @see Daemon#getResult()
   */
  public int getResult() {
    return this.result;
  }

  /**
   * @see Daemon#setResult(int result)
   */
  public void setResult(int result) {
    this.result = result;
  }

  /**
   * @see Daemon#getMessage()
   */
  public String getMessage() {
    return null;
  }

}
