/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2011, Red Hat, Inc., and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.jboss.as.controller;

import static org.jboss.logging.Logger.Level.ERROR;
import static org.jboss.logging.Logger.Level.INFO;
import static org.jboss.logging.Logger.Level.WARN;

import java.io.Closeable;
import java.net.InetAddress;
import java.util.List;
import java.util.Set;

import javax.xml.stream.XMLStreamWriter;

import org.jboss.as.controller.notification.Notification;
import org.jboss.dmr.ModelNode;
import org.jboss.logging.BasicLogger;
import org.jboss.logging.Logger;
import org.jboss.logging.Logger.Level;
import org.jboss.logging.annotations.Cause;
import org.jboss.logging.annotations.LogMessage;
import org.jboss.logging.annotations.Message;
import org.jboss.logging.annotations.MessageLogger;

/**
 * This module is using message IDs in the ranges 14600-14899 and 13400-13499.
 * <p/>
 * This file is using the subsets 14600-14629 and 13400-13449 for logger messages.
 * <p/>
 * See <a href="http://community.jboss.org/docs/DOC-16810">http://community.jboss.org/docs/DOC-16810</a> for the full
 * list of currently reserved JBAS message id blocks.
 * <p/>
 * Date: 02.11.2011
 *
 * @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a>
 */
@MessageLogger(projectCode = "JBAS")
public interface ControllerLogger extends BasicLogger {

    /**
     * Default root logger with category of the package name.
     */
    ControllerLogger ROOT_LOGGER = Logger.getMessageLogger(ControllerLogger.class, ControllerLogger.class.getPackage().getName());

    /**
     * Logger for management operation messages.
     */
    ControllerLogger MGMT_OP_LOGGER = Logger.getMessageLogger(ControllerLogger.class, ControllerLogger.class.getPackage().getName() + ".management-operation");

    /**
     * A logger with the category {@code org.jboss.as.server}
     */
    ControllerLogger SERVER_LOGGER = Logger.getMessageLogger(ControllerLogger.class, "org.jboss.as.server");

    /**
     * A logger with the category {@code org.jboss.server.management}
     */
    ControllerLogger SERVER_MANAGEMENT_LOGGER = Logger.getMessageLogger(ControllerLogger.class, "org.jboss.server.management");

    /**
     * A logger for logging deprecated resources usage
     */
    ControllerLogger DEPRECATED_LOGGER = Logger.getMessageLogger(ControllerLogger.class, ControllerLogger.class.getPackage().getName() + ".management-deprecated");

    /**
     * A logger for logging problems in the transformers
     */
    ControllerLogger TRANSFORMER_LOGGER = Logger.getMessageLogger(ControllerLogger.class, ControllerLogger.class.getPackage().getName() + ".transformer");

    /**
     * A logger for access control related messages.
     */
    ControllerLogger ACCESS_LOGGER = Logger.getMessageLogger(ControllerLogger.class, ControllerLogger.class.getPackage().getName() + ".access-control");

    /**
     * Logs a warning message indicating the address, represented by the {@code address} parameter, could not be
     * resolved, so cannot match it to any InetAddress.
     *
     * @param address the address that could not be resolved.
     */
    @LogMessage(level = WARN)
    @Message(id = 14600, value = "Cannot resolve address %s, so cannot match it to any InetAddress")
    void cannotResolveAddress(String address);

