/*
* 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 com.cloud.test;

import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggingEvent;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
import static org.apache.log4j.Level.ALL;
import static org.apache.log4j.Level.DEBUG;
import static org.apache.log4j.Level.ERROR;
import static org.apache.log4j.Level.FATAL;
import static org.apache.log4j.Level.INFO;
import static org.apache.log4j.Level.OFF;
import static org.apache.log4j.Level.WARN;

/**
*
* Tracks one or more patterns to determine whether or not they have been
* logged. It uses a streaming approach to determine whether or not a message
* has a occurred to prevent unnecessary memory consumption. Instances of this
* of this class are created using the {@link TestAppenderBuilder}.
*
* To use this class, register a one or more expected patterns by level as part
* of the test setup and retain an reference to the appender instance. After the
* expected logging events have occurred in the test case, call
* {@link TestAppender#assertMessagesLogged()} which will fail the test if any of the
* expected patterns were not logged.
*
*/
public final class TestAppender extends AppenderSkeleton {
    private final static String APPENDER_NAME = "test_appender";
    private final ImmutableMap<Level, Set<PatternResult>> expectedPatternResults;
    private TestAppender(final Map<Level, Set<PatternResult>> expectedPatterns) {
        super();
        expectedPatternResults = ImmutableMap.copyOf(expectedPatterns);
    }
    protected void append(LoggingEvent loggingEvent) {
        checkArgument(loggingEvent != null, "append requires a non-null loggingEvent");
        final Level level = loggingEvent.getLevel();
        checkState(expectedPatternResults.containsKey(level), "level " + level + " not supported by append");
        for (final PatternResult patternResult : expectedPatternResults.get(level)) {
            if (patternResult.getPattern().matcher(loggingEvent.getRenderedMessage()).matches()) {
                patternResult.markFound();
            }
        }
    }

    public void close() {
// Do nothing ...
    }
    public boolean requiresLayout() {
        return false;
    }
    public void assertMessagesLogged() {
        final List<String> unloggedPatterns = new ArrayList<>();
        for (final Map.Entry<Level, Set<PatternResult>> expectedPatternResult : expectedPatternResults.entrySet()) {
            for (final PatternResult patternResults : expectedPatternResult.getValue()) {
                if (!patternResults.isFound()) {
                    unloggedPatterns.add(format("%1$s was not logged for level %2$s",
                            patternResults.getPattern().toString(), expectedPatternResult.getKey()));
                }
            }
        }
        if (!unloggedPatterns.isEmpty()) {
            //Raise an assert
            Assert.isTrue(false, Joiner.on(",").join(unloggedPatterns));
        }
    }

    private static final class PatternResult {
        private final Pattern pattern;
        private boolean foundFlag = false;
        private PatternResult(Pattern pattern) {
            super();
            this.pattern = pattern;
        }
        public Pattern getPattern() {
            return pattern;
        }
        public void markFound() {
        // This operation is thread-safe because the value will only ever be switched from false to true. Therefore,
        // multiple threads mutating the value for a pattern will not corrupt the value ...
            foundFlag = true;
        }
        public boolean isFound() {
            return foundFlag;
        }
        @Override
        public boolean equals(Object thatObject) {
            if (this == thatObject) {
                return true;
            }
            if (thatObject == null || getClass() != thatObject.getClass()) {
                return false;
            }
            PatternResult thatPatternResult = (PatternResult) thatObject;
            return foundFlag == thatPatternResult.foundFlag &&
                    Objects.equal(pattern, thatPatternResult.pattern);
        }
        @Override
        public int hashCode() {
            return Objects.hashCode(pattern, foundFlag);
        }
        @Override
        public String toString() {
            return format("Pattern Result [ pattern: %1$s, markFound: %2$s ]", pattern.toString(), foundFlag);
        }
    }

    public static final class TestAppenderBuilder {
        private final Map<Level, Set<PatternResult>> expectedPatterns;
        public TestAppenderBuilder() {
            super();
            expectedPatterns = new HashMap<>();
            expectedPatterns.put(ALL, new HashSet<PatternResult>());
            expectedPatterns.put(DEBUG, new HashSet<PatternResult>());
            expectedPatterns.put(ERROR, new HashSet<PatternResult>());
            expectedPatterns.put(FATAL, new HashSet<PatternResult>());
            expectedPatterns.put(INFO, new HashSet<PatternResult>());
            expectedPatterns.put(OFF, new HashSet<PatternResult>());
            expectedPatterns.put(WARN, new HashSet<PatternResult>());
        }
        public TestAppenderBuilder addExpectedPattern(final Level level, final String pattern) {
            checkArgument(level != null, "addExpectedPattern requires a non-null level");
            checkArgument(StringUtils.isNotEmpty(pattern), "addExpectedPattern requires a non-blank pattern");
            checkState(expectedPatterns.containsKey(level), "level " + level + " is not supported by " + getClass().getName());
            expectedPatterns.get(level).add(new PatternResult(Pattern.compile(pattern)));
            return this;
        }
        public TestAppender build() {
            return new TestAppender(expectedPatterns);
        }
    }
    /**
     *
     * Attaches a {@link TestAppender} to a {@link Logger} and ensures that it is the only
     * test appender attached to the logger.
     *
     * @param logger The logger which will be monitored by the test
     * @param testAppender The test appender to attach to {@code logger}
     */
    public static void safeAddAppender(Logger logger, TestAppender testAppender) {
        logger.removeAppender(APPENDER_NAME);
        logger.addAppender(testAppender);
    }
}
