package org.apache.logging.log4j.core.impl;

import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.ThreadContext;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.util.Clock;
import org.apache.logging.log4j.core.util.ClockFactory;
import org.apache.logging.log4j.message.LoggerNameAwareMessage;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.message.TimestampMessage;

public class Log4jLogEvent implements LogEvent {
   private static final long serialVersionUID = -1351367343806656055L;
   private static final Clock clock = ClockFactory.getClock();
   private final String loggerFqcn;
   private final Marker marker;
   private final Level level;
   private final String loggerName;
   private final Message message;
   private final long timeMillis;
   private final transient Throwable thrown;
   private ThrowableProxy thrownProxy;
   private final Map<String, String> contextMap;
   private final ThreadContext.ContextStack contextStack;
   private String threadName;
   private StackTraceElement source;
   private boolean includeLocation;
   private boolean endOfBatch;

   public Log4jLogEvent() {
      this(clock.currentTimeMillis());
   }

   public Log4jLogEvent(long timestamp) {
      this("", (Marker)null, "", (Level)null, (Message)null, (Throwable)null, (Map)null, (ThreadContext.ContextStack)null, (String)null, (StackTraceElement)null, timestamp);
   }

   public Log4jLogEvent(String loggerName, Marker marker, String loggerFQCN, Level level, Message message, Throwable t) {
      this(loggerName, marker, loggerFQCN, level, message, (List)null, t);
   }

   public Log4jLogEvent(String loggerName, Marker marker, String loggerFQCN, Level level, Message message, List<Property> properties, Throwable t) {
      this(loggerName, marker, loggerFQCN, level, message, t, createMap(properties), ThreadContext.getDepth() == 0 ? null : ThreadContext.cloneStack(), (String)null, (StackTraceElement)null, message instanceof TimestampMessage ? ((TimestampMessage)message).getTimestamp() : clock.currentTimeMillis());
   }

   public Log4jLogEvent(String loggerName, Marker marker, String loggerFQCN, Level level, Message message, Throwable t, Map<String, String> mdc, ThreadContext.ContextStack ndc, String threadName, StackTraceElement location, long timestamp) {
      this(loggerName, marker, loggerFQCN, level, message, t, (ThrowableProxy)null, mdc, ndc, threadName, location, timestamp);
   }

   public static Log4jLogEvent createEvent(String loggerName, Marker marker, String loggerFQCN, Level level, Message message, Throwable thrown, ThrowableProxy thrownProxy, Map<String, String> mdc, ThreadContext.ContextStack ndc, String threadName, StackTraceElement location, long timestamp) {
      Log4jLogEvent result = new Log4jLogEvent(loggerName, marker, loggerFQCN, level, message, thrown, thrownProxy, mdc, ndc, threadName, location, timestamp);
      return result;
   }

   private Log4jLogEvent(String loggerName, Marker marker, String loggerFQCN, Level level, Message message, Throwable thrown, ThrowableProxy thrownProxy, Map<String, String> contextMap, ThreadContext.ContextStack contextStack, String threadName, StackTraceElement source, long timestamp) {
      this.threadName = null;
      this.endOfBatch = false;
      this.loggerName = loggerName;
      this.marker = marker;
      this.loggerFqcn = loggerFQCN;
      this.level = level == null ? Level.OFF : level;
      this.message = message;
      this.thrown = thrown;
      this.thrownProxy = thrownProxy;
      this.contextMap = contextMap == null ? ThreadContext.EMPTY_MAP : contextMap;
      this.contextStack = (ThreadContext.ContextStack)(contextStack == null ? ThreadContext.EMPTY_STACK : contextStack);
      this.timeMillis = message instanceof TimestampMessage ? ((TimestampMessage)message).getTimestamp() : timestamp;
      this.threadName = threadName;
      this.source = source;
      if (message != null && message instanceof LoggerNameAwareMessage) {
         ((LoggerNameAwareMessage)message).setLoggerName(loggerName);
      }

   }

   private static Map<String, String> createMap(List<Property> properties) {
      Map<String, String> contextMap = ThreadContext.getImmutableContext();
      if (contextMap != null || properties != null && !properties.isEmpty()) {
         if (properties != null && !properties.isEmpty()) {
            Map<String, String> map = new HashMap(contextMap);
            Iterator i$ = properties.iterator();

            while(i$.hasNext()) {
               Property prop = (Property)i$.next();
               if (!map.containsKey(prop.getName())) {
                  map.put(prop.getName(), prop.getValue());
               }
            }

            return Collections.unmodifiableMap(map);
         } else {
            return contextMap;
         }
      } else {
         return null;
      }
   }

   public Level getLevel() {
      return this.level;
   }

