/*
 * 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.nifi.logging.repository;

import org.apache.nifi.logging.ComponentLog;
import org.apache.nifi.logging.LogLevel;
import org.apache.nifi.logging.LogMessage;
import org.apache.nifi.logging.LogObserver;
import org.apache.nifi.logging.LogRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.MessageFormatter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class StandardLogRepository implements LogRepository {

    private final Map<LogLevel, Collection<LogObserver>> observers = new HashMap<>();
    private final Map<String, LogObserver> observerLookup = new HashMap<>();

    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final Lock readLock = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();

    private final Logger logger = LoggerFactory.getLogger(StandardLogRepository.class);

    private volatile ComponentLog componentLogger;

    @Override
    public void addLogMessage(final LogLevel level, final String message) {
        addLogMessage(level, message, (Throwable) null);
    }

    @Override
    public void addLogMessage(final LogLevel level, final String message, final Throwable t) {
        final LogMessage logMessage = new LogMessage(System.currentTimeMillis(), level, message, t);

        final Collection<LogObserver> logObservers = observers.get(level);
        if (logObservers != null) {
            for (LogObserver observer : logObservers) {
                try {
                    observer.onLogMessage(logMessage);
                } catch (final Throwable observerThrowable) {
                    logger.error("Failed to pass log message to Observer {} due to {}", observer, observerThrowable.toString());
                }
            }
        }
    }

    @Override
    public void addLogMessage(final LogLevel level, final String format, final Object[] params) {
        replaceThrowablesWithMessage(params);
        final String formattedMessage = MessageFormatter.arrayFormat(format, params).getMessage();
        addLogMessage(level, formattedMessage);
    }

    @Override
    public void addLogMessage(final LogLevel level, final String format, final Object[] params, final Throwable t) {
        replaceThrowablesWithMessage(params);
        final String formattedMessage = MessageFormatter.arrayFormat(format, params, t).getMessage();
        addLogMessage(level, formattedMessage, t);
    }

    private void replaceThrowablesWithMessage(final Object[] params) {
        for (int i = 0; i < params.length; i++) {
            if(params[i] instanceof Throwable) {
                params[i] = ((Throwable) params[i]).getLocalizedMessage();
            }
        }
    }

    @Override
    public void setObservationLevel(String observerIdentifier, LogLevel level) {
        writeLock.lock();
        try {
            final LogObserver observer = removeObserver(observerIdentifier);

            if (observer != null) {
                addObserver(observerIdentifier, level, observer);
            }
        } finally {
            writeLock.unlock();
        }
    }

    @Override
    public LogLevel getObservationLevel(String observerIdentifier) {
        readLock.lock();
        try {
            // ensure observer exists
            if (!observerLookup.containsKey(observerIdentifier)) {
                throw new IllegalStateException("The specified observer identifier does not exist.");
            }

            final LogObserver observer = observerLookup.get(observerIdentifier);
            for (final LogLevel logLevel : LogLevel.values()) {
                final Collection<LogObserver> levelObservers = observers.get(logLevel);
                if (levelObservers != null && levelObservers.contains(observer)) {
                    return logLevel;
                }
            }

            // at this point, the LogLevel must be NONE since we don't register observers for NONE
            return LogLevel.NONE;
        } finally {
            readLock.unlock();
        }
    }

    @Override
    public void addObserver(final String observerIdentifier, final LogLevel minimumLevel, final LogObserver observer) {
        writeLock.lock();
        try {
            // ensure observer does not exists
            if (observerLookup.containsKey(observerIdentifier)) {
                throw new IllegalStateException("The specified observer identifier (" + observerIdentifier + ") already exists.");
            }

            final LogLevel[] allLevels = LogLevel.values();
            for (int i = minimumLevel.ordinal(); i < allLevels.length; i++) {
                // no need to register an observer for NONE since that level will never be logged to by a component
                if (i != LogLevel.NONE.ordinal()) {
                    Collection<LogObserver> collection = observers.get(allLevels[i]);
                    if (collection == null) {
                        collection = new ArrayList<>();
                        observers.put(allLevels[i], collection);
                    }
                    collection.add(observer);
                }
            }
            observerLookup.put(observerIdentifier, observer);
        } finally {
            writeLock.unlock();
        }
    }

    @Override
    public LogObserver removeObserver(final String observerIdentifier) {
        writeLock.lock();
        try {
            final LogObserver observer = observerLookup.get(observerIdentifier);
            for (final Collection<LogObserver> collection : observers.values()) {
                collection.remove(observer);
            }
            return observerLookup.remove(observerIdentifier);
        } finally {
            writeLock.unlock();
        }
    }

    @Override
    public void removeAllObservers() {
        writeLock.lock();
        try {
            observers.clear();
            observerLookup.clear();
        } finally {
            writeLock.unlock();
        }
    }

    @Override
    public void setLogger(final ComponentLog componentLogger) {
        this.componentLogger = componentLogger;
    }

    @Override
    public ComponentLog getLogger() {
        return componentLogger;
    }

    private boolean hasObserver(final LogLevel logLevel) {
        final Collection<LogObserver> logLevelObservers = observers.get(logLevel);
        return (logLevelObservers != null && !logLevelObservers.isEmpty());
    }

    @Override
    public boolean isDebugEnabled() {
        return hasObserver(LogLevel.DEBUG);
    }

    @Override
    public boolean isInfoEnabled() {
        return hasObserver(LogLevel.INFO);
    }

    @Override
    public boolean isWarnEnabled() {
        return hasObserver(LogLevel.WARN);
    }

    @Override
    public boolean isErrorEnabled() {
        return hasObserver(LogLevel.ERROR);
    }
}
