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

import java.util.Calendar;
import java.util.Date;
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 com.aimluck.eip.cayenne.om.portlet.EipMMailAccount;
import com.aimluck.eip.cayenne.om.portlet.EipTMailFilter;
import com.aimluck.eip.cayenne.om.portlet.EipTMailFolder;
import com.aimluck.eip.mail.util.ALMailUtils;
import com.aimluck.eip.orm.Database;
import com.aimluck.eip.orm.query.SelectQuery;

/**
 * メールのユーティリティクラスALMailUtilsのコピークラスです。<br>
 * insertMailAccountDataのコミット、ロールバックなどのトランザクション関連の処理をコメントアウトし、<br>
 * パラメータのrunDataとmsgListを削除しました。<br>
 * dataContextをパラメータに追加しました。
 * 
 */
public class ALBatchMailUtils {

  private static final JetspeedLogger logger =
    JetspeedLogFactoryService.getLogger(ALBatchMailUtils.class.getName());

  /** アカウントタイプを無指定 */
  public static final int ACCOUNT_TYPE_NON = 0;

  /** デフォルトアカウント */
  public static final int ACCOUNT_TYPE_DEFAULT = 1;

  /** 初期アカウント */
  public static final int ACCOUNT_TYPE_INIT = 2;

  // add by motegi start
  /** フォルダ種別：受信 */
  public static final String FOLDER_KIND_RECEIVE = "R";

  /** フォルダ種別：送信 */
  public static final String FOLDER_KIND_SEND = "S";

  /** フォルダタイプ：通常 */
  public static final String FOLDER_TYPE_NORMAL = "0";

  /** フォルダタイプ：下書き */
  public static final String FOLDER_TYPE_DRAFT = "D";

  /** フォルダタイプ：ゴミ箱 */
  public static final String FOLDER_TYPE_TRASH = "T";

  /** フォルダタイプ：迷惑メール */
  public static final String FOLDER_TYPE_SPAM = "S";

  /** フォルダタイプ：戻したメール */
  public static final String FOLDER_TYPE_RETURN = "R";

