/*
 * 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 aipo.batch.userinfo;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.cayenne.access.DataContext;
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.jetspeed.services.resources.JetspeedResources;

import aipo.batch.utils.BatchUtils;

import com.aimluck.eip.cayenne.om.account.AvzMGroupsend;
import com.aimluck.eip.cayenne.om.account.AvzMGroupsendPosition;
import com.aimluck.eip.common.ALEipManager;
import com.aimluck.eip.orm.Database;
import com.aimluck.eip.orm.query.SelectQuery;

/**
 * <HR>
 * <p>
 * 
 * グループ送信情報のファイルを読み込み、Aipoのデータベースにインポートします。<br>
 * <P>
 * <HR>
 * <P>
 */
public class GroupsendImporter {
  /** ロガー */
  private static final JetspeedLogger logger =
    JetspeedLogFactoryService.getLogger(GroupsendImporter.class.getName());

  /** プロパティファイル */
  private static final String PROPERTY_FILE =
    JetspeedResources.getString("aipo.conf", "")
      + File.separator
      + "Batch.properties";

  /** グループ送信ファイル名 */
  private static final String GROUPSEND_FILE_NAME =
    (String) BatchUtils.getProperties(PROPERTY_FILE).get(
      "import.groupsend.file.name");

  /**
   * グループ送信情報インポート
   * <p>
   * グループ送信情報のファイルを読み込み、Aipoのデータベースにインポートします。<br>
   * 
   * @param dataContext
   * 
   * @return boolean True(処理成功)、False(処理失敗)
   * @exception DBエラー
   *              、ファイルなし 、データ件数エラーの際に発生
   */
  public boolean importGroupsend(DataContext dataContext) throws Exception {

    int updateCounter = 0;
    int insertCounter = 0;
    int deleteCounter = 0;
    BufferedReader reader = null;

    try {
      // 開始メッセージをログに出力
      logger.info("グループ送信情報更新開始");

      // CSVデータファイル
      File csvFile =
        new File(BatchUtils.IMPORT_CSV_FILE_PATH
          + File.separator
          + GROUPSEND_FILE_NAME); // データファイル
      if (!csvFile.exists()) {
        throw new FileNotFoundException();
      }

      reader =
        new BufferedReader(new InputStreamReader(
          new FileInputStream(csvFile),
          BatchUtils.FILE_ENCODING));

      List<AvzMGroupsend> groupsendList = new ArrayList<AvzMGroupsend>();
      List<String> groupsendAddedList = new ArrayList<String>(); // 処理済みのグループ送信コード格納配列

      // 最終行まで読み込む
      String line = "";
      while ((line = reader.readLine()) != null) {
        String[] s = line.split(BatchUtils.SEPARATOR);
        String groupSendCode = BatchUtils.trimDoubleQuotes(s[0]); // グループ送信コード
        String groupSendName = BatchUtils.trimDoubleQuotes(s[1]); // グループ送信名
        String category = BatchUtils.trimDoubleQuotes(s[2]); // グループ送信種別

        logger.debug("groupsend code -> " + groupSendCode + ".");

        // 処理済みグループ送信コードに存在するか判定
        // 存在する場合はコード重複エラーとしてロールバック
        if (groupsendAddedList.contains(groupSendCode)) {
          throw new Exception("グループ送信コードが重複しています。グループ送信コード：["
            + groupSendCode
            + "]");
        }

        // グループ送信コードでグループ送信情報を検索する
        SelectQuery<AvzMGroupsend> query = Database.query(AvzMGroupsend.class);
        // 検索条件：グループ送信コードと一致
        Expression exp =
          ExpressionFactory.matchExp(
            AvzMGroupsend.GROUPSEND_CODE_PROPERTY,
            groupSendCode);
        query.setQualifier(exp); // 検索実行
        List<AvzMGroupsend> resultList = query.fetchList();

        // <グループ送信情報>件数が2件以上の場合、例外を発生させる。
        if (resultList.size() >= 2) {
          throw new Exception("グループ送信コードに一致するグループ送信情報が2件以上見つかりました。グループ送信コード：["
            + groupSendCode
            + "]");
        }

        AvzMGroupsend groupSend = null;
        // <グループ送信情報>件数が1件の場合
        if (resultList.size() == 1) {
          // グループ送信情報を更新する。
          groupSend = resultList.get(0);
          logger.debug("groupsend update -> "
            + groupSend.getGroupsendId()
            + " start.");
          groupSend.setGroupsendName(groupSendName);
          if (category.equals(AvzMGroupsend.GROUPSEND_CATEGORY_POST)) {
            groupSend.setCategory(AvzMGroupsend.GROUPSEND_CATEGORY_POST);
          }
          groupSend.setUpdateDate(new Date());

          dataContext.commitChanges();
          // 更新件数をインクリメントする。
          updateCounter++;
        }

        // <グループ送信情報>件数が0件の場合
        if (resultList.size() == 0) {
          logger.debug("groupsend insert -> " + groupSendCode + " start.");

          groupSend = new AvzMGroupsend();
          groupSend = Database.create(AvzMGroupsend.class);
          groupSend.setGroupsendName(groupSendName);
          groupSend.setGroupsendCode(groupSendCode);
          if (category.equals(AvzMGroupsend.GROUPSEND_CATEGORY_POST)) {
            groupSend.setCategory(AvzMGroupsend.GROUPSEND_CATEGORY_POST);
          }
          groupSend.setCreateDate(new Date());
          groupSend.setUpdateDate(new Date());
          dataContext.commitChanges();

          // グループ送信順位情報に登録
          List<AvzMGroupsendPosition> posposlist =
            Database.query(AvzMGroupsendPosition.class).fetchList();
          int new_pos =
            (posposlist != null && posposlist.size() > 0)
              ? posposlist.size() + 1
              : 1;
          AvzMGroupsendPosition groupSendPosition =
            Database.create(AvzMGroupsendPosition.class);
          groupSendPosition.setToAvzMGroupsend(groupSend);
          groupSendPosition.setPosition(Integer.valueOf(new_pos));
          logger.debug("groupsend position inserted -> " + new_pos + ".");
          dataContext.commitChanges();

          // 登録件数をインクリメントする。
          insertCounter++;
        }

        // 処理済みのグループ送信コード格納配列に保持
        groupsendAddedList.add(groupSendCode);

        // <グループ送信情報レコード>を<グループ送信情報ファイル配列>に追加で格納する。
        groupsendList.add(groupSend);
      }

      // グループ送信情報ファイルをクローズする。
      reader.close();
      reader = null;

      logger.debug("groupsend delete start.");
      // グループ送信情報の全レコードを抽出する。
      SelectQuery<AvzMGroupsend> groupSendQuery =
        Database.query(AvzMGroupsend.class);
      groupSendQuery.orderAscending(AvzMGroupsend.GROUPSEND_CODE_PROPERTY);
      // グループ送信情報の削除用リスト
      List<AvzMGroupsend> delList = groupSendQuery.fetchList();

      // 全レコードに対して判定
      for (Iterator<AvzMGroupsend> dbGroupsend = delList.iterator(); dbGroupsend
        .hasNext();) {
        AvzMGroupsend groupsend = dbGroupsend.next();
        for (AvzMGroupsend fileGroupsend : groupsendList) {
          // グループ送信IDが一致したら削除リストから削除
          if (fileGroupsend.getGroupsendId() == groupsend.getGroupsendId()) {
            dbGroupsend.remove();
            break;
          }
        }
      }
      // 削除リストのグループ送信を削除
      for (AvzMGroupsend delGroupsend : delList) {
        AvzMGroupsendPosition delGroupsendPosition =
          new AvzMGroupsendPosition();
        delGroupsendPosition.setToAvzMGroupsend(delGroupsend);
        // グループ送信表示順位を削除
        Database.delete(delGroupsendPosition);
        // グループ送信を削除
        Database.delete(delGroupsend);

        logger.debug("groupsend deleted -> "
          + delGroupsend.getGroupsendId()
          + ".");

        // 削除件数をインクリメントする。
        deleteCounter++;
      }
      dataContext.commitChanges();

      // 表示順位の更新
      // グループ送信表示順位情報の一覧を取得
      SelectQuery<AvzMGroupsendPosition> posposQuery =
        Database.query(AvzMGroupsendPosition.class);
      posposQuery.orderAscending(AvzMGroupsendPosition.POSITION_PROPERTY);
      List<AvzMGroupsendPosition> posposList = posposQuery.fetchList();
      int counter = 1;
      for (AvzMGroupsendPosition pospos : posposList) {
        pospos.setPosition(counter);
        counter++;
      }
      dataContext.commitChanges();
      logger.debug("groupsend position updated.");

      // singletonオブジェクトのリフレッシュ
      ALEipManager.getInstance().reloadGroupSend();

      // 終了メッセージ
      logger.info("グループ送信情報更新完了　登録件数：["
        + insertCounter
        + "]　更新件数：["
        + updateCounter
        + "]　削除件数：["
        + deleteCounter
        + "]");

    } catch (FileNotFoundException e) {
      logger.warn("グループ送信情報ファイルが存在しません。");
    } catch (Exception e) {
      try {
        if (reader != null) {
          // グループ送信情報ファイルをクローズする。
          reader.close();
        }
      } catch (Exception ex) {

      }
      logger.error("グループ送信情報の更新に失敗しました。", e);
      return false;
    }
    return true;
  }
}
