/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.log4j.chainsaw;

import java.awt.Color;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.helpers.Constants;
import org.apache.logging.log4j.core.LogEvent;

/**
 * Wrap access to a LogEvent.  All property updates need to go through this object and not through the wrapped logging event,
 * since the properties are shared by two views of the same backing LogEvent, and logEvent itself creates a copy of passed-in properties..
 *
 * Property reads can be made on the actual LogEvent.
 */
public class LogEventWrapper {
  private final LogEvent logEvent;
  private static final int DEFAULT_HEIGHT = -1;

  private Color colorRuleBackground = ChainsawConstants.COLOR_DEFAULT_BACKGROUND;
  private Color colorRuleForeground = ChainsawConstants.COLOR_DEFAULT_FOREGROUND;
  private int markerHeight = DEFAULT_HEIGHT;
  private int msgHeight = DEFAULT_HEIGHT;

  //set to the log4jid value via setId - assumed to never change
  private int id;

  private boolean searchMatch = false;
  //a Map of event fields to Sets of string matches (can be used to render matches differently)
  Map eventMatches = new HashMap();
  private LogEventWrapper syncWrapper;
  private boolean displayed;

  public LogEventWrapper(LogEvent logEvent) {
    this.logEvent = logEvent;
  }

  public LogEventWrapper(LogEventWrapper logEventWrapper) {
    this.logEvent = logEventWrapper.getLogEvent();
    this.id = logEventWrapper.id;
    this.syncWrapper = logEventWrapper;
    logEventWrapper.syncWrapper = this;
  }

  public LogEvent getLogEvent() {
    return logEvent;
  }

  public void setProperty(String propName, String propValue) {
    logEvent.setProperty(propName, propValue);
    if (id == 0 && propName.equals(Constants.LOG4J_ID_KEY)) {
      id = Integer.parseInt(propValue);
    }
    if (syncWrapper != null && !propName.equals(ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE)) {
      syncWrapper.getLogEvent().setProperty(propName, propValue);
    }
  }

  public Object removeProperty(String propName) {
    Object result = logEvent.removeProperty(propName);
    if (syncWrapper != null && !propName.equals(ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE)) {
      syncWrapper.getLogEvent().removeProperty(propName);
    }
    return result;
  }

  public Set getPropertyKeySet() {
    return logEvent.getPropertyKeySet();
  }

  public void updateColorRuleColors(Color backgroundColor, Color foregroundColor) {
    if (backgroundColor != null && foregroundColor != null) {
      this.colorRuleBackground = backgroundColor;
      this.colorRuleForeground = foregroundColor;
      if (syncWrapper != null) {
        syncWrapper.colorRuleBackground = this.colorRuleBackground;
        syncWrapper.colorRuleForeground = this.colorRuleForeground;
      }
    } else {
      this.colorRuleBackground = ChainsawConstants.COLOR_DEFAULT_BACKGROUND;
      this.colorRuleForeground = ChainsawConstants.COLOR_DEFAULT_FOREGROUND;
      if (syncWrapper != null) {
        syncWrapper.colorRuleBackground = this.colorRuleBackground;
        syncWrapper.colorRuleForeground = this.colorRuleForeground;
      }
    }
  }

  public void evaluateSearchRule(Rule searchRule) {
    eventMatches.clear();
    searchMatch = searchRule != null && searchRule.evaluate(logEvent, eventMatches);
  }

  public Map getSearchMatches() {
    return eventMatches;
  }

  public Color getForeground() {
    return colorRuleForeground;
  }

  public Color getBackground() {
    return colorRuleBackground;
  }

  public Color getColorRuleBackground() {
    return colorRuleBackground;
  }

  public Color getColorRuleForeground() {
    return colorRuleForeground;
  }

  public boolean isSearchMatch() {
    return searchMatch;
  }

  public void setMarkerHeight(int markerHeight) {
    this.markerHeight = markerHeight;
  }

  public int getMarkerHeight() {
    return markerHeight;
  }

  public void setMsgHeight(int msgHeight) {
    this.msgHeight = msgHeight;
  }

  public int getMsgHeight() {
    return msgHeight;
  }

  public void setDisplayed(boolean b) {
    markerHeight = DEFAULT_HEIGHT;
    msgHeight = DEFAULT_HEIGHT;
    displayed = b;
  }

  public void setPreviousDisplayedEventTimestamp(long previousDisplayedEventTimeStamp) {
    setProperty(ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE, String.valueOf(logEvent.getTimeStamp() - previousDisplayedEventTimeStamp));
  }

  public boolean isDisplayed() {
    return displayed;
  }

  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }

    LogEventWrapper that = (LogEventWrapper) o;

    if (id != that.id) {
      return false;
    }

    return true;
  }

  public int hashCode() {
    return id;
  }

  public String toString() {
    return "LoggingEventWrapper - id: " + id + " background: " + getBackground() + ", foreground: " + getForeground() + ", msg: " + logEvent.getMessage();
  }
}