  /**
   * メールアカウント情報をデータベースに保存する．<br>
   * コミット、ロールバックをコメントアウト。<br>
   * 自己管理トランザクションへの変更とcommitChanges()をコメントアウト。<br>
   * イベントログへの出力をコメントアウト。<br>
   * dataContextをパラメータに追加。
   * 
   * @param dataContext
   * 
   * @param userId
   * @param accountName
   * @param accountType
   * @param mailAddress
   * @param mailUserName
   * @param smtpServerName
   * @param smtpPort
   * @param Pop3ServerName
   * @param pop3Port
   * @param pop3UserName
   * @param pop3Password
   * @param authSendFlag
   * @param authSendUserId
   * @param authSendUserPasswd
   * @param authReceiveFlg
   * @param delAtPop3Flg
   * @param delAtPop3BeforeDaysFlg
   * @param delAtPop3BeforeDays
   * @param nonReceivedFlg
   * @param signature
   * @param smtpEncryptionFlg
   * @param pop3EncryptionFlg
   * @return
   * @throws Exception
   * @see {@link ALMailUtils#insertMailAccountData(org.apache.turbine.util.RunData, List, int, String, int, String, String, String, int, String, int, String, String, int, String, String, int, int, int, int, String, String, int, int)}
   */
  public static boolean insertMailAccountData(
      DataContext dataContext, // RunData rundata,
      // List<String> msgList,
      int userId, String accountName, int accountType, String mailAddress,
      String mailUserName, String smtpServerName, int smtpPort,
      String oop3ServerName, int pop3Port, String pop3UserName,
      String pop3Password, int authSendFlag, String authSendUserId,
      String authSendUserPasswd, int authReceiveFlg, int delAtPop3Flg,
      int delAtPop3BeforeDaysFlg, int delAtPop3BeforeDays,
      String nonReceivedFlg, String signature, int smtpEncryptionFlg,
      int pop3EncryptionFlg) throws Exception {

    boolean enableUpdate = false;

    // add by motegi start アカウントのデフォルトフォルダに（ROOT）フォルダ追加に伴う
    // 標準のトランザクション（オートコミット）
    // Transaction baseTx = Transaction.getThreadTransaction();

    // DataContext dataContext = DataContext.getThreadDataContext();

    // 自己管理トランザクション
    // Transaction tx = Transaction.internalTransaction(DataContext
    // .getThreadDataContext() .getParentDataDomain()
    // .getTransactionDelegate());

    // 標準のトランザクションを自己管理トランザクションに置き換えます。
    // Transaction.bindThreadTransaction(tx);
    // add by motegi end

    try {
      // add by motegi start
      // トランザクション開始
      // tx.begin();
      // add by motegi end

      Date createdDate = Calendar.getInstance().getTime();

      EipMMailAccount mailAccount = null;
      mailAccount = Database.create(EipMMailAccount.class);
      mailAccount.setAccountType(Integer.toString(accountType));

      // if (accountType == ACCOUNT_TYPE_INIT) {
      // mailAccount = Database.create(EipMMailAccount.class);
      // mailAccount.setAccountType(Integer.toString(ACCOUNT_TYPE_INIT));
      // } else {
      // SelectQuery<EipMMailAccount> query =
      // Database.query(EipMMailAccount.class);
      //
      // Expression exp1 =
      // ExpressionFactory.matchExp(EipMMailAccount.USER_ID_PROPERTY, Integer
      // .valueOf(userId));
      // Expression exp2 =
      // ExpressionFactory.matchExp(
      // EipMMailAccount.ACCOUNT_TYPE_PROPERTY,
      // Integer.valueOf(ACCOUNT_TYPE_INIT));
      // EipMMailAccount account =
      // query.andQualifier(exp1).andQualifier(exp2).fetchSingle();
      //
      // if (account == null) {
      // // 新規オブジェクトモデル
      // mailAccount = Database.create(EipMMailAccount.class);
      //
      // SelectQuery<EipMMailAccount> query3 =
      // Database.query(EipMMailAccount.class);
      //
      // Expression exp3 =
      // ExpressionFactory.matchExp(
      // EipMMailAccount.USER_ID_PROPERTY,
      // Integer.valueOf(userId));
      // EipMMailAccount anotherAccount =
      // query3.andQualifier(exp3).fetchSingle();
      //
      // if (anotherAccount == null) {
      // mailAccount.setAccountType(Integer.toString(ACCOUNT_TYPE_DEFAULT));
      // } else {
      // mailAccount.setAccountType(Integer.toString(ACCOUNT_TYPE_NON));
      // }
      // } else {
      // mailAccount = account;
      // if (Integer.toString(ACCOUNT_TYPE_INIT).equals(
      // account.getAccountType())) {
      // enableUpdate = true;
      // mailAccount.setAccountType(Integer.toString(ACCOUNT_TYPE_DEFAULT));
      // } else {
      // mailAccount.setAccountType(Integer.toString(ACCOUNT_TYPE_NON));
      // }
      // }
      // }

      // ユーザーID
      mailAccount.setUserId(Integer.valueOf(userId));
      mailAccount.setAccountName(accountName);
      mailAccount.setSmtpserverName(smtpServerName);
      mailAccount.setPop3serverName(oop3ServerName);
      mailAccount.setPop3userName(pop3UserName);
      mailAccount.setPop3password(ALMailUtils
        .getEncryptedMailAccountPasswd(pop3Password.getBytes()));
      mailAccount.setMailUserName(mailUserName);
      mailAccount.setMailAddress(mailAddress);
      mailAccount.setSmtpPort(Integer.toString(smtpPort));
      mailAccount.setPop3Port(Integer.toString(pop3Port));
      mailAccount.setAuthSendFlg((short) authSendFlag);
      mailAccount.setAuthSendUserId(authSendUserId);
      if (authSendUserPasswd != null) {
        mailAccount.setAuthSendUserPasswd(ALMailUtils
          .getEncryptedMailAccountPasswd(authSendUserPasswd.getBytes()));
      }
      mailAccount.setSmtpEncryptionFlg((short) smtpEncryptionFlg);
      mailAccount.setPop3EncryptionFlg((short) pop3EncryptionFlg);
      mailAccount.setAuthReceiveFlg(Short.valueOf((short) authReceiveFlg));
      mailAccount.setDelAtPop3Flg(Integer.valueOf(delAtPop3Flg).toString());
      mailAccount.setDelAtPop3BeforeDaysFlg(Integer.valueOf(
        delAtPop3BeforeDaysFlg).toString());
      mailAccount.setDelAtPop3BeforeDays(Integer.valueOf(delAtPop3BeforeDays));
      mailAccount.setNonReceivedFlg(nonReceivedFlg);
      mailAccount.setUpdateDate(createdDate);
      mailAccount.setSignature(signature);

      if (!enableUpdate) {
        // 新規作成日
        mailAccount.setCreateDate(createdDate);
      }
      dataContext.commitChanges();

      // 以下の処理により、受信メールフォルダのトップフォルダ（”受信”）を登録する。
      EipTMailFolder rootRecvFolder = null;
      rootRecvFolder = Database.create(EipTMailFolder.class);
      rootRecvFolder.setEipMMailAccount(mailAccount);
      rootRecvFolder
        .setFolderName(EipTMailFolder.DEFAULT_ROOT_RECEIVE_FOLDER_NAME);
      rootRecvFolder.setCreateDate(createdDate);
      rootRecvFolder.setUpdateDate(createdDate);
      rootRecvFolder.setParentFolderId(0);
      rootRecvFolder.setFolderType(FOLDER_TYPE_NORMAL);
      rootRecvFolder.setFolderVolume(0L);
      rootRecvFolder.setFolderKind(FOLDER_KIND_RECEIVE);
      dataContext.commitChanges();

      EipTMailFolder mailFolder = null;

      // 以下の処理により、受信メールフォルダのデフォルトフォルダ（”受信トレイ”）を登録する。
      EipTMailFolder mailDefaultFolder = Database.create(EipTMailFolder.class);
      mailDefaultFolder.setEipMMailAccount(mailAccount);
      mailDefaultFolder.setFolderName(EipTMailFolder.DEFAULT_FOLDER_NAME);
      mailDefaultFolder.setCreateDate(createdDate);
      mailDefaultFolder.setUpdateDate(createdDate);
      mailDefaultFolder.setParentFolderId(rootRecvFolder.getFolderId());
      mailDefaultFolder.setFolderType(FOLDER_TYPE_NORMAL);
      mailDefaultFolder.setFolderVolume(0L);
      mailDefaultFolder.setFolderKind(FOLDER_KIND_RECEIVE);
      dataContext.commitChanges();

      // 以下の処理により、受信メールフォルダの戻したメールフォルダ（”戻したメール”）を登録する。
      mailFolder = Database.create(EipTMailFolder.class);
      mailFolder.setEipMMailAccount(mailAccount);
      mailFolder.setFolderName(EipTMailFolder.DEFAULT_RETURNMAIL_FOLDER_NAME);
      mailFolder.setCreateDate(createdDate);
      mailFolder.setUpdateDate(createdDate);
      mailFolder.setParentFolderId(rootRecvFolder.getFolderId());
      mailFolder.setFolderType(FOLDER_TYPE_RETURN);
      mailFolder.setFolderVolume(0L);
      mailFolder.setFolderKind(FOLDER_KIND_RECEIVE);
      dataContext.commitChanges();

      // 以下の処理により、受信メールフォルダの迷惑メールフォルダ（”迷惑メール”）を登録する。
      mailFolder = Database.create(EipTMailFolder.class);
      mailFolder.setEipMMailAccount(mailAccount);
      mailFolder.setFolderName(EipTMailFolder.DEFAULT_SPAMMAIL_FOLDER_NAME);
      mailFolder.setCreateDate(createdDate);
      mailFolder.setUpdateDate(createdDate);
      mailFolder.setParentFolderId(rootRecvFolder.getFolderId());
      mailFolder.setFolderType(FOLDER_TYPE_SPAM);
      mailFolder.setFolderVolume(0L);
      mailFolder.setFolderKind(FOLDER_KIND_RECEIVE);
      dataContext.commitChanges();

      // SPAMメール除外条件
      EipTMailFilter filter = Database.create(EipTMailFilter.class);
      filter.setEipMMailAccount(mailAccount);
      filter.setFilterName("SPAMメール除外ルール");
      filter.setEipTMailFolder(mailFolder);
      filter.setFilterString(ALMailUtils.excludeSpamKey);
      filter.setFilterType("S");
      filter.setSortOrder(1);
      dataContext.commitChanges();

      // 以下の処理により、受信メールフォルダのごみ箱フォルダ（”ごみ箱”）を登録する。
      mailFolder = Database.create(EipTMailFolder.class);
      mailFolder.setEipMMailAccount(mailAccount);
      mailFolder.setFolderName(EipTMailFolder.DEFAULT_TRASH_FOLDER_NAME);
      mailFolder.setCreateDate(createdDate);
      mailFolder.setUpdateDate(createdDate);
      mailFolder.setParentFolderId(rootRecvFolder.getFolderId());
      mailFolder.setFolderType(FOLDER_TYPE_TRASH);
      mailFolder.setFolderVolume(0L);
      mailFolder.setFolderKind(FOLDER_KIND_RECEIVE);
      dataContext.commitChanges();

      // 以下の処理により、送信メールフォルダのトップフォルダ（”送信”）を登録する。
      EipTMailFolder rootSendFolder = null;
      rootSendFolder = Database.create(EipTMailFolder.class);
      rootSendFolder.setEipMMailAccount(mailAccount);
      rootSendFolder
        .setFolderName(EipTMailFolder.DEFAULT_ROOT_SEND_FOLDER_NAME);
      rootSendFolder.setCreateDate(createdDate);
      rootSendFolder.setUpdateDate(createdDate);
      rootSendFolder.setParentFolderId(0);
      rootSendFolder.setFolderType(FOLDER_TYPE_NORMAL);
      rootSendFolder.setFolderVolume(0L);
      rootSendFolder.setFolderKind(FOLDER_KIND_SEND);
      dataContext.commitChanges();

      // 以下の処理により、送信メールフォルダのデフォルトフォルダ（”送信トレイ”）を登録する。
      EipTMailFolder mailDefaultSendFolder =
        Database.create(EipTMailFolder.class);
      mailDefaultSendFolder.setEipMMailAccount(mailAccount);
      mailDefaultSendFolder
        .setFolderName(EipTMailFolder.DEFAULT_SEND_FOLDER_NAME);
      mailDefaultSendFolder.setCreateDate(createdDate);
      mailDefaultSendFolder.setUpdateDate(createdDate);
      mailDefaultSendFolder.setParentFolderId(rootSendFolder.getFolderId());
      mailDefaultSendFolder.setFolderType(FOLDER_TYPE_NORMAL);
      mailDefaultSendFolder.setFolderVolume(0L);
      mailDefaultSendFolder.setFolderKind(FOLDER_KIND_SEND);
      dataContext.commitChanges();

      // 以下の処理により、送信メールフォルダのごみ箱フォルダ（”ごみ箱”）を登録する。
      mailFolder = Database.create(EipTMailFolder.class);
      mailFolder.setEipMMailAccount(mailAccount);
      mailFolder.setFolderName(EipTMailFolder.DEFAULT_TRASH_FOLDER_NAME);
      mailFolder.setCreateDate(createdDate);
      mailFolder.setUpdateDate(createdDate);
      mailFolder.setParentFolderId(rootSendFolder.getFolderId());
      mailFolder.setFolderType(FOLDER_TYPE_TRASH);
      mailFolder.setFolderVolume(0L);
      mailFolder.setFolderKind(FOLDER_KIND_SEND);
      dataContext.commitChanges();

      // 以下の処理により、送信メールフォルダのごみ箱フォルダ（”下書き”）を登録する。
      mailFolder = Database.create(EipTMailFolder.class);
      mailFolder.setEipMMailAccount(mailAccount);
      mailFolder.setFolderName(EipTMailFolder.DEFAULT_DRAFT_FOLDER_NAME);
      mailFolder.setCreateDate(createdDate);
      mailFolder.setUpdateDate(createdDate);
      mailFolder.setParentFolderId(rootSendFolder.getFolderId());
      mailFolder.setFolderType(FOLDER_TYPE_DRAFT);
      mailFolder.setFolderVolume(0L);
      mailFolder.setFolderKind(FOLDER_KIND_SEND);
      dataContext.commitChanges();

      // デフォルトのフォルダID
      mailAccount.setDefaultFolderId(mailDefaultFolder.getFolderId());
      mailAccount.setDefaultSendFolderId(mailDefaultSendFolder.getFolderId());
      mailAccount.setCreateDate(createdDate);

      dataContext.commitChanges();

      // コミット
      // Database.commit();

      // イベントログに保存
      /*
       * ALEventlogFactoryService.getInstance().getEventlogHandler().log(
       * mailAccount.getAccountId(),
       * ALEventlogConstants.PORTLET_TYPE_WEBMAIL_ACCOUNT,
       * mailAccount.getAccountName());
       */
      // change start
      // } catch (Throwable t) {
    } catch (Exception e) {
      // change end
      // Database.rollback();
      // change start
      // logger.error(t);
      // return false;
      throw e;
      // change end

      // add by motegi start
    } finally {
      // 自己管理トランザクションを標準のトランザクションに戻します。
      // Transaction.bindThreadTransaction(baseTx);
      // add by motegi end
    }
    return true;
  }

