/*
 * 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.JDBCDriverConfig;

class JDBCDriverTask implements CliPostInstallTaskImpl {

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

    @Override
    public boolean applyToStandalone(InstallationData data, StandaloneServer server, TaskPrinter printer) {
        taskLog.info(String.format("Starting applying JDBC driver changes to %s", server.currentConfiguration()));
        printer.print("tasks.jdbc_driver.started", server.currentConfiguration());

        final JDBCDriverConfig config = data.getConfig(JDBCDriverConfig.class);
        assert config != null;
        try {
            taskLog.debug("Applying JDBC driver change");
            final ModelNode jdbcDriverOp = getJdbcDriverOp(config);
            server.execute(jdbcDriverOp, "Set JDBC Driver");
        } catch (ServerOperationException e) {
            taskLog.error("CLI operation failed", e);
            printer.print("tasks.jdbc_driver.failed");
            printer.print(e);
            return false;
        }
        printer.print("tasks.jdbc_driver.finished");
        return true;
    }

    @Override
    public boolean applyToDomain(InstallationData data, DomainServer server, TaskPrinter printer) {
        if (!server.currentConfiguration().equals("host.xml")) {
            return true;
        }

        final JDBCDriverConfig config = data.getConfig(JDBCDriverConfig.class);
        assert config != null;

        taskLog.info(String.format("Starting applying JDBC driver changes to %s", server.currentConfiguration()));
        printer.print("tasks.jdbc_driver.started", server.currentConfiguration());
        try {
            taskLog.debug("Applying JDBC driver change");
            final ModelNode jdbcDriverOp = getJdbcDriverOp(config);
            server.executeOnProfiles(jdbcDriverOp, "Set JDBC Driver");

        } catch (ServerOperationException e) {
            taskLog.error("CLI operation failed", e);
            printer.print("tasks.jdbc_driver.failed");
            printer.print(e);
            return false;
        }
        printer.print("tasks.jdbc_driver.finished");
        return true;
    }

    private ModelNode getJdbcDriverOp(JDBCDriverConfig config) {
        final ModelNode driverOp = createEmptyOperation("add",
                pathAddress("subsystem", "datasources").add("jdbc-driver", config.getDatabaseDriver().getJdbcName()));
        driverOp.get("driver-name").set(config.getDatabaseDriver().getJdbcName());
        driverOp.get("driver-module-name").set(config.getDatabaseDriver().getModuleName());
        driverOp.get("driver-xa-datasource-class-name").set(config.getDatabaseDriver().getXaClassName());
        return driverOp;
    }
}
