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

import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

import org.jboss.installer.auto.AutomaticInstallationParsingException;
import org.jboss.installer.core.FileUtils;
import org.jboss.installer.core.FlatListPostInstallConfig;

public class JSFLibraryConfig extends FlatListPostInstallConfig {

    public enum JsfProject {
        Mojarra,
        MyFaces;

        public String fileName() {
            return toString().toLowerCase(Locale.ROOT);
        }
    }

    private boolean makeDefault;
    private String implJarPath;
    private JsfProject jsfProject;
    private String jsfVersion;
    private String localChannelRepositoryPath;
    private List<URL> remoteMavenRepositoryUrls = Collections.emptyList();
    private String manifestCoordinates;

    // not persisted
    private String resolvedImplJarPath;

    public boolean isMakeDefault() {
        return makeDefault;
    }

    public void setMakeDefault(boolean makeDefault) {
        this.makeDefault = makeDefault;
    }

    public String getImplJarPath() {
        return implJarPath;
    }

    public void setImplJarPath(String implJarPath) {
        this.implJarPath = implJarPath;
    }

    public JsfProject getJsfProject() {
        return jsfProject;
    }

    public void setJsfProject(JsfProject jsfProject) {
        this.jsfProject = jsfProject;
    }

    public String getJsfVersion() {
        return jsfVersion;
    }

    public void setJsfVersion(String jsfVersion) {
        this.jsfVersion = jsfVersion;
    }

    public String getResolvedImplJarPath() {
        return resolvedImplJarPath;
    }

    public void setResolvedImplJarPath(String resolvedImplJarPath) {
        this.resolvedImplJarPath = resolvedImplJarPath;
    }

    public String getLocalChannelRepositoryPath() {
        return localChannelRepositoryPath;
    }

    public void setLocalChannelRepositoryPath(String localChannelRepositoryPath) {
        this.localChannelRepositoryPath = localChannelRepositoryPath;
    }

    public List<URL> getRemoteMavenRepositoryUrls() {
        return remoteMavenRepositoryUrls;
    }

    public void setRemoteMavenRepositoryUrl(URL remoteMavenRepositoryUrls) {
        this.remoteMavenRepositoryUrls = List.of(remoteMavenRepositoryUrls);
    }

    public void setRemoteMavenRepositoryUrls(List<URL> remoteMavenRepositoryUrls) {
        this.remoteMavenRepositoryUrls = remoteMavenRepositoryUrls;
    }

    public String getManifestCoordinates() {
        return manifestCoordinates;
    }

    public void setManifestCoordinates(String manifestCoordinates) {
        this.manifestCoordinates = manifestCoordinates;
    }

    @Override
    protected Map<String, String> listAttributes() {
        final HashMap<String, String> attrs = new HashMap<>();
        attrs.put("makeDefault", makeDefault + "");
        attrs.put("implJarPath", implJarPath);
        attrs.put("jsfProject", jsfProject.toString());
        attrs.put("jsfVersion", jsfVersion);
        if (remoteMavenRepositoryUrls != null) {
            for (int i = 0; i < remoteMavenRepositoryUrls.size(); i++) {
                attrs.put("remoteRepositoryUrls-" + i, remoteMavenRepositoryUrls.get(i).toExternalForm());
            }
        }
        attrs.put("localChannelPath", localChannelRepositoryPath);
        attrs.put("manifestCoordinates", manifestCoordinates);
        return attrs;
    }

    @Override
    protected void acceptAttributes(Map<String, String> attributes, BiFunction<String, String, String> variableResolver) throws AutomaticInstallationParsingException {
        makeDefault = Boolean.parseBoolean(attributes.getOrDefault("makeDefault", "false"));
        implJarPath = attributes.get("implJarPath");
        jsfProject = JsfProject.valueOf(attributes.get("jsfProject"));
        jsfVersion = attributes.get("jsfVersion");
        remoteMavenRepositoryUrls = getListOfRepositories(attributes);
        localChannelRepositoryPath = attributes.get("localChannelPath");
        manifestCoordinates = attributes.get("manifestCoordinates");
    }

    private List<URL> getListOfRepositories(Map<String, String> attributes) {
        return attributes.entrySet().stream()
                .filter(entry -> entry.getKey().startsWith("remoteRepositoryUrls"))
                .map(Map.Entry::getValue)
                .map(FileUtils::asUrl)
                .collect(Collectors.toList());
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        JSFLibraryConfig config = (JSFLibraryConfig) o;
        return makeDefault == config.makeDefault && Objects.equals(implJarPath, config.implJarPath) && jsfProject == config.jsfProject && Objects.equals(jsfVersion, config.jsfVersion) && Objects.equals(localChannelRepositoryPath, config.localChannelRepositoryPath) && Objects.equals(remoteMavenRepositoryUrls, config.remoteMavenRepositoryUrls) && Objects.equals(manifestCoordinates, config.manifestCoordinates) && Objects.equals(resolvedImplJarPath, config.resolvedImplJarPath);
    }

    @Override
    public int hashCode() {
        return Objects.hash(makeDefault, implJarPath, jsfProject, jsfVersion, localChannelRepositoryPath, remoteMavenRepositoryUrls, manifestCoordinates, resolvedImplJarPath);
    }

    @Override
    public String toString() {
        return "Config{" +
                "makeDefault=" + makeDefault +
                ", implJarPath='" + implJarPath + '\'' +
                ", jsfProject=" + jsfProject +
                ", jsfVersion='" + jsfVersion + '\'' +
                ", localChannelRepositoryPath='" + localChannelRepositoryPath + '\'' +
                ", remoteMavenRepositoryUrls=" + remoteMavenRepositoryUrls +
                ", manifestCoordinates='" + manifestCoordinates + '\'' +
                ", resolvedImplJarPath='" + resolvedImplJarPath + '\'' +
                '}';
    }
}
