/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2024 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed 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.jboss.installer.postinstall.task.impl;

import static org.jboss.installer.core.LoggerUtils.taskLog;
import static org.jboss.installer.postinstall.task.utils.ModelUtils.createEmptyOperation;
import static org.jboss.installer.postinstall.task.utils.ModelUtils.pathAddress;

import org.jboss.dmr.ModelNode;
import org.jboss.installer.core.InstallationData;
import org.jboss.installer.postinstall.CliPostInstallTaskImpl;
import org.jboss.installer.postinstall.TaskPrinter;
import org.jboss.installer.postinstall.server.DomainServer;
import org.jboss.installer.postinstall.server.ServerOperationException;
import org.jboss.installer.postinstall.server.StandaloneServer;
import org.jboss.installer.postinstall.task.LoggingLevelConfig;

class LoggingLevelsTask implements CliPostInstallTaskImpl {

    @Override
    public String getName() {
        return "post_install.task.logging.name";
    }

    @Override
    public boolean applyToStandalone(InstallationData data, StandaloneServer server, TaskPrinter printer) {
        taskLog.info(String.format("Starting applying logger level changes to %s", server.currentConfiguration()));
        printer.print("tasks.logger_levels.started", server.currentConfiguration());
        final LoggingLevelConfig config = data.getConfig(LoggingLevelConfig.class);
        assert config != null;

        try {
            taskLog.debug("Applying root logger change");
            final ModelNode rootLoggerOp = getLoggerLevelOp("root-logger", "ROOT", config.getRootLevel());
            server.execute(rootLoggerOp, "Set root logger level");

            if (!server.currentConfiguration().equals("standalone-full-ha.xml")) {
                taskLog.debug("Applying console handler change");
                final ModelNode consoleLoggerOp = getLoggerLevelOp("console-handler", "CONSOLE", config.getConsoleLevel());
                server.execute(consoleLoggerOp, "Set console logger level");
            }
            taskLog.info(String.format("Finished applying logger level changes to %s", server.currentConfiguration()));
            printer.print("tasks.logger_levels.finished", server.currentConfiguration());
            return true;
        }catch (ServerOperationException e) {
            taskLog.error("CLI operation failed", e);
            printer.print("tasks.logger_levels.failed", server.currentConfiguration());
            printer.print(e);
            return false;
        }
    }

    @Override
    public boolean applyToDomain(InstallationData data, DomainServer server, TaskPrinter printer) {
        taskLog.info(String.format("Starting applying logger level changes to %s", server.currentConfiguration()));
        printer.print("tasks.logger_levels.started", server.currentConfiguration());
        final LoggingLevelConfig config = data.getConfig(LoggingLevelConfig.class);
        assert config != null;

        try {
            if (!server.currentConfiguration().equals(DomainServer.HOST_SECONDARY_XML)) {
                taskLog.debug("Applying root logger change");
                final ModelNode rootLoggerOp = getLoggerLevelOp("root-logger", "ROOT", config.getRootLevel());
                server.executeOnProfiles(rootLoggerOp, "Set root logger level");
            }

            taskLog.info(String.format("Finished applying logger level changes to %s", server.currentConfiguration()));
            printer.print("tasks.logger_levels.finished", server.currentConfiguration());
            return true;
        }catch (ServerOperationException e) {
            taskLog.error("CLI operation failed", e);
            printer.print("tasks.logger_levels.failed", server.currentConfiguration());
            printer.print(e);
            return false;
        }
    }

    private ModelNode getLoggerLevelOp(String loggerType, String loggerName, String level) {
        final ModelNode rootLoggerOp = createEmptyOperation("write-attribute",
                pathAddress("subsystem", "logging").add(loggerType, loggerName));
        rootLoggerOp.get("name").set("level");
        rootLoggerOp.get("value").set(level);
        return rootLoggerOp;
    }
}
