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

import java.util.ArrayList;
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.cayenne.query.SelectQuery;
import org.apache.jetspeed.om.security.JetspeedUser;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.jetspeed.services.rundata.JetspeedRunData;
import org.apache.turbine.util.RunData;
import org.apache.velocity.context.Context;

import com.aimluck.commons.field.ALDateTimeField;
import com.aimluck.commons.utils.ALStringUtil;
import com.aimluck.eip.cayenne.om.portlet.EipMMailAccount;
import com.aimluck.eip.cayenne.om.portlet.EipTMail;
import com.aimluck.eip.common.ALEipConstants;
import com.aimluck.eip.mail.ALFolder;
import com.aimluck.eip.mail.ALMailFactoryService;
import com.aimluck.eip.mail.ALMailHandler;
import com.aimluck.eip.mail.ALMailMessage;
import com.aimluck.eip.mail.ALMailReceiverContext;
import com.aimluck.eip.mail.ALPop3MailReceiveThread;
import com.aimluck.eip.mail.util.ALMailUtils;
import com.aimluck.eip.mail.util.ALStaticObject;
import com.aimluck.eip.orm.DatabaseOrmService;
import com.aimluck.eip.util.ALEipUtils;
import com.aimluck.eip.webmail.WebMailFormData;

/**
 */
public class WebMailUtils {
  /** logger */
  private static final JetspeedLogger logger = JetspeedLogFactoryService
      .getLogger(WebMailUtils.class.getName());

  public static final String TAB_RECEIVE = "receive";

  public static final String TAB_SENT = "sent";

  public static final String DATE_TIME_FORMAT = ALDateTimeField.DEFAULT_DATE_TIME_FORMAT;

  public static final String CREATED_DATE_FORMAT = ALDateTimeField.DEFAULT_DATE_FORMAT;

  public final static String ACCOUNT_ID = "accountid";

  public final static String ACCOUNT_NAME = "accountname";

  public final static String MAIL_TYPE = "mailtype";

  public final static String CONFIRM_LAST_TIME = "confirmlasttime";

  public final static String LAST_TIME = "lasttime";

  public final static String UNREAD_NUM = "unread_num";

  public final static ArrayList flagList = new ArrayList();

  public static final List getMailAccountNameList(int userId) {
    DataContext dataContext = DatabaseOrmService.getInstance().getDataContext();
    SelectQuery query = new SelectQuery(EipMMailAccount.class);
    query.addCustomDbAttribute(EipMMailAccount.ACCOUNT_ID_PK_COLUMN);
    query.addCustomDbAttribute(EipMMailAccount.ACCOUNT_NAME_COLUMN);
    Expression exp = ExpressionFactory.matchExp(
        EipMMailAccount.USER_ID_PROPERTY, Integer.valueOf(userId));
    query.setQualifier(exp);

    return dataContext.performQuery(query);
  }

  /**
   * 選択したメールをローカルファイルシステムから取得する．
   * 
   * @param rundata
   * @param context
   * @return
   * @throws Exception
   */
  public static final ALMailMessage getSelectedLocalMailMessage(
      RunData rundata, Context context, int mailType) throws Exception {
    String org_id = DatabaseOrmService.getInstance().getOrgId(rundata);
    int uid = ALEipUtils.getUserId(rundata);
    int accountId = Integer.parseInt(ALEipUtils.getTemp(rundata, context,
        ACCOUNT_ID));

    String mailid = ALEipUtils.getTemp(rundata, context,
        ALEipConstants.ENTITY_ID);
    if (mailid == null || Integer.valueOf(mailid) == null) {
      // Mail IDが空の場合
      logger.debug("[Mail] Empty ID...");
      return null;
    }

    String currentTab = ALEipUtils.getTemp(rundata, context, "tab");
    int type_mail = (WebMailUtils.TAB_RECEIVE.equals(currentTab)) ? ALFolder.TYPE_RECEIVE
        : ALFolder.TYPE_SEND;
    ALMailHandler handler = ALMailFactoryService.getInstance().getMailHandler();
    ALFolder folder = handler.getALFolder(type_mail, org_id, uid, accountId);
    ALMailMessage msg = folder.getMail(Integer.valueOf(mailid));

    if (WebMailFormData.TYPE_REPLY_MAIL == mailType) {
      return ALMailUtils.getReplyMessage(msg);
    } else if (WebMailFormData.TYPE_FORWARD_MAIL == mailType) {
      return ALMailUtils.getForwardMessage(msg);
    } else {
      return msg;
    }
  }

