/*
 * 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.cassandra.distributed.api;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public interface LogAction
{
    /**
     * @return current position of the iterator
     * @see LogAction#grep(long, String)
     * @see LogAction#watchFor(long, String)
     */
    long mark();

    LineIterator match(long startPosition, Predicate<String> fn);

    default LineIterator match(Predicate<String> fn){
        return match(Internal.DEFAULT_START_POSITION, fn);
    }

    default LogResult<List<String>> watchFor(long startPosition, Duration timeout, Predicate<String> fn) throws TimeoutException
    {
        long nowNanos = System.nanoTime();
        long deadlineNanos = nowNanos + timeout.toNanos();
        long previousPosition = startPosition;
        List<String> matches = new ArrayList<>();
        while (System.nanoTime() <= deadlineNanos)
        {
            if (previousPosition == mark())
            {
                // still matching... wait a bit
                Internal.sleepUninterruptibly(1, TimeUnit.SECONDS);
                continue;
            }
            // position not matching, try to read
            try (LineIterator it = match(previousPosition, fn))
            {
                while (it.hasNext())
                    matches.add(it.next());
                if (!matches.isEmpty())
                    return new BasicLogResult<>(it.mark(), matches);
                previousPosition = it.mark();
            }
        }
        throw new TimeoutException();
    }

    default LogResult<List<String>> watchFor(Duration timeout, Predicate<String> fn) throws TimeoutException {
        return watchFor(Internal.DEFAULT_START_POSITION, timeout, fn);
    }

    default LogResult<List<String>> watchFor(Predicate<String> fn) throws TimeoutException {
        return watchFor(Internal.DEFAULT_START_POSITION, Internal.DEFAULT_TIMEOUT, fn);
    }

    default LogResult<List<String>> watchFor(long startPosition, Duration timeout, List<Pattern> patterns) throws TimeoutException
    {
        return watchFor(startPosition, timeout, Internal.regexPredicate(patterns));
    }

    default LogResult<List<String>> watchFor(Duration timeout, List<Pattern> patterns) throws TimeoutException
    {
        return watchFor(Internal.DEFAULT_START_POSITION, timeout, Internal.regexPredicate(patterns));
    }

    default LogResult<List<String>> watchFor(long startPosition, List<Pattern> patterns) throws TimeoutException
    {
        return watchFor(startPosition, Internal.DEFAULT_TIMEOUT, Internal.regexPredicate(patterns));
    }

    default LogResult<List<String>> watchFor(List<Pattern> patterns) throws TimeoutException
    {
        return watchFor(Internal.DEFAULT_START_POSITION, Internal.DEFAULT_TIMEOUT, Internal.regexPredicate(patterns));
    }

    default LogResult<List<String>> watchFor(long startPosition, Duration timeout, Pattern pattern) throws TimeoutException
    {
        return watchFor(startPosition, timeout, Internal.regexPredicate(pattern));
    }

    default LogResult<List<String>> watchFor(Duration timeout, Pattern pattern) throws TimeoutException
    {
        return watchFor(Internal.DEFAULT_START_POSITION, timeout, Internal.regexPredicate(pattern));
    }

    default LogResult<List<String>> watchFor(long startPosition, Pattern pattern) throws TimeoutException
    {
        return watchFor(startPosition, Internal.DEFAULT_TIMEOUT, Internal.regexPredicate(pattern));
    }

    default LogResult<List<String>> watchFor(Pattern pattern) throws TimeoutException
    {
        return watchFor(Internal.DEFAULT_START_POSITION, Internal.DEFAULT_TIMEOUT, Internal.regexPredicate(pattern));
    }

    default LogResult<List<String>> watchFor(long startPosition, Duration timeout, String pattern) throws TimeoutException
    {
        return watchFor(startPosition, timeout, Internal.regexPredicate(pattern));
    }

    default LogResult<List<String>> watchFor(Duration timeout, String pattern) throws TimeoutException
    {
        return watchFor(Internal.DEFAULT_START_POSITION, timeout, Internal.regexPredicate(pattern));
    }

    default LogResult<List<String>> watchFor(long startPosition, String pattern) throws TimeoutException
    {
        return watchFor(startPosition, Internal.DEFAULT_TIMEOUT, Internal.regexPredicate(pattern));
    }

    default LogResult<List<String>> watchFor(String pattern) throws TimeoutException
    {
        return watchFor(Internal.DEFAULT_START_POSITION, Internal.DEFAULT_TIMEOUT, Internal.regexPredicate(pattern));
    }

    default LogResult<List<String>> watchFor(long startPosition, Duration timeout, String pattern, String... others) throws TimeoutException
    {

        return watchFor(startPosition, timeout, Internal.regexPredicate(pattern, others));
    }

    default LogResult<List<String>> watchFor(Duration timeout, String pattern, String... others) throws TimeoutException
    {

        return watchFor(Internal.DEFAULT_START_POSITION, timeout, Internal.regexPredicate(pattern, others));
    }

    default LogResult<List<String>> watchFor(long startPosition, String pattern, String... others) throws TimeoutException
    {

        return watchFor(startPosition, Internal.DEFAULT_TIMEOUT, Internal.regexPredicate(pattern, others));
    }

    default LogResult<List<String>> watchFor(String pattern, String... others) throws TimeoutException
    {
        return watchFor(Internal.DEFAULT_START_POSITION, Internal.DEFAULT_TIMEOUT, Internal.regexPredicate(pattern, others));
    }

    default LogResult<List<String>> grep(long startPosition, Predicate<String> fn)
    {
        try (LineIterator it = match(startPosition, fn))
        {
            return new BasicLogResult<>(it.mark(), Internal.collect(it));
        }
    }

    default LogResult<List<String>> grep(Predicate<String> fn)
    {
        return grep(Internal.DEFAULT_START_POSITION, fn);
    }

    default LogResult<List<String>> grep(long startPosition, List<Pattern> patterns)
    {
        return grep(startPosition, Internal.regexPredicate(patterns));
    }

    default LogResult<List<String>> grep(List<Pattern> patterns)
    {
        return grep(Internal.DEFAULT_START_POSITION, Internal.regexPredicate(patterns));
    }

    default LogResult<List<String>> grep(long startPosition, Pattern pattern)
    {
        return grep(startPosition, Internal.regexPredicate(pattern));
    }

    default LogResult<List<String>> grep(Pattern pattern)
    {
        return grep(Internal.DEFAULT_START_POSITION, Internal.regexPredicate(pattern));
    }

    default LogResult<List<String>> grep(long startPosition, String pattern)
    {
        return grep(startPosition, Internal.regexPredicate(pattern));
    }

    default LogResult<List<String>> grep(String pattern)
    {
        return grep(Internal.DEFAULT_START_POSITION, Internal.regexPredicate(pattern));
    }

    default LogResult<List<String>> grep(long startPosition, String pattern, String... others)
    {

        return grep(startPosition, Internal.regexPredicate(pattern, others));
    }

    default LogResult<List<String>> grep(String pattern, String... others)
    {
        return grep(Internal.DEFAULT_START_POSITION, Internal.regexPredicate(pattern, others));
    }

    /**
     * Attempt to find all errors in the log.  This method is different from {@code grep("^ERROR")} as it will also
     * attempt to stitch the exception stack trace into a single line.
     *
     * This method is modeled after python dtests's grep_for_errors and matches the semantics there.
     *
     * @param startPosition to grep from
     * @param exceptionPattern for WARN logs to check if they might have an exception
     * @return result of all found exceptions, with stitched errors
     */
    default LogResult<List<String>> grepForErrors(long startPosition, Pattern exceptionPattern)
    {
        Objects.requireNonNull(exceptionPattern, "exceptionPattern");

        Pattern logLevelPattern = Internal.LOG_LEVEL_PATTERN;
        Function<String, String> extractLogLevel = line -> {
            Matcher matcher = logLevelPattern.matcher(line);
            if (!matcher.find())
                return null;
            return matcher.group(1);
        };
        List<String> matches = new ArrayList<>();
        try (LineIterator it = match(startPosition, ignore -> true))
        {
            StringBuilder lineBuffer = new StringBuilder();
            while (it.hasNext())
            {
                String line = it.next();
                String logLevelOrNull = extractLogLevel.apply(line);
                if (logLevelOrNull == null)
                {
                    // found a log which isn't the start of a logger line; assume its an exception
                    if (lineBuffer.length() == 0)
                    {
                        // no previous start of line found, so skip this
                        continue;
                    }
                    lineBuffer.append('\n').append(line);
                    continue;
                }
                // line is a start of a log, reset state
                if (lineBuffer.length() != 0)
                {
                    // buffer has content, add and move on
                    matches.add(lineBuffer.toString());
                    lineBuffer.setLength(0);
                }
                switch (logLevelOrNull)
                {
                    case "ERROR":
                        lineBuffer.append(line);
                        break;
                    case "WARN":
                        if (exceptionPattern.matcher(line).find())
                            lineBuffer.append(line);
                        break;
                    default:
                        // ignore
                }
            }
            if (lineBuffer.length() != 0)
            {
                matches.add(lineBuffer.toString());
            }
            return new BasicLogResult<>(it.mark(), matches);
        }
    }

    /**
     * Attempt to find all errors in the log.  This method is different from {@code grep("^ERROR")} as it will also
     * attempt to stitch the exception stack trace into a single line.
     *
     * This method is modeled after python dtests's grep_for_errors and matches the semantics there.
     *
     * @param startPosition to grep from
     * @return result of all found exceptions, with stitched errors
     */
    default LogResult<List<String>> grepForErrors(long startPosition)
    {
        return grepForErrors(startPosition, Internal.LOG_EXCEPTION_PATTERN);
    }

    /**
     * Attempt to find all errors in the log.  This method is different from {@code grep("^ERROR")} as it will also
     * attempt to stitch the exception stack trace into a single line.
     *
     * This method is modeled after python dtests's grep_for_errors and matches the semantics there.
     *
     * @return result of all found exceptions, with stitched errors
     */
    default LogResult<List<String>> grepForErrors()
    {
        return grepForErrors(Internal.DEFAULT_START_POSITION, Internal.LOG_EXCEPTION_PATTERN);
    }

    class BasicLogResult<T> implements LogResult<T>
    {
        private final long mark;
        private final T result;

        public BasicLogResult(long mark, T result) {
            this.mark = mark;
            this.result = Objects.requireNonNull(result);
        }

        @Override
        public long getMark() {
            return mark;
        }

        @Override
        public T getResult() {
            return result;
        }

        @Override
        public String toString() {
            return "LogResult{" +
                    "mark=" + mark +
                    ", result=" + result +
                    '}';
        }
    }
    
    class Internal
    {
        private static final int DEFAULT_START_POSITION = -1;
        // why 10m?  This is the default for python dtest...
        private static final Duration DEFAULT_TIMEOUT = Duration.ofMinutes(10);
        private static final Pattern LOG_LEVEL_PATTERN = Pattern.compile("^(INFO|DEBUG|WARN|ERROR)");
        private static final Pattern LOG_EXCEPTION_PATTERN = Pattern.compile("[Ee]xception|AssertionError");

        private static List<String> collect(LineIterator it)
        {
            List<String> matches = new ArrayList<>();
            while (it.hasNext())
                matches.add(it.next());
            return matches.isEmpty() ? Collections.emptyList() : matches;
        }

        private static Predicate<String> regexPredicate(List<Pattern> patterns)
        {
            return line -> {
                for (Pattern regex : patterns)
                {
                    Matcher m = regex.matcher(line);
                    if (m.find())
                        return true;
                }
                return false;
            };
        }

        private static Predicate<String> regexPredicate(String pattern, String... others)
        {
            List<Pattern> patterns = new ArrayList<>(others.length + 1);
            patterns.add(Pattern.compile(pattern));
            for (String s : others)
                patterns.add(Pattern.compile(s));
            return regexPredicate(patterns);
        }

        private static Predicate<String> regexPredicate(Pattern pattern)
        {
            return line -> pattern.matcher(line).find();
        }

        private static Predicate<String> regexPredicate(String pattern)
        {
            return regexPredicate(Pattern.compile(pattern));
        }

        private static void sleepUninterruptibly(long sleepFor, TimeUnit unit) {
            // copied from guava since dtest can't depend on guava
            boolean interrupted = false;

            try {
                long remainingNanos = unit.toNanos(sleepFor);
                long end = System.nanoTime() + remainingNanos;

                while(true) {
                    try {
                        TimeUnit.NANOSECONDS.sleep(remainingNanos);
                        return;
                    } catch (InterruptedException var12) {
                        interrupted = true;
                        remainingNanos = end - System.nanoTime();
                    }
                }
            } finally {
                if (interrupted) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
}
