/*
 * Copyright 2022 Red Hat, Inc. and/or its affiliates
 * and other 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.validators;

import org.jboss.installer.core.FileUtils;
import org.jboss.installer.core.LanguageUtils;
import org.jboss.installer.core.ValidationResult;
import org.jboss.installer.postinstall.task.JsfLibraryTask;

import java.io.IOException;
import java.util.jar.JarFile;

public class JsfValidator {

    public static final String JSF_IMPL_JAR_EMPTY_ERROR = "jsf_install.impl.jar.empty.error";
    public static final String JSF_VERSION_NOT_SUPPORTED_KEY = "jsf_install.version.not.supported";
    public static final String JSF_VERSION_NOT_DETECTED_KEY = "jsf_install.version.not.detected";
    public static final String JSF_PROJECT_NOT_DETECTED_KEY = "jsf_install.project.not.detected";
    public static final String JSF_PROJECT_MISMATCHED_KEY = "jsf_install.project.not_mojarra";
    public static final String JSF_JAR_NOT_IMPL_KEY = "jsf_install.jar.detect_impl";
    public static final String JSF_INVALID_FILE_KEY = "jsf_install.jar.invalid_file";
    public static final String VERSION_MISMATCHED_KEY = "jsf_install.version.mismatched";
    private final JsfUtils jsfUtils;
    private final LanguageUtils langUtils;

    public JsfValidator(JsfUtils jsfUtils, LanguageUtils langUtils) {
        this.jsfUtils = jsfUtils;
        this.langUtils = langUtils;
    }

    public ValidationResult validate(JsfLibraryTask.Config config) {
        final JsfLibraryTask.Config.JsfProject userProvidedJsfProject = config.getJsfProject();

        final String implJarPath = config.getImplJarPath();
        if (implJarPath == null) {
            return ValidationResult.error(langUtils.getString(JSF_IMPL_JAR_EMPTY_ERROR));
        }

        final JarFile implJarFile;
        try {
            implJarFile = FileUtils.getJarFromPath(implJarPath);
        } catch (IOException e) {
            return ValidationResult.error(langUtils.getString(JSF_INVALID_FILE_KEY, implJarPath));
        }

        final ValidationResult result = CombiningValidator.of(
                () -> validateJarContainsImplementation(implJarPath, implJarFile),
                () -> validateProject(userProvidedJsfProject, implJarPath, implJarFile),
                () -> verifyVersionFound(implJarPath)).validate();
        return result;
    }

    private ValidationResult validateProject(JsfLibraryTask.Config.JsfProject userProvidedJsfProject, String implJarPath, JarFile implJarFile) {
        try {
            final JsfLibraryTask.Config.JsfProject implProject = jsfUtils.getProject(implJarFile);
            // verify the entered value matches detected ones
            if (implProject == null) {
                return ValidationResult.warning(langUtils.getString(JSF_PROJECT_NOT_DETECTED_KEY, implJarPath));
            }
            if (implProject != null && implProject != userProvidedJsfProject) {
                return ValidationResult.error(langUtils.getString(JSF_PROJECT_MISMATCHED_KEY, implProject.toString()));
            }
        } catch (IOException e) {
            return ValidationResult.warning(langUtils.getString(JSF_PROJECT_NOT_DETECTED_KEY, implJarPath));
        }
        return ValidationResult.ok();
    }

    private ValidationResult validateJarContainsImplementation(String implJarPath, JarFile implJarFile) {
        try {
            if (!jsfUtils.verifyIsImpl(implJarFile)) {
                return ValidationResult.warning(langUtils.getString(JSF_JAR_NOT_IMPL_KEY, implJarPath));
            } else {
                return ValidationResult.ok();
            }
        } catch (IOException e) {
            return ValidationResult.warning(langUtils.getString(JSF_JAR_NOT_IMPL_KEY, implJarPath));
        }
    }

    private ValidationResult verifyVersionFound(String implJarPath) {
        try {
            final String version = jsfUtils.getVersion(FileUtils.getJarFromPath(implJarPath));
            if (version == null || version.isEmpty()) {
                return ValidationResult.warning(langUtils.getString(JSF_VERSION_NOT_DETECTED_KEY));
            }
            final String implVersion = jsfUtils.cleanedVer(version);
            if (implVersion == null) {
                return ValidationResult.error(langUtils.getString(JSF_VERSION_NOT_SUPPORTED_KEY, version));
            } else {
                return ValidationResult.ok();
            }
        } catch (IOException e) {
            return ValidationResult.warning(langUtils.getString(JSF_VERSION_NOT_DETECTED_KEY));
        }
    }

}