  /**
   * 複数のメールアドレスを含む文字列の中のメールアドレス形式をチェックします。 想定メール形式は address@aimluck.com xxxyyy
   * <address@aimluck.com>
   * 
   * @param argstr
   *            複数メールアドレス
   * @param delim
   * @return
   */
  public static boolean checkAddress(String argstr, String delim) {
    String[] addresses;
    if (argstr == null || argstr.trim().length() == 0)
      return false;
    addresses = ALMailUtils.getTokens(argstr, delim);
    for (int i = 0; i < addresses.length; i++) {
      String str = addresses[i].trim();
      if (str.length() == 0)
        continue;
      if (str.charAt(str.length() - 1) == '>') {
        // 氏名付きアドレス指定 sei mei <seimei@xxx.com>
        int idx = str.indexOf("<");
        // "<"がなければエラー
        if (idx == -1) {
          return false;
        }
        String address = str.substring(idx + 1, str.length() - 1);
        if (!ALStringUtil.isCellPhoneMailAddress(address)) {
          return false;
        }
      } else {
        // アドレス指定のみ
        if (!ALStringUtil.isCellPhoneMailAddress(str)) {
          return false;
        }
      }
    }
    return true;
  }

  public static String checkUnusualChar(String str) {
    ArrayList unusualChars = new ArrayList();

    /**
     * 文字化けを起こす特殊記号 【囲み英数字／ローマ数字】①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ
     * 【単位記号】㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗㌍・㌣㌫㍊㌻㎜㎝㎞㎎㎏㏄㎡ 【省略文字／囲み文字／年号】㍻〝〟№㏍℡㊤㊥㊦㊧㊨㈱㈲㈹㍾㍽㍼∮∑∟⊿
     */
    char[] unusualchars = { '①', '②', '③', '④', '⑤', '⑥', '⑦', '⑧', '⑨', '⑩',
        '⑪', '⑫', '⑬', '⑭', '⑮', '⑯', '⑰', '⑱', '⑲', '⑳', 'Ⅰ', 'Ⅱ', 'Ⅲ', 'Ⅳ',
        'Ⅴ', 'Ⅵ', 'Ⅶ', 'Ⅷ', 'Ⅸ', 'Ⅹ', '㍉', '㌔', '㌢', '㍍', '㌘', '㌧', '㌃', '㌶',
        '㍑', '㍗', '㌍', '・', '㌣', '㌫', '㍊', '㌻', '㎜', '㎝', '㎞', '㎎', '㎏', '㏄',
        '㎡', '㍻', '〝', '〟', '№', '㏍', '℡', '㊤', '㊥', '㊦', '㊧', '㊨', '㈱', '㈲',
        '㈹', '㍾', '㍽', '㍼', '∮', '∑', '∟', '⊿' };
    int unusuallen = unusualchars.length;
    int length = str.length();
    Character cha = null;
    for (int i = 0; i < length; i++) {
      for (int j = 0; j < unusuallen; j++) {
        if (str.charAt(i) == unusualchars[j]) {
          cha = Character.valueOf(unusualchars[j]);
          if (!unusualChars.contains(cha)) {
            unusualChars.add(cha);
          }
        }
      }
    }

    StringBuffer sb = new StringBuffer();
    if (unusualChars.size() < 1) {
      return null;
    }
    length = unusualChars.size() - 1;
    for (int i = 0; i < length; i++) {
      sb.append("\"").append(unusualChars.get(i)).append("\"").append(",");
    }
    sb.append("\"").append(unusualChars.get(length)).append("\"");
    return sb.toString();
  }