   public String getLoggerName() {
      return this.loggerName;
   }

   public Message getMessage() {
      return this.message;
   }

   public String getThreadName() {
      if (this.threadName == null) {
         this.threadName = Thread.currentThread().getName();
      }

      return this.threadName;
   }

   public long getTimeMillis() {
      return this.timeMillis;
   }

   public Throwable getThrown() {
      return this.thrown;
   }

   public ThrowableProxy getThrownProxy() {
      if (this.thrownProxy == null && this.thrown != null) {
         this.thrownProxy = new ThrowableProxy(this.thrown);
      }

      return this.thrownProxy;
   }

   public Marker getMarker() {
      return this.marker;
   }

   public String getLoggerFqcn() {
      return this.loggerFqcn;
   }

   public Map<String, String> getContextMap() {
      return this.contextMap;
   }

   public ThreadContext.ContextStack getContextStack() {
      return this.contextStack;
   }

   public StackTraceElement getSource() {
      if (this.source != null) {
         return this.source;
      } else if (this.loggerFqcn != null && this.includeLocation) {
         this.source = calcLocation(this.loggerFqcn);
         return this.source;
      } else {
         return null;
      }
   }

   public static StackTraceElement calcLocation(String fqcnOfLogger) {
      if (fqcnOfLogger == null) {
         return null;
      } else {
         StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
         StackTraceElement last = null;

         for(int i = stackTrace.length - 1; i > 0; --i) {
            String className = stackTrace[i].getClassName();
            if (fqcnOfLogger.equals(className)) {
               return last;
            }

            last = stackTrace[i];
         }

         return null;
      }
   }

   public boolean isIncludeLocation() {
      return this.includeLocation;
   }

   public void setIncludeLocation(boolean includeLocation) {
      this.includeLocation = includeLocation;
   }

   public boolean isEndOfBatch() {
      return this.endOfBatch;
   }

   public void setEndOfBatch(boolean endOfBatch) {
      this.endOfBatch = endOfBatch;
   }

   protected Object writeReplace() {
      this.getThrownProxy();
      return new Log4jLogEvent.LogEventProxy(this, this.includeLocation);
   }

   public static Serializable serialize(Log4jLogEvent event, boolean includeLocation) {
      event.getThrownProxy();
      return new Log4jLogEvent.LogEventProxy(event, includeLocation);
   }

   public static boolean canDeserialize(Serializable event) {
      return event instanceof Log4jLogEvent.LogEventProxy;
   }

   public static Log4jLogEvent deserialize(Serializable event) {
      if (event == null) {
         throw new NullPointerException("Event cannot be null");
      } else if (event instanceof Log4jLogEvent.LogEventProxy) {
         Log4jLogEvent.LogEventProxy proxy = (Log4jLogEvent.LogEventProxy)event;
         Log4jLogEvent result = new Log4jLogEvent(proxy.loggerName, proxy.marker, proxy.loggerFQCN, proxy.level, proxy.message, proxy.thrown, proxy.thrownProxy, proxy.contextMap, proxy.contextStack, proxy.threadName, proxy.source, proxy.timeMillis);
         result.setEndOfBatch(proxy.isEndOfBatch);
         result.setIncludeLocation(proxy.isLocationRequired);
         return result;
      } else {
         throw new IllegalArgumentException("Event is not a serialized LogEvent: " + event.toString());
      }
   }

   private void readObject(ObjectInputStream stream) throws InvalidObjectException {
      throw new InvalidObjectException("Proxy required");
   }

   public String toString() {
      StringBuilder sb = new StringBuilder();
      String n = this.loggerName.isEmpty() ? "root" : this.loggerName;
      sb.append("Logger=").append(n);
      sb.append(" Level=").append(this.level.name());
      sb.append(" Message=").append(this.message.getFormattedMessage());
      return sb.toString();
   }