    /**
     * Logs an error message indicating there was an error booting the container.
     *
     * @param cause the cause of the error.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14601, value = "Error booting the container")
    void errorBootingContainer(@Cause Throwable cause);

    /**
     * Logs an error message indicating there was an error booting the container.
     *
     * @param cause         the cause of the error.
     * @param bootStackSize the boot stack size.
     * @param name          the property name to increase the boot stack size.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14602, value = "Error booting the container due to insufficient stack space for the thread used to " +
            "execute boot operations. The thread was configured with a stack size of [%1$d]. Setting " +
            "system property %2$s to a value higher than [%1$d] may resolve this problem.")
    void errorBootingContainer(@Cause Throwable cause, long bootStackSize, String name);

    /**
     * Logs an error message indicating the class, represented by the {@code className} parameter, caught exception
     * attempting to revert the operation, represented by the {@code op} parameter, at the address, represented by the
     * {@code address} parameter.
     *
     * @param cause     the cause of the error.
     * @param className the name of the class that caught the error.
     * @param op        the operation.
     * @param address   the address.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14603, value = "%s caught exception attempting to revert operation %s at address %s")
    void errorRevertingOperation(@Cause Throwable cause, String className, String op, PathAddress address);

    /**
     * Logs an error message indicating a failure to execute the operation, represented by the {@code op} parameter, at
     * the address represented by the {@code path} parameter.
     *
     * @param cause the cause of the error.
     * @param op    the operation.
     * @param path  the path the operation was executed on.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14604, value = "Failed executing operation %s at address %s")
    void failedExecutingOperation(@Cause Throwable cause, ModelNode op, PathAddress path);

    /**
     * Logs an error message indicating a failure executing the subsystem, represented by the {@code name} parameter,
     * boot operations.
     *
     * @param cause the cause of the error.
     * @param name  the name of subsystem.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14605, value = "Failed executing subsystem %s boot operations")
    void failedSubsystemBootOperations(@Cause Throwable cause, String name);

    /**
     * Logs an error message indicating to failure to close the resource represented by the {@code closeable} parameter.
     *
     * @param cause     the cause of the error.
     * @param closeable the resource.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14606, value = "Failed to close resource %s")
    void failedToCloseResource(@Cause Throwable cause, Closeable closeable);

    /**
     * Logs an error message indicating to failure to close the resource represented by the {@code writer} parameter.
     *
     * @param cause  the cause of the error.
     * @param writer the resource.
     */
    @LogMessage(level = ERROR)
    void failedToCloseResource(@Cause Throwable cause, XMLStreamWriter writer);

    /**
     * Logs an error message indicating a failure to persist configuration change.
     *
     * @param cause the cause of the error.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14607, value = "Failed to persist configuration change")
    void failedToPersistConfigurationChange(@Cause Throwable cause);

    /**
     * Logs an error message indicating a failure to store the configuration file.
     *
     * @param cause the cause of the error.
     * @param name  the name of the configuration.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14608, value = "Failed to store configuration to %s")
    void failedToStoreConfiguration(@Cause Throwable cause, String name);

    /**
     * Logs an error message indicating an invalid value for the system property, represented by the {@code name}
     * parameter, was found.
     *
     * @param value        the invalid value.
     * @param name         the name of the system property.
     * @param defaultValue the default value being used.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14609, value = "Invalid value %s for system property %s -- using default value [%d]")
    void invalidSystemPropertyValue(String value, String name, int defaultValue);

    /**
     * Logs a warning message indicating the address, represented by the {@code address} parameter, is a wildcard
     * address and will not match any specific address.
     *
     * @param address        the wildcard address.
     * @param inetAddress    the inet-address tag.
     * @param anyAddress     the any-address tag.
     * @param anyIpv4Address the any-ipv4-address tag.
     * @param anyIpv6Address the any-ipv6-address tag.
     */
    @LogMessage(level = WARN)
    @Message(id = 14610, value = "Address %1$s is a wildcard address, which will not match against any specific address. Do not use " +
            "the '%2$s' configuration element to specify that an interface should use a wildcard address; " +
            "use '%3$s', '%4$s', or '%5$s'")
    void invalidWildcardAddress(String address, String inetAddress, String anyAddress, String anyIpv4Address, String anyIpv6Address);

    /**
     * Logs an error message indicating no handler for the step operation, represented by the {@code stepOpName}
     * parameter, at {@code address}.
     *
     * @param stepOpName the step operation name.
     * @param address    the address
     * @deprecated use {@link #noSuchResourceType(PathAddress)} or {@link #noHandlerForOperation(String, PathAddress)}
     */
    @Deprecated
    @LogMessage(level = ERROR)
    @Message(id = 14611, value = "No handler for %s at address %s")
    void noHandler(String stepOpName, PathAddress address);

    /**
     * Logs an error message indicating operation failed.
     *
     * @param cause     the cause of the error.
     * @param op        the operation that failed.
     * @param opAddress the address the operation failed on.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14612, value = "Operation (%s) failed - address: (%s)")
    void operationFailed(@Cause Throwable cause, ModelNode op, ModelNode opAddress);

    /**
     * Logs an error message indicating operation failed.
     *
     * @param op                 the operation that failed.
     * @param opAddress          the address the operation failed on.
     * @param failureDescription the failure description.
     */
    @LogMessage(level = ERROR)
    @Message(id = Message.INHERIT, value = "Operation (%s) failed - address: (%s) - failure description: %s")
    void operationFailed(ModelNode op, ModelNode opAddress, ModelNode failureDescription);

