/*
 * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.gms;

import com.sun.enterprise.config.serverbeans.*;
import com.sun.enterprise.module.bootstrap.EarlyLogHandler;
import com.sun.enterprise.util.EarlyLogger;
import org.glassfish.api.admin.config.ConfigurationUpgrade;
import jakarta.inject.Inject;
import org.jvnet.hk2.annotations.Service;
import org.glassfish.hk2.api.PostConstruct;
import org.jvnet.hk2.config.ConfigSupport;
import org.jvnet.hk2.config.SingleConfigCode;
import org.jvnet.hk2.config.Transaction;
import org.jvnet.hk2.config.TransactionFailure;
import org.jvnet.hk2.config.types.Property;

import java.beans.PropertyVetoException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.LogRecord;

/**
 * Startup service to upgrade cluster/gms elements in domain.xml
 * @author Bhakti Mehta
 *
 */
@Service(name="gmsupgrade")
public class GMSConfigUpgrade implements ConfigurationUpgrade, PostConstruct {

    @Inject
    Clusters clusters;

    @Inject
    Configs configs;

    @Override
    public void postConstruct() {
        try {
            //This will upgrade all the cluster elements in the domain.xml
            upgradeClusterElements();

            // this will upgrade all the group-management-service elements in domain.xml
            upgradeGroupManagementServiceElements();
        } catch (Exception e) {
            LogRecord lr = new LogRecord(Level.SEVERE,
                "Failure while upgrading cluster data from V2 to V3: " + e);
            lr.setLoggerName(getClass().getName());
            EarlyLogHandler.earlyMessages.add(lr);
            throw new RuntimeException(e);
        }
    }

    private void upgradeClusterElements () throws TransactionFailure {
        List<Cluster> clusterList = clusters.getCluster();
        for (Cluster cl :clusterList) {
            ConfigSupport.apply(new ClusterConfigCode(), cl);
        }
    }

    private void upgradeGroupManagementServiceElements()
        throws TransactionFailure {
        List<Config> lconfigs = configs.getConfig();
        for (Config c : lconfigs) {
            LogRecord lr = new LogRecord(Level.FINE, "Upgrade config " + c.getName());
            lr.setLoggerName(getClass().getName());
            EarlyLogHandler.earlyMessages.add(lr);
            ConfigSupport.apply(new GroupManagementServiceConfigCode(), c);
        }
    }

    private class ClusterConfigCode implements SingleConfigCode<Cluster> {
        public Object run(Cluster cluster) throws PropertyVetoException, TransactionFailure {
            //set gms-enabled (default is true incase it may not appear in upgraded
            //domain.xml)
            String value = cluster.getHeartbeatEnabled();
            if (value != null) {
                cluster.setGmsEnabled(value);
                cluster.setHeartbeatEnabled(null);
            }

            //set gms-multicast-address the value obtained from heartbeat-address
            value = cluster.getHeartbeatAddress();
            if (value != null) {
                try {
                    cluster.setGmsMulticastAddress(value);
                } catch (Throwable t) {
                    // catch RuntimeException hk2 ValidationException.  Some values from v2 may not be valid in v3.
                }
                cluster.setHeartbeatAddress(null);
            }

            // ensure this propery is set to a valid value. Either it was missing or v2 value was invalid in v3 constraints.
            if (cluster.getGmsMulticastAddress() == null) {

                // generate a valid gms multicast address. Either heartbeataddress was missing OR had an invalid value from v2 domain.xml
                cluster.setGmsMulticastAddress(generateHeartbeatAddress());
            }

            //set gms-multicast-port the value of heartbeat-port.
            value = cluster.getHeartbeatPort();
            if (value != null) {
                try {
                    cluster.setGmsMulticastPort(value);
                } catch (Throwable t) {
                    // catch RuntimeException hk2 ValidationException. There are definitely values in v2 that are not valid in v3 for this field.
                    // There were bugs filed that this port was randomly generated with an IANA allocated port. So v3.1 min and max are more restrictive than v2 were.
                }
                cluster.setHeartbeatPort(null);
            }

            // ensure this property is set to a valid value. Either the value was missing or had a value in v2 that is considered invalid in tighter constrained v3.1.
            if (cluster.getGmsMulticastPort() == null) {
                // generate a valid gms multicastport. Either heartbeatport was not set or was set to a value that is now invalid in v3.1.
                // port range in v2 was quite large and outside the IANA recommended range being followed by v3.1.
                cluster.setGmsMulticastPort(generateHeartbeatPort());

            }

            //gms-bind-interface is an attribute of cluster in 3.1
            Property prop  = cluster.getProperty("gms-bind-interface-address");
            if (prop != null && prop.getValue() != null) {
                cluster.setGmsBindInterfaceAddress(prop.getValue());
                List<Property> props = cluster.getProperty();
                props.remove(prop);
            } else {
                value = cluster.getGmsBindInterfaceAddress();
                if (value == null) {
                    cluster.setGmsBindInterfaceAddress(String.format(
                            "${GMS-BIND-INTERFACE-ADDRESS-%s}",
                            cluster.getName()));
                }
            }
            Property gmsListenerPort = cluster.createChild(Property.class);
            gmsListenerPort.setName("GMS_LISTENER_PORT");
            gmsListenerPort.setValue(String.format("${GMS_LISTENER_PORT-%s}", cluster.getName()));
            cluster.getProperty().add(gmsListenerPort);
            return cluster;
        }
    }

