package com.plumelog.log4j.util;

import com.plumelog.core.LogMessageThreadLocal;
import com.plumelog.core.TraceMessage;
import com.plumelog.core.constant.LogMessageConstant;
import com.plumelog.core.dto.BaseLogMessage;
import com.plumelog.core.dto.RunLogMessage;
import com.plumelog.core.util.DateUtil;
import com.plumelog.core.util.GfJsonUtil;
import com.plumelog.core.util.LogExceptionStackTrace;
import com.plumelog.core.util.TraceLogMessageFactory;
import org.apache.log4j.MDC;
import org.apache.log4j.Priority;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;

import java.util.Date;
import java.util.Map;

/**
 * className：LogMessageUtil
 * description：组装日志对象
 *
 * @author Frank.chen
 * @version 1.0.0
 */
public class LogMessageUtil {

    public static BaseLogMessage getLogMessage(String appName, String srvName, LoggingEvent loggingEvent) {
        TraceMessage traceMessage = LogMessageThreadLocal.logMessageThreadLocal.get();
        String formattedMessage = getMessage(loggingEvent);
        if (formattedMessage.startsWith(LogMessageConstant.TRACE_PRE)) {
            return TraceLogMessageFactory.getTraceLogMessage(
                    traceMessage, appName, srvName, loggingEvent.timeStamp);
        }
        RunLogMessage logMessage =
                TraceLogMessageFactory.getLogMessage(appName, srvName, formattedMessage, loggingEvent.timeStamp);
        logMessage.setClassName(loggingEvent.getLoggerName());
        if (LogMessageConstant.RUN_MODEL == 1) {
            logMessage.setMethod(loggingEvent.getThreadName());
        } else {
            LocationInfo locationInfo = loggingEvent.getLocationInformation();
            String method = locationInfo.getMethodName();
            String line = locationInfo.getLineNumber();
            logMessage.setMethod(method + "(" + locationInfo.getFileName() + ":" + line + ")");
            logMessage.setDateTime(DateUtil.parseDateToStr(new Date(loggingEvent.timeStamp), DateUtil.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI));
        }
        logMessage.setLogLevel(loggingEvent.getLevel().toString());
        return logMessage;
    }

    /**
     * 扩展字段
     *
     * @param baseLogMessage
     * @param logEvent
     * @return
     */
    public static String getLogMessage(BaseLogMessage baseLogMessage, final LoggingEvent logEvent) {
        Map<String, String> mdc = MDC.getContext();
        Map<String, Object> map = GfJsonUtil.parseObject(GfJsonUtil.toJSONString(baseLogMessage), Map.class);
        if (mdc != null) {
            map.putAll(mdc);
        }
        return GfJsonUtil.toJSONString(map);
    }

    private static String getMessage(LoggingEvent logEvent) {
        if (logEvent.getLevel().toInt() == Priority.ERROR_INT) {
            String msg = "";
            if (logEvent.getThrowableInformation() != null) {
                msg = LogExceptionStackTrace.erroStackTrace(
                        logEvent.getThrowableInformation().getThrowable()).toString();
            }
            if (logEvent.getRenderedMessage() != null && logEvent.getRenderedMessage().indexOf(LogMessageConstant.DELIM_STR) > -1) {
                FormattingTuple format = MessageFormatter.format(logEvent.getRenderedMessage(), msg);
                return format.getMessage();
            }
            return logEvent.getRenderedMessage() + "\n" + msg;
        }
        return logEvent.getRenderedMessage();
    }
}