    /**
     * Logs an error message indicating operation failed.
     *
     * @param cause        the cause of the error.
     * @param op           the operation that failed.
     * @param opAddress    the address the operation failed on.
     * @param propertyName the boot stack size property name.
     * @param defaultSize  the default boot stack size property size.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14613, value = "Operation (%s) failed - address: (%s) -- due to insufficient stack space for the thread used to " +
            "execute operations. If this error is occurring during server boot, setting " +
            "system property %s to a value higher than [%d] may resolve this problem.")
    void operationFailedInsufficientStackSpace(@Cause Throwable cause, ModelNode op, ModelNode opAddress, String propertyName, int defaultSize);

    /**
     * Logs a warning message indicating a wildcard address was detected and will ignore other interface criteria.
     */
    @LogMessage(level = WARN)
    @Message(id = 14614, value = "Wildcard address detected - will ignore other interface criteria.")
    void wildcardAddressDetected();

    /**
     * Logs a warning message indicating an invocation on a {@link ProxyController} did not provide a final response.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14615, value = "Received no final outcome response for operation %s with address %s from remote " +
            "process at address %s. The result of this operation will only include the remote process' preliminary response to " +
            "the request.")
    void noFinalProxyOutcomeReceived(ModelNode op, ModelNode opAddress, ModelNode proxyAddress);

    /**
     * Logs an error message indicating operation failed due to a client error (e.g. an invalid request).
     *
     * @param op                 the operation that failed.
     * @param opAddress          the address the operation failed on.
     * @param failureDescription the failure description.
     */
    @LogMessage(level = Logger.Level.DEBUG)
    @Message(id = 14616, value = "Operation (%s) failed - address: (%s) - failure description: %s")
    void operationFailedOnClientError(ModelNode op, ModelNode opAddress, ModelNode failureDescription);

    /**
     * Logs an error indicating that createWrapper should be called
     *
     * @param name the subsystem name
     */
    @LogMessage(level = Logger.Level.WARN)
    @Message(id = 14617, value = "A subystem '%s' was registered without calling ExtensionContext.createTracker(). The subsystems are registered normally but won't be cleaned up when the extension is removed.")
    void registerSubsystemNoWraper(String name);

    /**
     * Logs a warning message indicating graceful shutdown of native management request handling
     * communication did not complete within the given timeout period.
     *
     * @param timeout the timeout, in ms.
     */
    @LogMessage(level = Logger.Level.WARN)
    @Message(id = 14618, value = "Graceful shutdown of the handler used for native management requests did not complete within [%d] ms but shutdown of the underlying communication channel is proceeding")
    void gracefulManagementChannelHandlerShutdownTimedOut(int timeout);

    /**
     * Logs a warning message indicating graceful shutdown of native management request handling
     * communication failed.
     *
     * @param cause the timeout, in ms.
     */
    @LogMessage(level = Logger.Level.WARN)
    @Message(id = 14619, value = "Graceful shutdown of the handler used for native management requests failed but shutdown of the underlying communication channel is proceeding")
    void gracefulManagementChannelHandlerShutdownFailed(@Cause Throwable cause);

    /**
     * Logs a warning message indicating graceful shutdown of management request handling of slave HC to master HC
     * communication failed.
     *
     * @param cause        the the cause of the failure
     * @param propertyName the name of the system property
     * @param propValue    the value provided
     */
    @LogMessage(level = Logger.Level.WARN)
    @Message(id = 14620, value = "Invalid value '%s' for system property '%s' -- value must be convertible into an int")
    void invalidChannelCloseTimeout(@Cause NumberFormatException cause, String propertyName, String propValue);

    /**
     * Logs a warning message indicating multiple addresses or nics matched the selection criteria provided for
     * an interface
     *
     * @param interfaceName    the name of the interface configuration
     * @param addresses        the matching addresses
     * @param nis              the matching nics
     * @param inetAddress      the selected address
     * @param networkInterface the selected nic
     */
    @LogMessage(level = Logger.Level.WARN)
    @Message(id = 14621, value = "Multiple addresses or network interfaces matched the selection criteria for interface '%s'. Matching addresses: %s.  Matching network interfaces: %s. The interface will use address %s and network interface %s.")
    void multipleMatchingAddresses(String interfaceName, Set<InetAddress> addresses, Set<String> nis, InetAddress inetAddress, String networkInterface);

    /**
     * Logs a warning message indicating multiple addresses or nics matched the selection criteria provided for
     * an interface
     *
     * @param toMatch   the name of the interface configuration
     * @param addresses the matching addresses
     * @param nis       the matching nics
     */
    @LogMessage(level = Logger.Level.WARN)
    @Message(id = 14622, value = "Value '%s' for interface selection criteria 'inet-address' is ambiguous, as more than one address or network interface available on the machine matches it. Because of this ambiguity, no address will be selected as a match. Matching addresses: %s.  Matching network interfaces: %s.")
    void multipleMatchingAddresses(String toMatch, Set<InetAddress> addresses, Set<String> nis);

