package jp.co.imtt;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.logging.FileHandler;
import java.io.IOException;
import java.lang.reflect.Method;

import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.jetspeed.services.resources.JetspeedResources;

public class ImwareLogger{

  /** Jetspeed logger */
  private static final JetspeedLogger jetspeedLogger = JetspeedLogFactoryService
      .getLogger(ImwareLogger.class.getName());
  
  // ログファイルの格納フォルダのパス
  private final String AIPO_HOME
    = JetspeedResources.getString("aipo.home", "");
  
  private final String LOG_FOLDER = AIPO_HOME + "/logs";
  private final String CONF_FOLDER = AIPO_HOME + "/conf";
  
  private static Logger logger = null;

  private static Date today = null;
  
  //private static Object lock = new Object();
  
  private String portlet = "";
  
  private String className = this.getClass().getCanonicalName();
  
  public ImwareLogger(String portlet) {
    //if (logger == null) {
      //synchronized (lock) {
        if (logger == null) {

          /*
           * try { LogManager.getLogManager().readConfiguration(
           * ImwareLogger.class.getResourceAsStream(CONF_FOLDER +
           * "/imwarelogger.properties")); } catch(IOException ex){ }
           */
          // ロガーが存在しなければ、ロガーを取得する。
          Date now = new Date();
          logger = getLogger(className, now);

          // System.out.println("★ ImwareLogger() make logger :" + className + "." + formatDate(now));
        }
     // }
    //}
    // ポートレット名設定
    if (portlet != null) {
      this.portlet = portlet;
    }
  }
   
  /**
   * debugレベルのログを出力します
   * @param message
   */
  public void debug(String message){
    log(Level.CONFIG, message);
  }
  
  /**
   * infoレベルのログを出力します
   * @param message
   */
  public void info(String message){
    log(Level.INFO, message);
  }
  
  /**
   * warnレベルのログを出力します
   * @param message
   */
  public void warn(String message){
    log(Level.WARNING, message);
  }
  
  /**
   * errorレベルのログを出力します
   * @param message
   */
  public void error(String message){
    log(Level.SEVERE, message);
  }
  
  /**
   * errorレベルのログを出力します
   * @param message
   * @param ex
   */
  public void error(String message, Exception ex){
    log(Level.SEVERE, message, ex);
  }
  
  public void error(Exception ex){
    log(Level.SEVERE, "Exception", ex);
  }
  
  /**
   * ログを出力します。
   * @param level
   * @param message
   */
  public void log(Level level, String message){
    Date now = new Date();
    // 日付が変わったら、ロガーと出力先ログファイルを変更
    //if (!sameDay(today, now)) {
      //synchronized (lock) {
        if (!sameDay(today, now)) {
          logger = getLogger(className, now);
          // System.out.println("★ log(2) make logger :" + className + "." + formatDate(now));
        }
      //}
    //}
    if(logger==null) return;
    // ログにポートレット名を追加
    message = "[portlet]" + portlet + "\t" + message;
    logger.log(level, message);
  }
   
  /**
   * ログを出力します
   * @param level
   * @param message
   * @param ex
   */
  public void log(Level level, String message, Exception ex){
    Date now = new Date();
    // 日付が変わったら、ロガーと出力先ログファイルを変更
    //if (!sameDay(today, now)) {
      //synchronized (lock) {
        if (!sameDay(today, now)) {
          logger = getLogger(className, now);
          // System.out.println("★ log(3) make logger :" + className + "." + formatDate(now));
        }
      //}
    //}
    if(logger==null) return;
    // ログにポートレット名を追加
    message = "[portlet]" + portlet + "\t" + message;
    logger.log(level, message, ex);
  }
  
  /**
   * logger を取得します。
   * @return FileHandler
   */
  private synchronized Logger getLogger(String className, Date date){
    try {
      Logger logger = null;
      
      if(date == null) return null;
      
      // 同一の名前のロガーが存在するか確認
      logger = LogManager.getLogManager().getLogger(
          getLoggerName(className, date));

      if (logger != null) {
        // 存在すれば、既存のロガーを返す。
        return logger;
      } else {
        // 存在しなければ、新規でロガーを作成する。
        logger = Logger.getLogger(getLoggerName(className, date));

        String filename = getLogFileName(date);
        if (filename == null) {
          return null;
        }
        // 出力ファイルを追加モードで指定する
        FileHandler fh = new FileHandler(filename, true);
        // 出力フォーマットを指定する
        // fh.setFormatter(new java.util.logging.SimpleFormatter());
        fh.setFormatter(new jp.co.imtt.ImwareFormatter());
        logger.addHandler(fh);
        // 日付を変更
        this.today = date;
        return logger;
      }
    } catch (IOException e) {
      e.printStackTrace();
      //logger.log(Level.SEVERE, "[portlet]imwarelogger\tException", e);
      jetspeedLogger.error("Exception", e);
      return null;
    }
  }
  
  /**
   * ログファイル名を取得します
   * @return String
   */
  private String getLogFileName(Date date){
    String filename = null;
    try {
      //Date date = new Date();
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy'-'MM'-'dd");
      return LOG_FOLDER + "/imware_" + sdf.format(date) + ".%u.log";
    } catch (Exception e) {
      e.printStackTrace();
      //logger.log(Level.SEVERE, "[portlet]imwarelogger\tException", e);
      jetspeedLogger.error("Exception", e);
      return null;
    }
  }
  
  /**
   * 同一の日付であるか判断します
   * @param date1
   * @param date2
   * @return　boolean
   */
  private boolean sameDay(Date date1, Date date2) {
    try {
      if (date1 == null || date2 == null)
        return false;
      
      String stringDate1 = formatDate(date1);
      String stringDate2 = formatDate(date2);
      if (stringDate1 == null || stringDate2 == null
          || "".equals(stringDate1) || "".equals(stringDate2))
        return false;
      return stringDate1.equals(stringDate2);
    } catch (Exception e) {
      e.printStackTrace();
      //logger.log(Level.SEVERE, "[portlet]imwarelogger\tException", e);
      jetspeedLogger.error("Exception", e);
      return false;
    }
  }
  
  /**
   * 日付をyyyy-MM-dd形式にフォーマットします
   * @param date
   * @return String
   */
  private String formatDate(Date date){
    try {
      if (date == null) return "";
      SimpleDateFormat sdf = new SimpleDateFormat("yyyy'-'MM'-'dd");
      return sdf.format(date);
    } catch (Exception e) {
      e.printStackTrace();
      //logger.log(Level.SEVERE, "[portlet]imwarelogger\tException", e);
      jetspeedLogger.error("Exception", e);
      return "";
    }
  }
  
  /**
   * ロガー名を取得します
   * @param className
   * @param date
   * @return　String
   */
  private String getLoggerName(String className, Date date){
    return className + "." + formatDate(date);
  }
  
}