  /**
   * POP3 サーバからメールを受信する。
   * 
   * @param rundata
   * @param context
   * @throws Exception
   */
  public static void receiveMailsThread(RunData rundata, Context context)
      throws Exception {
    synchronized (ALPop3MailReceiveThread.KEY_SYNCHRONIZED_LOCK) {
      JetspeedRunData jdata = (JetspeedRunData) rundata;
      JetspeedUser user = (JetspeedUser) jdata.getUser();

      int accountId = 0;
      try {
        accountId = Integer.parseInt(ALEipUtils.getTemp(rundata, context,
            ACCOUNT_ID));
      } catch (Exception ex) {
      }

      if (accountId <= 0) {
        return;
      }
      if (!ALPop3MailReceiveThread.isProcessing(user, accountId)) {
        ALStaticObject ob = ALStaticObject.getInstance();
        if (ob.receivable(accountId)) {
          // メールと接続してなければ新規にスレッドを生成
          String orgId = DatabaseOrmService.getInstance().getOrgId(rundata);
          ob.addAccountId(accountId);
          Thread mailthread = new Thread(
              new ALPop3MailReceiveThread(orgId, user, accountId,
                  ALPop3MailReceiveThread.PROCESS_TYPE_RECEIVEMAIL));
          mailthread.start();
        }
      }
    }
  }

  /**
   * POP3 サーバから新着メール数を取得する。
   * 
   * @param rundata
   * @param context
   * @throws Exception
   */
  public static int getNewMailNumThread(String orgId, JetspeedUser user,
      int accountId) throws Exception {
    // synchronized (ALPop3MailReceiveThread.KEY_SYNCHRONIZED_LOCK) {

    if (!ALPop3MailReceiveThread.isProcessing(user, accountId)) {
      // メールと接続してなければ新規にスレッドを生成
      Thread mailthread = new Thread(new ALPop3MailReceiveThread(orgId, user,
          accountId, ALPop3MailReceiveThread.PROCESS_TYPE_GET_NEWMAILNUM));
      mailthread.start();
    }

    return ALPop3MailReceiveThread.getNewMailNum(user, accountId);
    // }
  }

  /**
   * POP3 サーバと通信後の結果を取得する。
   * 
   * @param rundata
   * @param context
   * @throws Exception
   */
  public static int getStatThread(String orgId, JetspeedUser user, int accountId)
      throws Exception {
    if (ALPop3MailReceiveThread.isProcessing(user, accountId)) {
      return ALPop3MailReceiveThread.PROCESS_STAT_PROCESSING;
    } else {
      return ALPop3MailReceiveThread.getReceiveMailResult(user, accountId);
    }
  }

  /**
   * POP3 サーバと通信後の結果を取得する。
   * 
   * @param rundata
   * @param context
   * @throws Exception
   */
  public static String getStatStrThread(String orgId, JetspeedUser user,
      int accountId) throws Exception {
    return ALPop3MailReceiveThread.getReceiveMailResultStr(user, accountId);
  }

  public static int getUnreadMailNumber(RunData rundata, int userId,
      int accountId) {
    DataContext dataContext = DatabaseOrmService.getInstance().getDataContext();
    Expression exp1 = ExpressionFactory.matchExp(EipTMail.USER_ID_PROPERTY,
        Integer.valueOf(userId));
    Expression exp2 = ExpressionFactory.matchExp(EipTMail.ACCOUNT_ID_PROPERTY,
        Integer.valueOf(accountId));
    Expression exp3 = ExpressionFactory.matchExp(EipTMail.TYPE_PROPERTY, "R");
    Expression exp4 = ExpressionFactory.matchExp(EipTMail.READ_FLG_PROPERTY,
        "F");
    SelectQuery query = new SelectQuery(EipTMail.class, exp1.andExp(exp2)
        .andExp(exp3).andExp(exp4));
    List list = dataContext.performQuery(query);
    return list.size();
  }

  public static boolean isNewMessage(RunData rundata, Context context) {
    String accountId = rundata.getParameters().getString(
        WebMailUtils.ACCOUNT_ID);
    if (accountId == null || "".equals(accountId)) {
      return true;
    }
    EipMMailAccount account = ALMailUtils.getMailAccount(null, ALEipUtils
        .getUserId(rundata), Integer.parseInt(accountId));
    String orgId = DatabaseOrmService.getInstance().getOrgId(rundata);

    ALMailHandler handler = ALMailFactoryService.getInstance().getMailHandler();
    ALMailReceiverContext rcontext = ALMailUtils.getALPop3MailReceiverContext(
        orgId, account);
    int res = -1;
    try {
      res = handler.getNewMailSum(rcontext);
    } catch (Exception e) {
      res = -1;
      e.printStackTrace();
    }
    return (res > 0 ? true : false);
  }

}