    /**
     * Logs an error message indicating the target definition could not be read.
     *
     * @param cause the cause of the error.
     */
    @LogMessage(level = Level.ERROR)
    @Message(id = 14623, value = "Could not read target definition!")
    void cannotReadTargetDefinition(@Cause Throwable cause);

    /**
     * Logs an error message indicating a failure to transform.
     *
     * @param cause the cause of the error.
     */
    @LogMessage(level = Level.ERROR)
    @Message(id = 14624, value = "Could not transform")
    void cannotTransform(@Cause Throwable cause);

    /**
     * Logs a warning message indicating the there is not transformer for the subsystem.
     *
     * @param subsystemName the subsystem name
     * @param major         the major version
     * @param minor         the minor version
     */
    @LogMessage(level = Level.WARN)
    @Message(id = 14625, value = "We have no transformer for subsystem: %s-%d.%d model transfer can break!")
    void transformerNotFound(String subsystemName, int major, int minor);

    /**
     * Logs a warning message indicating that an operation was interrupted before service stability was reached
     */
    @LogMessage(level = Level.ERROR)
    @Message(id = 14626, value = "Operation was interrupted before service container stability could be reached. Process should be restarted. Step that first updated the service container was '%s' at address '%s'")
    void interruptedWaitingStability(String operation, PathAddress address);


    @LogMessage(level = Level.INFO)
    @Message(id = 14627, value = "Attribute '%s' in the resource at address '%s' is deprecated, and may be removed in " +
            "future version. See the attribute description in the output of the read-resource-description operation " +
            "to learn more about the deprecation.")
    void attributeDeprecated(String name, String address);

    /**
     * Logs a warnning message indicating a temp file could not be deleted.
     *
     * @param name temp filename
     */
    @LogMessage(level = Level.WARN)
    @Message(id = 14628, value = "Cannot delete temp file %s, will be deleted on exit")
    void cannotDeleteTempFile(String name);

    /**
     * Logs an error message indicating the given {@code address} does not match any known
     * resource registration.
     *
     * @param address the address.
     */
    @LogMessage(level = ERROR)
    @Message(id = 14629, value = "No resource definition is registered for address %s")
    void noSuchResourceType(PathAddress address);

    // END OF 146xx SERIES USABLE FOR LOGGER MESSAGES

    /**
     * Logs an error message indicating no handler is registered for an operation, represented by the {@code operationName}
     * parameter, at {@code address}.
     *
     * @param operationName the operation name.
     * @param address       the address.
     */
    @LogMessage(level = ERROR)
    @Message(id = 13400, value = "No operation named '%s' exists at address %s")
    void noHandlerForOperation(String operationName, PathAddress address);

    @Message(id = 13403, value = "There were problems during the transformation process for target host: '%s' %nProblems found: %n%s")
    @LogMessage(level = WARN)
    void tranformationWarnings(String hostName, Set<String> problems);


    @Message(id = 13404, value = "Extension '%s' is deprecated and may not be supported in future versions")
    @LogMessage(level = WARN)
    void extensionDeprecated(String extensionName);

    @Message(id = 13405, value = "Subsystems %s provided by legacy extension '%s' are not supported on servers running this version. " +
            "The extension is only supported for use by hosts running a previous release in a mixed-version managed domain. " +
            "On this server the extension will not register any subsystems, and future attempts to create or address " +
            "subsystem resources on this server will result in failure.")
    @LogMessage(level = INFO)
    void ignoringUnsupportedLegacyExtension(List<String> subsystemNames, String extensionName);

    /**
     * Logs an error message indicating that updating the audit log failed
     */
    @LogMessage(level = Level.ERROR)
    @Message(id = 13406, value = "Update of the management operation audit log failed")
    void failedToUpdateAuditLog(@Cause Exception e);

    /**
     * Logs an error message indicating that audit logging is being disabled due to logging failures.
     */
    @LogMessage(level = Level.ERROR)
    @Message(id = 13407, value = "[%d] consecutive management operation audit logging failures have occurred; disabling audit logging")
    void disablingLoggingDueToFailures(short failureCount);

    /**
     * Logs an error message indicating that a handler failed writing a log message
     */
    @LogMessage(level = Level.ERROR)
    @Message(id = 13408, value = "Update of the management operation audit log failed in handler '%s'")
    void logHandlerWriteFailed(@Cause Throwable t, String name);