   public boolean equals(Object o) {
      if (this == o) {
         return true;
      } else if (o != null && this.getClass() == o.getClass()) {
         Log4jLogEvent that = (Log4jLogEvent)o;
         if (this.endOfBatch != that.endOfBatch) {
            return false;
         } else if (this.includeLocation != that.includeLocation) {
            return false;
         } else if (this.timeMillis != that.timeMillis) {
            return false;
         } else {
            if (this.loggerFqcn != null) {
               if (!this.loggerFqcn.equals(that.loggerFqcn)) {
                  return false;
               }
            } else if (that.loggerFqcn != null) {
               return false;
            }

            if (this.level != null) {
               if (!this.level.equals(that.level)) {
                  return false;
               }
            } else if (that.level != null) {
               return false;
            }

            label119: {
               if (this.source != null) {
                  if (this.source.equals(that.source)) {
                     break label119;
                  }
               } else if (that.source == null) {
                  break label119;
               }

               return false;
            }

            label112: {
               if (this.marker != null) {
                  if (this.marker.equals(that.marker)) {
                     break label112;
                  }
               } else if (that.marker == null) {
                  break label112;
               }

               return false;
            }

            label105: {
               if (this.contextMap != null) {
                  if (this.contextMap.equals(that.contextMap)) {
                     break label105;
                  }
               } else if (that.contextMap == null) {
                  break label105;
               }

               return false;
            }

            if (!this.message.equals(that.message)) {
               return false;
            } else if (!this.loggerName.equals(that.loggerName)) {
               return false;
            } else {
               label95: {
                  if (this.contextStack != null) {
                     if (this.contextStack.equals(that.contextStack)) {
                        break label95;
                     }
                  } else if (that.contextStack == null) {
                     break label95;
                  }

                  return false;
               }

               label88: {
                  if (this.threadName != null) {
                     if (this.threadName.equals(that.threadName)) {
                        break label88;
                     }
                  } else if (that.threadName == null) {
                     break label88;
                  }

                  return false;
               }

               if (this.thrown != null) {
                  if (!this.thrown.equals(that.thrown)) {
                     return false;
                  }
               } else if (that.thrown != null) {
                  return false;
               }

               if (this.thrownProxy != null) {
                  if (!this.thrownProxy.equals(that.thrownProxy)) {
                     return false;
                  }
               } else if (that.thrownProxy != null) {
                  return false;
               }

               return true;
            }
         }
      } else {
         return false;
      }
   }

   public int hashCode() {
      int result = this.loggerFqcn != null ? this.loggerFqcn.hashCode() : 0;
      result = 31 * result + (this.marker != null ? this.marker.hashCode() : 0);
      result = 31 * result + (this.level != null ? this.level.hashCode() : 0);
      result = 31 * result + this.loggerName.hashCode();
      result = 31 * result + this.message.hashCode();
      result = 31 * result + (int)(this.timeMillis ^ this.timeMillis >>> 32);
      result = 31 * result + (this.thrown != null ? this.thrown.hashCode() : 0);
      result = 31 * result + (this.thrownProxy != null ? this.thrownProxy.hashCode() : 0);
      result = 31 * result + (this.contextMap != null ? this.contextMap.hashCode() : 0);
      result = 31 * result + (this.contextStack != null ? this.contextStack.hashCode() : 0);
      result = 31 * result + (this.threadName != null ? this.threadName.hashCode() : 0);
      result = 31 * result + (this.source != null ? this.source.hashCode() : 0);
      result = 31 * result + (this.includeLocation ? 1 : 0);
      result = 31 * result + (this.endOfBatch ? 1 : 0);
      return result;
   }

   // $FF: synthetic method
   Log4jLogEvent(String x0, Marker x1, String x2, Level x3, Message x4, Throwable x5, ThrowableProxy x6, Map x7, ThreadContext.ContextStack x8, String x9, StackTraceElement x10, long x11, Object x12) {
      this(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11);
   }

   private static class LogEventProxy implements Serializable {
      private static final long serialVersionUID = -7139032940312647146L;
      private final String loggerFQCN;
      private final Marker marker;
      private final Level level;
      private final String loggerName;
      private final Message message;
      private final long timeMillis;
      private final transient Throwable thrown;
      private final ThrowableProxy thrownProxy;
      private final Map<String, String> contextMap;
      private final ThreadContext.ContextStack contextStack;
      private final String threadName;
      private final StackTraceElement source;
      private final boolean isLocationRequired;
      private final boolean isEndOfBatch;

      public LogEventProxy(Log4jLogEvent event, boolean includeLocation) {
         this.loggerFQCN = event.loggerFqcn;
         this.marker = event.marker;
         this.level = event.level;
         this.loggerName = event.loggerName;
         this.message = event.message;
         this.timeMillis = event.timeMillis;
         this.thrown = event.thrown;
         this.thrownProxy = event.thrownProxy;
         this.contextMap = event.contextMap;
         this.contextStack = event.contextStack;
         this.source = includeLocation ? event.getSource() : null;
         this.threadName = event.getThreadName();
         this.isLocationRequired = includeLocation;
         this.isEndOfBatch = event.endOfBatch;
      }

      protected Object readResolve() {
         Log4jLogEvent result = new Log4jLogEvent(this.loggerName, this.marker, this.loggerFQCN, this.level, this.message, this.thrown, this.thrownProxy, this.contextMap, this.contextStack, this.threadName, this.source, this.timeMillis);
         result.setEndOfBatch(this.isEndOfBatch);
         result.setIncludeLocation(this.isLocationRequired);
         return result;
      }
   }
}