  /**
   * デフォルトのメールアカウントの情報をデータベースから所得する．
   * 
   * @param userId
   * @return
   */
  public static EipMMailAccount getPrimaryEipMMailAccount(int userId,
      String email) {
    try {
      SelectQuery<EipMMailAccount> query1 =
        Database.query(EipMMailAccount.class);

      Expression exp11 =
        ExpressionFactory.matchExp(EipMMailAccount.USER_ID_PROPERTY, Integer
          .valueOf(userId));
      Expression exp12 =
        ExpressionFactory.matchExp(
          EipMMailAccount.ACCOUNT_TYPE_PROPERTY,
          ACCOUNT_TYPE_DEFAULT);
      EipMMailAccount account =
        query1.andQualifier(exp11).andQualifier(exp12).fetchSingle();

      if (account == null) {
        SelectQuery<EipMMailAccount> query2 =
          Database.query(EipMMailAccount.class);

        Expression exp21 =
          ExpressionFactory.matchExp(EipMMailAccount.USER_ID_PROPERTY, Integer
            .valueOf(userId));
        Expression exp22 =
          ExpressionFactory.matchExp(
            EipMMailAccount.MAIL_ADDRESS_PROPERTY,
            email);
        account = query2.andQualifier(exp21).andQualifier(exp22).fetchSingle();
      }
      return account;
    } catch (Exception ex) {
      logger.error("Exception", ex);
      return null;
    }
  }

}