    /**
     * Logs an error message indicating that audit logging is being disabled due to logging failures.
     */
    @LogMessage(level = Level.ERROR)
    @Message(id = 13409, value = "[%d] consecutive management operation audit logging failures have occurred in handler '%s'; disabling this handler for audit logging")
    void disablingLogHandlerDueToFailures(int failureCount, String name);

    @LogMessage(level = Level.ERROR)
    @Message(id = 13410, value = "Invalid value %s for property %s; must be a numeric value greater than zero. Default value of %d will be used.")
    void invalidDefaultBlockingTimeout(String sysPropValue, String sysPropName, long defaultUsed);

    @LogMessage(level = Level.DEBUG)
    @Message(id = 13411, value = "Timeout after [%d] seconds waiting for initial service container stability before allowing runtime changes for operation '%s' at address '%s'. Operation will roll back; process restart is required.")
    void timeoutAwaitingInitialStability(long blockingTimeout, String name, PathAddress address);

    @LogMessage(level = Level.ERROR)
    @Message(id = 13412, value = "Timeout after [%d] seconds waiting for service container stability. Operation will roll back. Step that first updated the service container was '%s' at address '%s'")
    void timeoutExecutingOperation(long blockingTimeout, String name, PathAddress address);

    @LogMessage(level = Level.ERROR)
    @Message(id = 13413, value = "Timeout after [%d] seconds waiting for service container stability while finalizing an operation. Process must be restarted. Step that first updated the service container was '%s' at address '%s'")
    void timeoutCompletingOperation(long blockingTimeout, String name, PathAddress address);

    @LogMessage(level = Level.INFO)
    @Message(id = 13414, value = "Execution of operation '%s' on remote process at address '%s' interrupted while awaiting initial response; remote process has been notified to cancel operation")
    void interruptedAwaitingInitialResponse(String operation, PathAddress proxyNodeAddress);

    @LogMessage(level = Level.INFO)
    @Message(id = 13415, value = "Execution of operation '%s' on remote process at address '%s' interrupted while awaiting final response; remote process has been notified to terminate operation")
    void interruptedAwaitingFinalResponse(String operation, PathAddress proxyNodeAddress);

    @LogMessage(level = Level.INFO)
    @Message(id = 13416, value = "Cancelling operation '%s' with id '%d' running on thread '%s'")
    void cancellingOperation(String operation, int id, String thread);

    @LogMessage(level = Level.INFO)
    @Message(id = 13417, value = "Attempting reconnect to syslog handler '%s; after timeout of %d seconds")
    void attemptingReconnectToSyslog(String name, int timeout);

    @LogMessage(level = Level.INFO)
    @Message(id = 13418, value = "Reconnecting to syslog handler '%s failed")
    void reconnectToSyslogFailed(String name, @Cause Throwable e);

    @LogMessage(level = WARN)
    @Message(id = 13419, value = "Failed to emit notification %s")
    void failedToEmitNotification(Notification notification, @Cause Throwable cause);

    @LogMessage(level = WARN)
    @Message(id = 13420, value = "Notification of type %s is not described for the resource at the address %s")
    void notificationIsNotDescribed(String type, PathAddress source);

    @LogMessage(level = WARN)
    @Message(id = 13421, value = "Update of the management operation audit log failed on the handler '%s' due to '%s'. Please make sure that the syslog server is running and reachable")
    void udpSyslogServerUnavailable(String name, String message);

    @Message(id = 13422, value = "Unexpected failure during execution of the following operation(s): %s")
    @LogMessage(level = ERROR)
    void unexpectedOperationExecutionException(@Cause Throwable t, List<ModelNode> controllerOperations);

    @LogMessage(level = Level.ERROR)
    @Message(id = 13423, value = "Failed sending completed response %s for %d")
    void failedSendingCompletedResponse(@Cause Throwable cause, ModelNode response, int operationId);

    @LogMessage(level = Level.ERROR)
    @Message(id = 13424, value = "Failed sending failure response %s for %d")
    void failedSendingFailedResponse(@Cause Throwable cause, ModelNode response, int operationId);

    @LogMessage(level = Level.INFO)
    @Message(id = 13425, value = "Execution of operation '%s' on remote process at address '%s' timed out after %d ms while awaiting final response; remote process has been notified to terminate operation")
    void timeoutAwaitingFinalResponse(String operation, PathAddress proxyNodeAddress, long timeout);

    // 13449 IS END OF 134xx SERIES USABLE FOR LOGGER MESSAGES

}
