/*
 * 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 java.io.IOException;
import java.net.URL;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import org.jboss.installer.actions.ActionException;
import org.jboss.installer.core.FileUtils;
import org.jboss.installer.core.InstallationData;
import org.jboss.installer.core.LanguageUtils;
import org.jboss.installer.core.LoggerUtils;
import org.jboss.installer.postinstall.SimplePostInstallTaskImpl;
import org.jboss.installer.postinstall.TaskPrinter;
import org.jboss.installer.postinstall.task.JSFLibraryConfig;
import org.jboss.installer.postinstall.task.jsf.MojarraJsfLibrarySetup;
import org.jboss.installer.postinstall.task.jsf.MyFacesJsfLibrarySetup;

class JsfLibraryTask implements SimplePostInstallTaskImpl {

    private LanguageUtils langUtils;

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

    @Override
    public void setLanguageUtils(LanguageUtils langUtils) {
        this.langUtils = langUtils;
    }

    @Override
    public boolean applyToInstallation(InstallationData data, TaskPrinter printer) {
        printer.print("tasks.jsf_module.started");

        final JSFLibraryConfig config = data.getConfig(JSFLibraryConfig.class);
        final Path baseFolder = data.getTargetFolder();

        boolean res;
        if (config.getJsfProject() == JSFLibraryConfig.JsfProject.Mojarra) {
            try {
                res = new MojarraJsfLibrarySetup(printer).perform(config, baseFolder);
                printer.print("tasks.jsf_module.finished");
                return res;
            } catch (IOException e) {
                taskLog.error(e.getMessage(), e);
                printer.print("tasks.jsf_module.failed");
                printer.print(e);
                return false;
            }
        } else {
            try {
                installMyFacesLibrary(printer, config, baseFolder);
                return true;
            } catch (ActionException e) {
                taskLog.error(e.getMessage(), e);
                printer.print("tasks.jsf_module.failed");
                printer.print(e);
                return false;
            }
        }
    }

    private void installMyFacesLibrary(TaskPrinter printer, JSFLibraryConfig config, Path baseFolder) throws ActionException {
        final MyFacesJsfLibrarySetup myFacesJsfLibrarySetup = new MyFacesJsfLibrarySetup(baseFolder, langUtils);
        final List<String> repositoryUrls = new ArrayList<>();
        String manifestCoordinates = config.getManifestCoordinates();
        // if new_channel
        if (manifestCoordinates == null) {
            // create channel manifest
            printer.print("tasks.jsf_module.manifest.create", config.getLocalChannelRepositoryPath());
            LoggerUtils.taskLog.debug(String.format("Creating MyFaces manifest repository at %s", config.getLocalChannelRepositoryPath()));
            manifestCoordinates = myFacesJsfLibrarySetup.createChannelManifest(config.getJsfVersion(), config.getLocalChannelRepositoryPath());

            // add local repository location to the channel repositories
            LoggerUtils.taskLog.debug(String.format("Adding manifest repository %s to the channel repositories",
                    FileUtils.asUrl(config.getLocalChannelRepositoryPath())));
            repositoryUrls.add(FileUtils.asUrl(config.getLocalChannelRepositoryPath()).toExternalForm());

        }

        for (URL repository : config.getRemoteMavenRepositoryUrls()) {
            LoggerUtils.taskLog.debug(String.format("Adding remote repository %s to the channel repositories",
                    repository.toExternalForm()));
            repositoryUrls.add(repository.toExternalForm());
        }
        // add channel definition
        printer.print("tasks.jsf_module.channel.register");
        LoggerUtils.taskLog.debug(String.format("Registering MyFaces channel with manifest %s", manifestCoordinates));
        myFacesJsfLibrarySetup.registerChannel(repositoryUrls, manifestCoordinates);

        // provision the feature
        printer.print("tasks.jsf_module.provision.starting");
        LoggerUtils.taskLog.debug("Installing MyFaces feature pack");
        myFacesJsfLibrarySetup.installFeaturePack(printer);
        LoggerUtils.taskLog.debug("MyFaces feature pack installed");
    }
}
