/*
 * Copyright (c) 2006 System Integrator Corporation.
 *                 All Rights Reserved.
 *
 * (8.1.0 ST2225 新規作成)
 */
package jp.co.sint.tools;

import java.util.HashMap;

import jp.co.sint.config.SIConfig;

import org.apache.log4j.Category;

/**
 * 大量送信チェッククラス
 * @author watanabe
 */
public final class SIMassiveSendChecker {

  //連続送信を許可する回数
  private static final int  COUNT_MAX = 5;
  //連続送信回数カウンタの保持期間
  private static final long TIME_OUT = 300000; //5 minutes

  private static Category log = Category.getInstance(SIConfig.SILOG4J_WEBSHOP_CATEGORY_NAME);
  private static HashMap map = new HashMap();

  /**
   * コンストラクタ(インスタンス生成不可)
   */
  private SIMassiveSendChecker() {
  }

  /**
   * 指定されたメールアドレスへの連続投稿をチェックします。
   * @param lEmail チェック対象メールアドレス
   * @return 送信が許可される場合はtrue
   */
  public static synchronized boolean check(String lEmail) {
    boolean result = false;
    if (SIUtil.isNotNull(lEmail)) {

      //以前の履歴がある場合
      if (map.containsKey(lEmail)) {
        History history = (History) map.get(lEmail);
        long now = System.currentTimeMillis();

        //タイムアウトしたらカウンタをリセット
        if (now - history.timestamp > TIME_OUT) {
          history.count = 1;
          history.timestamp = now;
          //ログへ出力
          log.warn("Count Reset:{email="
                  + lEmail + ",count="+ history.count + "}");
          return true;
        }

        //タイムスタンプ更新とカウントアップ
        history.timestamp = now;
        history.count++;

        //連続投稿が検知されたら警告ログを出力
        result = history.count <= COUNT_MAX;
        if (result == false) {
          log.warn("Detected Continuous Sending{email="
                  + lEmail + ", count=" + history.count + "}");
        }

      } else {
        //初回は履歴を新規作成
        map.put(lEmail, new History(1, System.currentTimeMillis()));
        result = true;
      }
    }
    return result;
  }

  /**
   * 内部用履歴管理クラス：(回数とタイムスタンプを管理)
   */
  private static class History {
    /** タイムスタンプ */
    public long timestamp;
    /** 投稿回数 */
    public int count;
    /** 新しい */
    public History(int lCount, long lTimestamp) {
      this.count = lCount;
      this.timestamp = lTimestamp;
    }
  }
}