/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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.LanguageUtils;
import org.jboss.installer.core.ValidationResult;
import org.jboss.installer.postinstall.task.CredentialStoreInstallTask;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;

public class CredentialStoreValidator {

    public static final String EMPTY_FIELD_ERROR = "credential_store.ic.error";
    public static final String PATH_IS_DIRECTORY_ERROR = "credential_store.path.is.directory";
    public static final String PATH_NOT_WRITABLE_ERROR = "credential_store.path.no.write.permission";
    private final LanguageUtils langUtils;
    private final Path targetFolder;

    public CredentialStoreValidator(LanguageUtils langUtils, Path targetFolder) {
        this.langUtils = langUtils;
        this.targetFolder = targetFolder;
    }

    public ValidationResult validate(CredentialStoreInstallTask.Config config) {
        // storeName not empty
        if (config.getStoreName() == null || config.getStoreName().isEmpty()) {
            return ValidationResult.error(langUtils.getString(EMPTY_FIELD_ERROR));
        }
        // password not empty
        if (config.getPassword() == null || config.getPassword().isEmpty()) {
            return ValidationResult.error(langUtils.getString(EMPTY_FIELD_ERROR));
        }
        if (config.getPath() == null || config.getPath().isEmpty()) {
            return ValidationResult.error(langUtils.getString(EMPTY_FIELD_ERROR));
        }

        final ValidationResult result = PathValidator.newInstance("cred-store", langUtils).validate(config.getPath());
        if (result.getResult() != ValidationResult.Result.OK) {
            return result;
        }

        File file = new File(config.getPath());
        // store path is not directory and is writable
        if (file.exists() && file.isDirectory()) {
            return ValidationResult.error(langUtils.getString(PATH_IS_DIRECTORY_ERROR));
        } else if (!isWritable(file)) {
            return ValidationResult.error(langUtils.getString(PATH_NOT_WRITABLE_ERROR));
        }

        if (file.exists()) {
            return KeystoreCredentialsValidator.credentialStoreValidator(langUtils)
                    .validate(file.toString(), config.getPassword(), targetFolder, true);
        } else {
            return ValidationResult.ok();
        }
    }

    private boolean isWritable(File file) {
        final File existingParent = getExistingParent(file);
        if (existingParent == null) {
            return false;
        }
        return Files.isWritable(existingParent.toPath());
    }

    private File getExistingParent(File dir) {
        while (dir != null && !dir.exists()) {
            dir = dir.getParentFile();
        }
        return dir;
    }
}
