package com.jiayue.ipfcst.fileupload.config;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.filter.ThresholdFilter;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy;
import ch.qos.logback.core.util.FileSize;
import ch.qos.logback.core.util.OptionHelper;
import com.jiayue.ipfcst.fileupload.util.FileConstant;
import com.jiayue.ipfcst.fileupload.util.FileUtil;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * 创建动态日志
 *
 * @author xsl
 * @version 3.0
 */
@Component
public class AppenderFactory {
  @Value("${fileupload.log.level}")
  private String logLevel;
  @Value("${fileupload.log.totalSizeCap}")
  private String totalSizeCap;
  @Value("${fileupload.log.maxFileSize}")
  private String maxFileSize;
  @Value("${fileupload.log.maxHistory}")
  private String maxHistory;

  public Logger getLogger(String name, String type, String no) {
    Logger logger = FileConstant.uploadLogMap.get(no);
    if (logger != null) {
      return logger;
    } else {
      if (logger != null) {
        return logger;
      }
      logger = getAppender(name, type, no);
      FileConstant.uploadLogMap.put(no, logger);
    }
    return logger;
  }

  /**
   * 通过传入的名字和级别，动态设置appender
   *
   * @param name
   * @return
   */
  public Logger getAppender(String name, String type, String no) {
//    Level level = Level.toLevel(this.logLevel);
//    DateFormat format = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.SIMPLIFIED_CHINESE);
    LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
    //这里是可以用来设置appender的，在xml配置文件里面，是这种形式：
    // <appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
    RollingFileAppender appender = new RollingFileAppender();
    //这里设置级别过滤器
    ThresholdFilter levelFilter = createLevelFilter(this.logLevel);
    levelFilter.start();
    appender.addFilter(levelFilter);
    // 但可以使用<contextName>设置成其他名字，用于区分不同应用程序的记录。一旦设置，不能修改。
    appender.setContext(context);
    //appender的name属性
    appender.setName("upload-" + type + "-" + name + "-" + no);
    //设置文件名
//        appender.setFile(OptionHelper.substVars("d:/eppLog/"+ name+"/" + "fileUploadLogFile-" +name+"-"+ type+".%d{yyyy-MM-dd}.%i.log",context));
    appender.setAppend(true);
    appender.setPrudent(false);
    //设置文件创建时间及大小的类
    SizeAndTimeBasedRollingPolicy policy = new SizeAndTimeBasedRollingPolicy();
    //文件名格式
    String fp = OptionHelper.substVars(FileUtil.getLogsPath() + "/" + "%d{yyyy-MM-dd}" + "/" + "upload-" + type + "-" + name + "-" + no + ".%d{yyyy-MM-dd}.%i.log", context);
    //最大日志文件大小
    policy.setMaxFileSize(FileSize.valueOf(this.maxFileSize));
    //设置文件名模式
    policy.setFileNamePattern(fp);
    //设置日志文件保留天数
    policy.setMaxHistory(Integer.parseInt(this.maxHistory));
    //总大小限制
    policy.setTotalSizeCap(FileSize.valueOf(this.totalSizeCap));
    //设置父节点是appender
    policy.setParent(appender);
    // 但可以使用<contextName>设置成其他名字，用于区分不同应用程序的记录。一旦设置，不能修改。
    policy.setContext(context);
    policy.setCleanHistoryOnStart(true);
    policy.start();
    PatternLayoutEncoder encoder = new PatternLayoutEncoder();
    //设置上下文，每个logger都关联到logger上下文，默认上下文名称为default。
    // 但可以使用<contextName>设置成其他名字，用于区分不同应用程序的记录。一旦设置，不能修改。
    encoder.setContext(context);
    //设置格式
//    encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n");
    encoder.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level - %msg%n");
    encoder.start();
    //加入下面两个节点
    appender.setRollingPolicy(policy);
    appender.setEncoder(encoder);
    appender.start();
    Logger logger = context.getLogger("upload-" + type + "-" + name + "-" + no);
    //设置不向上级打印信息
    logger.setAdditive(false);
    logger.addAppender(appender);
    return logger;
  }

  private ThresholdFilter createLevelFilter(String level) {
    ThresholdFilter levelFilter = new ThresholdFilter();
    levelFilter.setLevel(level);
//    levelFilter.setOnMatch(ACCEPT);
//    levelFilter.setOnMismatch(DENY);
    levelFilter.start();
    return levelFilter;
  }
}
