/*
 * 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.Arrays;
import java.util.HashMap;
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.AvzMUserGroupsend;
import com.aimluck.eip.cayenne.om.security.TurbineUser;
import com.aimluck.eip.orm.Database;
import com.aimluck.eip.orm.query.SelectQuery;

/**
 * <HR>
 * <p>
 * 
 * グループ送信割当情報のファイルを読み込み、Aipoのデータベースにインポートします。<br>
 * インポート前にテーブルごとデータをクリアします。<br>
 * <P>
 * <HR>
 * <P>
 */
public class UserGroupsendImporter {

  /** ロガー */
  private static final JetspeedLogger logger =
    JetspeedLogFactoryService.getLogger(UserGroupsendImporter.class.getName());

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

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

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

    int insertCounter = 0;
    BufferedReader reader = null;

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

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

      // グループ送信割当情報の全レコードを抽出し、削除する。
      SelectQuery<AvzMUserGroupsend> groupsendUserQuery =
        Database.query(AvzMUserGroupsend.class);
      groupsendUserQuery
        .orderAscending(AvzMUserGroupsend.GROUPSEND_ID_PROPERTY);
      List<AvzMUserGroupsend> delList = groupsendUserQuery.fetchList();

      for (AvzMUserGroupsend delGroupSendUser : delList) {
        // ユーザーIDがシステム用データのユーザーID（1,2,3）と一致する場合はスキップ
        if (Arrays.binarySearch(BatchUtils.SystemUserId, delGroupSendUser
          .getUserId()
          .toString()) >= 0) {
          continue;
        }

        Database.delete(delGroupSendUser);
        dataContext.commitChanges();
      }

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

      List<HashMap<String, String>> groupsendUserFileList =
        new ArrayList<HashMap<String, String>>();

      // 最終行まで読み込む
      String line = "";
      while ((line = reader.readLine()) != null) {
        String[] s = line.split(BatchUtils.SEPARATOR);
        String groupSendUserCode = BatchUtils.trimDoubleQuotes(s[0]); // グループ送信コード
        String groupSendLoginId = BatchUtils.trimDoubleQuotes(s[1]); // ログインID

        logger.debug("groupsend user -> "
          + groupSendLoginId
          + ", code-> "
          + groupSendUserCode
          + ".");

        // 処理済みグループ送信割当に存在するか判定
        // 存在する場合はコード重複としてスキップ
        HashMap<String, String> map = new HashMap<String, String>();
        map.put(groupSendLoginId, groupSendUserCode);
        if (groupsendUserFileList.contains(map)) {
          logger.warn("[更新不可]処理済みのグループ送信コード,ログインIDのためスキップします。　" + line);
          continue;
        }

        // ログインIDでユーザー情報を検索する
        SelectQuery<TurbineUser> userQuery = Database.query(TurbineUser.class);
        // 検索条件：ログイン名と一致
        Expression userExp =
          ExpressionFactory.matchExp(
            TurbineUser.LOGIN_NAME_PROPERTY,
            groupSendLoginId);
        userQuery.setQualifier(userExp); // 検索実行
        TurbineUser user = userQuery.fetchSingle();

        // <ユーザー情報>件数が0件の場合、ログを出力し、次のレコードの処理を行う。
        if (user == null) {
          logger.warn("[更新不可]ユーザーが存在しません。　" + line);
          continue;
        }

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

        // <グループ送信情報>件数が0件の場合、ログを出力し、次のレコードの処理を行う。
        if (groupSendList.size() == 0) {
          logger.warn("[更新不可]グループ送信情報が存在しません。　" + line);
          continue;
        }

        logger.debug("groupsend user -> "
          + groupSendLoginId
          + ", code-> "
          + groupSendUserCode
          + " insert start.");

        // <グループ送信割当情報>を登録する。
        AvzMUserGroupsend groupSendUser =
          Database.create(AvzMUserGroupsend.class);
        groupSendUser.setUserId(user.getUserId());
        groupSendUser.setGroupsendId(groupSendList.get(0).getGroupsendId());
        dataContext.commitChanges();

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

        // グループ送信コード、ログインIDのマップを<グループ送信割当ファイル配列>に追加で格納する。
        groupsendUserFileList.add(map);
      }

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

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

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

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