/*
 * 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.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;

import org.jboss.installer.auto.AutomaticInstallationParsingException;
import org.jboss.installer.core.FlatListPostInstallConfig;
import org.jboss.installer.postinstall.ldap.LdapModel;

public class LDAPManagementAuthConfig extends FlatListPostInstallConfig {

    public static final String PASSWORD_PROPERTY_NAME = "ldap_setup.password";
    private String url;
    private String dn;
    private String password;
    private String connection;
    private String filter;
    private boolean recursive;
    private FilterType filterType;
    private String baseDN;
    private String realmName;

    public LDAPManagementAuthConfig() {
    }

    public LDAPManagementAuthConfig(String connection, String url, String dn, String password) {
        this.connection = connection;
        this.url = url;
        this.dn = dn;
        this.password = password;
    }

    public LdapModel toModel() {
        final LdapModel model = new LdapModel();
        model.setRealmName(realmName);
        model.setConnection(connection, url, dn, password);
        model.setUserFilter(filterType, filter, baseDN, "userPassword", recursive);

        return model;
    }

    public String getUrl() {
        return url;
    }

    public String getDn() {
        return dn;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPassword() {
        return password;
    }

    public String getConnection() {
        return connection;
    }

    public void setFilter(String filter) {
        this.filter = filter;
    }

    public String getFilter() {
        return filter;
    }

    public void setRecursive(boolean recursive) {
        this.recursive = recursive;
    }

    public boolean isRecursive() {
        return recursive;
    }

    public void setFilterType(FilterType filterType) {
        this.filterType = filterType;
    }

    public FilterType getFilterType() {
        return filterType;
    }

    public void setBaseDN(String baseDN) {
        this.baseDN = baseDN;
    }

    public String getBaseDN() {
        return baseDN;
    }

    public void setRealmName(String realmName) {
        this.realmName = realmName;
    }

    public String getRealmName() {
        return realmName;
    }

    @Override
    protected Map<String, String> listAttributes() {
        final HashMap<String, String> attrs = new HashMap<>();
        attrs.put("url", url);
        attrs.put("dn", dn);
        attrs.put("connection", connection);
        attrs.put("filter", filter);
        attrs.put("recursive", recursive + "");
        attrs.put("filterType", filterType.toString());
        attrs.put("baseDN", baseDN);
        attrs.put("realmName", realmName);
        return attrs;
    }

    @Override
    protected Set<String> listVariables() {
        final HashSet<String> vars = new HashSet<>();
        vars.add(PASSWORD_PROPERTY_NAME);
        return vars;
    }

    @Override
    protected void acceptAttributes(Map<String, String> attributes, BiFunction<String, String, String> variableResolver) throws AutomaticInstallationParsingException {
        password = variableResolver.apply(PASSWORD_PROPERTY_NAME, "LDAP authentication password");
        url = attributes.get("url");
        dn = attributes.get("dn");
        connection = attributes.get("connection");
        filter = attributes.get("filter");
        recursive = Boolean.parseBoolean(attributes.getOrDefault("recursive", "false"));
        filterType = FilterType.valueOf(attributes.get("filterType"));
        baseDN = attributes.get("baseDN");
        realmName = attributes.get("realmName");
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        LDAPManagementAuthConfig config = (LDAPManagementAuthConfig) o;
        return recursive == config.recursive && Objects.equals(url, config.url) && Objects.equals(dn, config.dn) && Objects.equals(password, config.password) && Objects.equals(connection, config.connection) && Objects.equals(filter, config.filter) && filterType == config.filterType && Objects.equals(baseDN, config.baseDN) && Objects.equals(realmName, config.realmName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(url, dn, password, connection, filter, recursive, filterType, baseDN, realmName);
    }

    public enum FilterType {
        USERNAME("ldap_realm_screen.filter_type.username"), ADVANCED("ldap_realm_screen.filter_type.advanced");

        private final String key;

        FilterType(String key) {
            this.key = key;
        }

        public static String[] getLabels() {
            String[] res = new String[FilterType.values().length];
            for (int i = 0; i < FilterType.values().length; i++) {
                res[i] = FilterType.values()[i].key;
            }
            return res;
        }

        public String getKey() {
            return key;
        }
    }
}
