/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt'
 * which is part of this source code package
 */

package com.scytl.slogger.validator;

import static java.util.Objects.requireNonNull;

import org.apache.log4j.Logger;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;

import java.util.Objects;

/**
 * Extension of {@link LoggingEvent} to be used in the secure log validation.
 * 
 * @author aakimov
 */
@SuppressWarnings("serial")
public final class ValidatorLoggingEvent extends LoggingEvent {
  private final LocationInfo locationInformation;
  private final String ndc;
  private final String threadName;
  private final boolean malformed;

  private ValidatorLoggingEvent(String loggerName, long timeStamp, org.apache.log4j.Level level,
      String message, LocationInfo locationInformation, String ndc, String threadName,
      boolean malformed) {
    super(null, Logger.getLogger(loggerName), timeStamp, level, message, null);
    this.locationInformation = locationInformation;
    this.ndc = ndc;
    this.threadName = threadName;
    this.malformed = malformed;
  }

  /**
   * Creates a new malformed instance from a given line.
   * 
   * @param line the line
   * @return the instance.
   */
  public static ValidatorLoggingEvent newMalformedInstance(String line) {
    return new ValidatorLoggingEvent("", 0L, Level.ERROR, line, null, null, null, true);
  }

  @Override
  public LocationInfo getLocationInformation() {
    return locationInformation;
  }

  @Override
  public String getNDC() {
    return ndc;
  }

  @Override
  public String getRenderedMessage() {
    return Objects.toString(getMessage());
  }


  @Override
  public String getThreadName() {
    return threadName;
  }

  /**
   * Returns whether the event is malformed. If the returned value is {@code true} then the only
   * meaningful property is {@link #getRenderedMessage()}.
   * 
   * @return the event is malformed
   */
  public boolean isMalformed() {
    return malformed;
  }

  /**
   * Builder for creating well-formed {@link ValidatorLoggingEvent} instances.
   * 
   * @author aakimov
   */
  public static final class WellFormedInstanceBuilder {
    private String loggerName;
    private long timeStamp;
    private org.apache.log4j.Level level;
    private String message;
    private LocationInfo locationInformation;
    private String ndc;
    private String threadName;

    /**
     * Builds a new {@link ValidatorLoggingEvent} instance.
     * 
     * @return a new {@link ValidatorLoggingEvent} instance.
     */
    public ValidatorLoggingEvent build() {
      requireNonNull(loggerName, "Logger name is null.");
      requireNonNull(level, "Level is null.");
      requireNonNull(message, "Message is null.");
      requireNonNull(locationInformation, "Location information is null.");
      return new ValidatorLoggingEvent(loggerName, timeStamp, level, message, locationInformation,
          ndc, threadName, false);
    }

    /**
     * Sets the level.
     * 
     * @param level the level
     * @return this instance.
     */
    public WellFormedInstanceBuilder setLevel(org.apache.log4j.Level level) {
      this.level = level;
      return this;
    }

    /**
     * Sets the location information.
     * 
     * @param locationInformation the location information
     * @return this instance.
     */
    public WellFormedInstanceBuilder setLocationInformation(LocationInfo locationInformation) {
      this.locationInformation = locationInformation;
      return this;
    }

    /**
     * Sets the logger name.
     * 
     * @param loggerName the logger name
     * @return this instance.
     */
    public WellFormedInstanceBuilder setLoggerName(String loggerName) {
      this.loggerName = loggerName;
      return this;
    }

    /**
     * Sets the message
     * 
     * @param message the message
     * @return this instance.
     */
    public WellFormedInstanceBuilder setMessage(String message) {
      this.message = message;
      return this;
    }

    /**
     * Sets the NDC.
     * 
     * @param ndc the NDC
     * @return this instance.
     */
    public WellFormedInstanceBuilder setNdc(String ndc) {
      this.ndc = ndc;
      return this;
    }

    /**
     * Sets the thread name
     * 
     * @param threadName the thread name
     * @return this instance.
     */
    public WellFormedInstanceBuilder setThreadName(String threadName) {
      this.threadName = threadName;
      return this;
    }

    /**
     * Sets the timestamp.
     * 
     * @param timeStamp the timestamp
     * @return this instance.
     */
    public WellFormedInstanceBuilder setTimeStamp(long timeStamp) {
      this.timeStamp = timeStamp;
      return this;
    }
  }
}
