/*
 * 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.geode.test.greplogs;

import static java.lang.System.lineSeparator;
import static java.util.regex.Pattern.compile;
import static org.apache.geode.test.greplogs.Patterns.BLANK;
import static org.apache.geode.test.greplogs.Patterns.CAUSED_BY;
import static org.apache.geode.test.greplogs.Patterns.DEBUG_WROTE_EXCEPTION;
import static org.apache.geode.test.greplogs.Patterns.ERROR_OR_MORE_LOG_LEVEL;
import static org.apache.geode.test.greplogs.Patterns.ERROR_SHORT_NAME;
import static org.apache.geode.test.greplogs.Patterns.EXCEPTION;
import static org.apache.geode.test.greplogs.Patterns.EXCEPTION_2;
import static org.apache.geode.test.greplogs.Patterns.EXCEPTION_3;
import static org.apache.geode.test.greplogs.Patterns.EXCEPTION_4;
import static org.apache.geode.test.greplogs.Patterns.IGNORED_EXCEPTION;
import static org.apache.geode.test.greplogs.Patterns.JAVA_LANG_ERROR;
import static org.apache.geode.test.greplogs.Patterns.LOG_STATEMENT;
import static org.apache.geode.test.greplogs.Patterns.MALFORMED_I18N_MESSAGE;
import static org.apache.geode.test.greplogs.Patterns.MALFORMED_LOG4J_MESSAGE;
import static org.apache.geode.test.greplogs.Patterns.RMI_WARNING;
import static org.apache.geode.test.greplogs.Patterns.RVV_BIT_SET_MESSAGE;
import static org.apache.geode.test.greplogs.Patterns.WARN_OR_LESS_LOG_LEVEL;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LogConsumer {

  /** Limit long errors to this many lines */
  private static final int ERROR_BUFFER_LIMIT = 128;

  private final String logName;
  private final Collection<Pattern> dynamicIgnoredPatterns = new ArrayList<>();
  private final Collection<Pattern> constantIgnoredPatterns = new ArrayList<>();
  private final boolean enableLogLevelThreshold;
  private final int skipLimit;

  private final Map<String, Integer> individualErrorCount = new HashMap<>();

  private boolean infoMsgFlag;
  private int eatLines;
  private boolean tmpErrFlag;
  private int tmpErrLines;
  private boolean saveFlag;
  private int savelinenum;
  private StringBuilder all;
  private int lineNumber;

  public LogConsumer(boolean enableLogLevelThreshold, Collection<Pattern> constantIgnoredPatterns,
      String logName,
      int repeatLimit) {
    this.enableLogLevelThreshold = enableLogLevelThreshold;
    this.constantIgnoredPatterns.addAll(constantIgnoredPatterns);
    this.logName = logName;
    this.skipLimit = repeatLimit;
  }

  public StringBuilder consume(CharSequence line) {
    lineNumber++;

    // IgnoredException injects lines into the log to start or end ignore periods.
    // Process those lines, then exit.
    Matcher expectedExceptionMatcher = IGNORED_EXCEPTION.matcher(line);
    if (expectedExceptionMatcher.find()) {
      expectedExceptionMatcherHandler(expectedExceptionMatcher);
      return null;
    }

    // We may optionally skip info-level logs
    if (enableLogLevelThreshold && skipLine(line)) {
      return null;
    }

    // In some case, we want to skip an extra line.
    if (eatLines != 0) {
      eatLines--;
      return null;
    }

    if (saveFlag ||
        ERROR_OR_MORE_LOG_LEVEL.matcher(line).find() ||
        isExceptionErrorOrSomeSpecialCase(line)) {
      if (!saveFlag) {
        setInstanceVariablesForSomeReason(line);
      } else {
        if (!CAUSED_BY.matcher(line).find() && matchesIgnoredPatterns(line)) {
          // reset the counters and throw it all away if it matches
          // one of the registered expected strings
          tmpErrFlag = false;
          tmpErrLines = 0;
          saveFlag = false;
        }

        // We save all the lines up to the next blank line so we're
        // looking for a blank line here
        if (BLANK.matcher(line).matches()) {
          return enforceErrorLimitsAtShortErrMatcher();
        }

        // we're still saving lines to append them on to all which contains
        // all the lines we're trying to save
        if (tmpErrFlag) {
          addErrLinesToAll(line);
        }
      }

    } else if (isWroteOrRMIWarn(line)) {
      handleWroteOrRMIWarn();
      return null;
    }

    return null;
  }

  public StringBuilder close() {
    if (saveFlag) {
      saveFlag = false;
      return enforceErrorLimit(1, all.toString(), savelinenum, logName);
    }
    return null;
  }

  private void handleWroteOrRMIWarn() {
    // unique condition for when cache server see log exception and
    // logging level is set to fine. Message looks like this:
    // [fine 2005/10/25 17:53:13.586 PDT gemfire2 Server connection from
    // hobbes.gemstone.com:34466-0xf4 nid=0x23e40f1] Server connection from
    // hobbes.gemstone.com:34466: Wrote exception:
    // org.apache.geode.cache.EntryNotFoundException: remote-destroy-key
    // also now handles a JMX WARNING

    // if we are here then the line didn't have severe or error in it and
    // didn't meet any special cases that require eating lines
    // Check for other kinds of exceptions. This is by no means inclusive
    // of all types of exceptions that could occur and some ARE missed.

    // Eat only the single EntryNotFound Exception
    eatLines = 1;
  }

  private boolean isWroteOrRMIWarn(CharSequence line) {
    return DEBUG_WROTE_EXCEPTION.matcher(line).find() || RMI_WARNING.matcher(line).find();
  }

  private boolean isExceptionErrorOrSomeSpecialCase(CharSequence line) {
    return (EXCEPTION.matcher(line).find() ||
        JAVA_LANG_ERROR.matcher(line).find() ||
        MALFORMED_I18N_MESSAGE.matcher(line).find() ||
        MALFORMED_LOG4J_MESSAGE.matcher(line).find()) &&
        !(WARN_OR_LESS_LOG_LEVEL.matcher(line).find() &&
            RVV_BIT_SET_MESSAGE.matcher(line).find());
  }

  private void addErrLinesToAll(CharSequence line) {
    if (tmpErrLines < ERROR_BUFFER_LIMIT) {
      tmpErrLines++;
      all.append(line).append(lineSeparator());
    }
    if (tmpErrLines == ERROR_BUFFER_LIMIT) {
      tmpErrLines++; // increment to prevent this line from repeating
      all.append("GrepLogs: ERROR_BUFFER_LIMIT limit reached,")
          .append(" the error was too long to display completely.").append(lineSeparator());
    }
  }

  private StringBuilder enforceErrorLimitsAtShortErrMatcher() {
    // we found a blank line so print the suspect string and reset the savetag flag
    saveFlag = false;

    Matcher shortErrMatcher = ERROR_SHORT_NAME.matcher(all.toString());
    if (shortErrMatcher.matches()) {
      String shortName = shortErrMatcher.group(1);
      Integer i = individualErrorCount.get(shortName);
      int occurrences = i == null ? 1 : i + 1;
      individualErrorCount.put(shortName, occurrences);
      return enforceErrorLimit(occurrences, all.toString(), savelinenum, logName);
    }

    // error in determining shortName, wing it
    return enforceErrorLimit(1, all.toString(), lineNumber, logName);
  }

  private void setInstanceVariablesForSomeReason(CharSequence line) {
    saveFlag = true;
    tmpErrFlag = true;
    if (matchesIgnoredPatterns(line)) {
      saveFlag = false;
      tmpErrFlag = false;
      tmpErrLines = 0;
    }
    if (tmpErrFlag) {
      tmpErrLines = 1;
      all = new StringBuilder(line);
      all.append(lineSeparator());
      savelinenum = lineNumber;
    }
  }

  private String getShortName(CharSequence line) {
    Matcher exception2Matcher = EXCEPTION_2.matcher(line);
    if (exception2Matcher.find()) {
      return exception2Matcher.group(1);
    }

    Matcher exception3Matcher = EXCEPTION_3.matcher(line);
    if (exception3Matcher.find()) {
      return exception3Matcher.group(1);
    }

    Matcher exception4Matcher = EXCEPTION_4.matcher(line);
    if (exception4Matcher.find()) {
      return exception4Matcher.group(1);
    }

    return null;
  }

  /** This method returns true if this line should be skipped. */
  private boolean skipLine(CharSequence line) {
    if (infoMsgFlag) {
      if (LOG_STATEMENT.matcher(line).find()) {
        infoMsgFlag = false;
      } else {
        if (BLANK.matcher(line).matches()) {
          infoMsgFlag = false;
        }
        return true;
      }
    }

    if (WARN_OR_LESS_LOG_LEVEL.matcher(line).find()) {
      infoMsgFlag = true;
      return true;
    }

    return false;
  }

  private void expectedExceptionMatcherHandler(MatchResult expectedExceptionMatcher) {
    if (expectedExceptionMatcher.group(1).equals("add")) {
      dynamicIgnoredPatterns.add(compile(expectedExceptionMatcher.group(2)));
    } else {
      // assume add and remove are the only choices
      dynamicIgnoredPatterns.remove(compile(expectedExceptionMatcher.group(2)));
    }
  }

  private boolean matchesIgnoredPatterns(CharSequence line) {
    return dynamicIgnoredPatterns.stream().anyMatch(p -> p.matcher(line).find()) ||
        constantIgnoredPatterns.stream().anyMatch(p -> p.matcher(line).find());
  }

  private StringBuilder enforceErrorLimit(int hits, String line, int linenum, String filename) {
    if (hits < skipLimit) {
      StringBuilder string = new StringBuilder();
      string
          .append("-----------------------------------------------------------------------")
          .append(lineSeparator())
          .append("Found suspect string in ").append(filename).append(" at line ").append(linenum)
          .append(lineSeparator()).append(lineSeparator())
          .append(line).append(lineSeparator());
      return string;
    }

    if (hits == skipLimit) {
      StringBuilder string = new StringBuilder();
      string
          .append(lineSeparator()).append(lineSeparator())
          .append("Hit occurrence limit of ").append(hits).append(" for this string.")
          .append(lineSeparator())
          .append("Further reporting of this type of error will be suppressed.")
          .append(lineSeparator());
      return string;
    }
    return null;
  }
}