    static private class GroupManagementServiceConfigCode implements SingleConfigCode<Config> {
        public Object run(Config config) throws PropertyVetoException, TransactionFailure {
            GroupManagementService gms = config.getGroupManagementService();
            Transaction t = Transaction.getTransaction(config);
            gms = t.enroll(gms);
            String value = gms.getPingProtocolTimeoutInMillis();
            if (value != null) {
                try {
                    gms.setGroupDiscoveryTimeoutInMillis(value);
                } catch (Throwable re) {
                    // catch RuntimeException hk2 ValidationException. if v2 value is not valid for v3, just rely on v3 default
                }
                gms.setPingProtocolTimeoutInMillis(null);
            } // else null for server-config

            FailureDetection fd = gms.getFailureDetection();
            fd = t.enroll(fd);
            value = gms.getFdProtocolTimeoutInMillis();
            if (value != null){
                try {
                    fd.setHeartbeatFrequencyInMillis(value);
                } catch (Throwable re) {
                    // catch RuntimeException hk2 ValidationException. if v2 value is not valid for v3, just rely on v3 default
                }
                gms.setFdProtocolTimeoutInMillis(null);
            } // else  null for server-config

            value = gms.getFdProtocolMaxTries();
            if (value != null) {
                try {
                    fd.setMaxMissedHeartbeats(value);
                } catch (Throwable re) {
                    // catch RuntimeException hk2 ValidationException. if v2 value is not valid for v3, just rely on v3 default
                }
                gms.setFdProtocolMaxTries(null);
            } // else null for server config

            value = gms.getVsProtocolTimeoutInMillis();
            if (value != null) {
                try {
                    fd.setVerifyFailureWaittimeInMillis(value);
                } catch (Throwable re) {
                    // catch RuntimeException hk2 ValidationException. if v2 value is not valid for v3, just rely on v3 default
                }
                gms.setVsProtocolTimeoutInMillis(null);
            } // else null for server-config

            Property prop = gms.getProperty("failure-detection-tcp-retransmit-timeout");
            if (prop != null && prop.getValue() != null ) {
                try {
                    fd.setVerifyFailureConnectTimeoutInMillis(prop.getValue().trim());
                } catch (Throwable re) {
                    // catch RuntimeException hk2 ValidationException. if v2 value is not valid for v3, just rely on v3 default
                }
                List<Property> props = gms.getProperty();
                props.remove(prop);
            } //else v3.1 default value for VerifyFailureConnectTimeoutInMillis is sufficient.

            // remove v2.1 attributes that are no longer needed.  No info to transfer to v3.1 gms config.
            if (gms.getMergeProtocolMinIntervalInMillis() != null) {
                gms.setMergeProtocolMinIntervalInMillis(null);
            }
            if (gms.getMergeProtocolMaxIntervalInMillis() != null) {
                gms.setMergeProtocolMaxIntervalInMillis(null);
            }

            return config;
        }
    }

    // copied from config-api com.sun.enterprise.config.serverbeans.Cluster.java in order to generate a valid v3.1 value for this required properties.
    private String generateHeartbeatPort() {
        final int MIN_GMS_MULTICAST_PORT = 2048;
        final int MAX_GMS_MULTICAST_PORT = 32000;

        int portInterval = MAX_GMS_MULTICAST_PORT - MIN_GMS_MULTICAST_PORT;
        return Integer.toString(Math.round((float)(Math.random() * portInterval)) + MIN_GMS_MULTICAST_PORT);
    }

    // copied from config-api com.sun.enterprise.config.serverbeans.Cluster.java in order to generate a valid v3.1 value for this required properties.
    private String generateHeartbeatAddress() {
        final int MAX_GMS_MULTICAST_ADDRESS_SUBRANGE = 255;

        final StringBuffer heartbeatAddressBfr = new StringBuffer("228.9.");
        heartbeatAddressBfr.append(Math.round(Math.random() * MAX_GMS_MULTICAST_ADDRESS_SUBRANGE))
                .append('.')
                .append(Math.round(Math.random() * MAX_GMS_MULTICAST_ADDRESS_SUBRANGE));
        return heartbeatAddressBfr.toString();
    }
}
