/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.products.ov.config.cli;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public enum Action {

    GEN_ROOT("-generate") {
        @Override
        public List<ActionParams> getActionParams() {

            return Arrays.asList(ActionParams.PLATFORM_NAME, ActionParams.OUTPUT_FOLDER);

        }
    },
    CERT_TENANT("-certificate") {
        @Override
        public List<ActionParams> getActionParams() {
            return Arrays.asList(ActionParams.KEYSTORE_PATH, ActionParams.CSR_PATH, ActionParams.OUTPUT_FOLDER);
        }
    },

    GEN_LOGGING_KEYS("-loggingkeys") {
        @Override
        public List<ActionParams> getActionParams() {
            return Arrays.asList(ActionParams.KEYSTORE_PATH, ActionParams.SERVICES_NAMES_PATH,
                ActionParams.OUTPUT_FOLDER);
        }
    },
    GEN_SYSTEM_KEYS("-systemkeys") {
        @Override
        public List<ActionParams> getActionParams() {
            return Arrays.asList(ActionParams.TENANT_NAME, ActionParams.KEYSTORE_PATH, ActionParams.SERVICES_NAMES_PATH,
                ActionParams.OUTPUT_FOLDER);
        }
    },
    GEN_CCN_KEYS("-controlComponentNodeKeys") {
        @Override
        public List<ActionParams> getActionParams() {
            return Arrays.asList(ActionParams.KEYSTORE_PATH, ActionParams.CONTROL_COMPONENTS_NODES_PATH,
                ActionParams.OUTPUT_FOLDER);
        }
    },
    INSTALL_PLATFORM("-installPlatform") {
        @Override
        public List<ActionParams> getActionParams() {
            return Arrays.asList(ActionParams.PLATFORM_ROOT_CA_CERT_PATH,
                ActionParams.PLATFORM_ROOT_CA_ISSUER_CERT_PATH, ActionParams.LOGGING_KEYSTORES_FOLDER,
                ActionParams.SERVICES_NAMES_PATH, ActionParams.PASSWORD);
        }
    },
    INSTALL_TENANT("-installTenant") {
        @Override
        public List<ActionParams> getActionParams() {
            return Arrays.asList(ActionParams.TENANT_ID, ActionParams.TENANT_CERT_PATH,
                ActionParams.SYSTEM_KEYSTORES_FOLDER, ActionParams.PASSWORD);
        }
    },

    INSTALL_TENANT_BY_SERVICE("-installTenantService") {
        @Override
        public List<ActionParams> getActionParams() {

            return Arrays.asList(ActionParams.TENANT_ID, ActionParams.TENANT_CERT_PATH,
                ActionParams.SYSTEM_KEYSTORES_FOLDER, ActionParams.SERVICES_NAMES_PATH, ActionParams.PASSWORD);
        }
    };

    private static final int PARAMTER_VALUE_OFFSET_AFTER_KEY = 1;

    private static final int PARAMETER_KEY_VALUE_PLACEHOLDER_RATIO = 2;

    private String actionName;

    Action(final String actionName) {
        this.actionName = actionName;
    }

    public String getActionName() {
        return actionName;
    }

    public abstract List<ActionParams> getActionParams();

    public List<String> getParamsName() {
        return getActionParams().stream().map(x -> x.getName()).collect(Collectors.toList());
    }

    public Map<String, String> validateAndArrange(final String[] inputParams) {

        List<ActionParams> actionParams = getActionParams();
        List<ActionParams> mandatory =
            actionParams.stream().filter(ap -> !ap.isOptional()).collect(Collectors.toList());
        List<String> paramsNames = getParamsName();

        Map<String, String> parameter2Value = new HashMap<>();
        if (inputParams.length % PARAMETER_KEY_VALUE_PLACEHOLDER_RATIO != 0) {
            throwInvalidSetOfParamsException(paramsNames);
        }
        int totalParams = inputParams.length / PARAMETER_KEY_VALUE_PLACEHOLDER_RATIO;
        if (!(mandatory.size() <= totalParams && totalParams <= actionParams.size())) {
            throwInvalidSetOfParamsException(paramsNames);
        }

        for (int i = 0; i < inputParams.length; i += PARAMETER_KEY_VALUE_PLACEHOLDER_RATIO) {
            if (paramsNames.contains(inputParams[i]) && ((i + PARAMTER_VALUE_OFFSET_AFTER_KEY) < inputParams.length)) {

                String value = inputParams[i + PARAMTER_VALUE_OFFSET_AFTER_KEY];
                if (value == null || value.isEmpty()) {
                    throw new IllegalArgumentException("An invalid value was found for parameter " + inputParams[i]);
                }
                parameter2Value.put(inputParams[i], value);
            } else {
                throw new IllegalArgumentException(
                    "The given parameters are incorrect. The expected ones are: " + paramsNames);
            }
        }

        return parameter2Value;
    }

    private void throwInvalidSetOfParamsException(List<String> paramsNames) {
        throw new IllegalArgumentException("Invalid set of parameters passed. Expected: " + paramsNames);
    }

}
