/*
 * 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.HYDRA_MASTER_LOCATORS_WILDCARD;
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()) &&
        !(HYDRA_MASTER_LOCATORS_WILDCARD.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;
  }
}
