/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2022 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.validators;

import javax.swing.JFormattedTextField;
import javax.swing.JTextField;
import javax.swing.text.JTextComponent;
import java.util.HashMap;

import java.util.regex.Pattern;

public class PortConfigurationValidator {

    public static final int MIN_PORT_VALUE = 1;
    public static final int MAX_PORT_VALUE = 65535;
    private static final Pattern IP_ADDRESS_PATTERN = Pattern.compile("\\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\."+
            "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." +
            "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." +
            "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b");

    private static final Pattern IP_6_ADDRESS_PATTERN = Pattern.compile("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");
    private static final Pattern IP_6_COMPRESSED_ADDRESS_PATTERN = Pattern.compile("^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$");

    public boolean isIpAddressFormat(String input) {
        return isIp4AddressFormat(input) || isIp6AddressFormat(input);
    }
    public boolean isIp4AddressFormat(String input) {
        return IP_ADDRESS_PATTERN.matcher(input).matches();
    }

    public boolean isIp6AddressFormat(String input) {
        return IP_6_ADDRESS_PATTERN.matcher(input).matches() || IP_6_COMPRESSED_ADDRESS_PATTERN.matcher(input).matches();
    }

    public boolean isMulticastAddress(String input) {
        if (isIp6AddressFormat(input)) {
            Pattern p = Pattern.compile("^([fF]{2}[0-9a-fA-F]{2})$");
            final String[] ipSegments = input.split(":");
            if (ipSegments.length == 0) { // eg "::"
                return false;
            }
            return p.matcher(ipSegments[0]).matches();
        } else if (isIp4AddressFormat(input)) {
            final String firstPart = input.split("\\.")[0];
            final int value = Integer.parseInt(firstPart);
            return value >= 224 && value <=239;
        }
        return false;
    }

    public boolean portsDistinct(HashMap<String, JFormattedTextField> portFieldMap) {
        return portFieldMap.size() == portFieldMap.values().stream().map(JTextComponent::getText).distinct().count();
    }

    public boolean valueFieldEmpty(HashMap<String, JFormattedTextField> portFieldMap, HashMap<String, JTextField> ipAddressFieldMap) {
        return portFieldMap.values().stream().anyMatch(key -> key.getText().equals(""))
                || ipAddressFieldMap.values().stream().anyMatch(key -> key.getText().equals(""));
    }

    public boolean validIpAddresses(HashMap<String, JTextField> ipAddressFieldMap) {
        return ipAddressFieldMap.values().stream().allMatch(key -> isIpAddressFormat(key.getText()));
    }
}
