/*
 * 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 com.sun.enterprise.v3.server;

import com.sun.enterprise.config.serverbeans.Application;
import com.sun.enterprise.config.serverbeans.ApplicationRef;
import com.sun.enterprise.config.serverbeans.Applications;
import com.sun.enterprise.config.serverbeans.Cluster;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.ServerTags;
import com.sun.enterprise.module.bootstrap.StartupContext;
import com.sun.enterprise.util.LocalStringManagerImpl;
import com.sun.enterprise.v3.common.HTMLActionReporter;
import java.beans.PropertyChangeEvent;
import java.util.Calendar;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.glassfish.api.ActionReport;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.deployment.UndeployCommandParameters;
import org.glassfish.hk2.api.PostConstruct;
import org.glassfish.hk2.runlevel.RunLevel;
import org.glassfish.internal.api.PostStartupRunLevel;
import org.glassfish.internal.data.ApplicationInfo;
import org.glassfish.internal.data.ApplicationRegistry;
import org.glassfish.internal.deployment.Deployment;
import org.glassfish.kernel.KernelLoggerInfo;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.config.TransactionListener;
import org.jvnet.hk2.config.Transactions;
import org.jvnet.hk2.config.UnprocessedChangeEvents;

@Service
@RunLevel(PostStartupRunLevel.VAL)
public class ApplicationConfigListener implements TransactionListener, PostConstruct {

    final private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(ApplicationConfigListener.class);

    final private Logger logger = KernelLoggerInfo.getLogger();

    @Inject
    Transactions transactions;

    @Inject
    Domain domain;

    @Inject
    Applications applications;

    @Inject
    ApplicationRegistry appRegistry;

    @Inject
    Deployment deployment;

    @Inject
    StartupContext startupContext;

    @Inject @Named( ServerEnvironment.DEFAULT_INSTANCE_NAME)
    Server server;

    private final static String UPGRADE_PARAM = "-upgrade";

    public void transactionCommited( final List<PropertyChangeEvent> changes) {
        boolean isUpdatingAttribute = true;
        for (PropertyChangeEvent event : changes) {
            Object oldValue = event.getOldValue();
            Object newValue = event.getNewValue();
            if (event.getSource() instanceof Applications) {
                if (event.getPropertyName().equals(ServerTags.APPLICATION)) {
                    if (oldValue == null || newValue == null) {
                        // we are adding/removing application element here
                        // and updating existing attribute
                        isUpdatingAttribute = false;
                        break;
                    }
                }
            } else if (event.getSource() instanceof Server ||
                    event.getSource() instanceof Cluster) {
                if (event.getPropertyName().equals(
                        ServerTags.APPLICATION_REF)) {
                    if (oldValue == null || newValue == null) {
                        // we are adding/removing application-ref element here
                        // and updating existing attribute
                        isUpdatingAttribute = false;
                        break;
                    }
                }
            }
        }

        if (!isUpdatingAttribute) {
            // if we are not updating existing attribute, we should
            // skip the config listener
            return;
        }

        for (PropertyChangeEvent event : changes) {
            if (event.getSource() instanceof Application ||
                event.getSource() instanceof ApplicationRef) {
                Object oldValue = event.getOldValue();
                Object newValue = event.getNewValue();
                if (oldValue != null && newValue != null &&
                    oldValue instanceof String &&
                    newValue instanceof String &&
                    !((String)oldValue).equals((String)newValue)) {
                    // if it's an attribute change of the application
                    // element or application-ref element
                    Object parent = event.getSource();
                    String appName = null;
                    if (parent instanceof Application) {
                        appName = ((Application)parent).getName();
                    } else if (parent instanceof ApplicationRef) {
                        appName = ((ApplicationRef)parent).getRef();
                    }
                    // if it's not a user application, let's not do
                    // anything
                    if (applications.getApplication(appName) == null) {
                        return;
                    }
                    if (event.getPropertyName().equals(ServerTags.ENABLED)) {
                        // enable or disable application accordingly
                        handleAppEnableChange(event.getSource(),
                            appName, Boolean.valueOf((String)newValue));
                    } else if (event.getPropertyName().equals(ServerTags.CONTEXT_ROOT) || event.getPropertyName().equals(ServerTags.VIRTUAL_SERVERS) || event.getPropertyName().equals(ServerTags.AVAILABILITY_ENABLED)) {
                        // for other changes, reload the application
                        handleOtherAppConfigChanges(event.getSource(),
                            appName);
                    }
                }
            }
        }
    }

    public void unprocessedTransactedEvents(
        List<UnprocessedChangeEvents> changes) {
    }

    public void postConstruct() {
        Properties arguments = startupContext.getArguments();
        if (arguments != null) {
            boolean isUpgrade = Boolean.valueOf(
                arguments.getProperty(UPGRADE_PARAM));
            if (isUpgrade) {
                // we don't want to register this listener for the upgrade
                // start up
                return;
            }
        }
        transactions.addTransactionsListener(this);
    }

    private void handleAppEnableChange(Object parent,
        String appName, boolean enabled) {
        Application application = applications.getApplication(appName);
        if (application.isLifecycleModule()) {
            return;
        }
        if (enabled) {
            if (isCurrentInstanceMatchingTarget(parent)) {
                enableApplication(appName);
            }
        } else {
            if (isCurrentInstanceMatchingTarget(parent)) {
                disableApplication(appName);
            }
        }
    }

    private void handleOtherAppConfigChanges(Object parent, String appName) {
        Application application = applications.getApplication(appName);
        if (application.isLifecycleModule()) {
            return;
        }
        // reload the application for other application related
        // config changes if the application is in enabled state
        if (isCurrentInstanceMatchingTarget(parent) &&
            deployment.isAppEnabled(application)) {
            disableApplication(appName);
            enableApplication(appName);
        }
    }


    private boolean isCurrentInstanceMatchingTarget(Object parent) {
        // DAS receive all the events, so we need to figure out
        // whether we should take action on DAS depending on the event
        if (parent instanceof ApplicationRef) {
            Object grandparent = ((ApplicationRef)parent).getParent();
            if (grandparent instanceof Server) {
                Server gpServer = (Server)grandparent;
                if ( ! server.getName().equals(gpServer.getName())) {
                    return false;
                }
            } else if (grandparent instanceof Cluster) {
                if (server.isDas()) {
                    return false;
                }
            }
        }
        return true;
    }

    private void enableApplication(String appName) {
        Application app = applications.getApplication(appName);
        ApplicationRef appRef = domain.getApplicationRefInServer(server.getName(), appName);
        // if the application does not exist or application is not referenced
        // by the current server instance, do not load
        if (app == null || appRef == null) {
            return;
        }

        // if the application is not in enable state, do not load
        if (!deployment.isAppEnabled(app)) {
            return;
        }

        ApplicationInfo appInfo = appRegistry.get(appName);
        if (appInfo == null || appInfo.isLoaded()) {
            return;
        }

        long operationStartTime =
            Calendar.getInstance().getTimeInMillis();

        try {
            ActionReport report = new HTMLActionReporter();

            deployment.enable(server.getName(), app, appRef, report, logger);

            if (report.getActionExitCode().equals(ActionReport.ExitCode.SUCCESS)) {
                logger.log(Level.INFO, KernelLoggerInfo.loadingApplicationTime,
                        new Object[] { appName, (Calendar.getInstance().getTimeInMillis() - operationStartTime)});
            } else if (report.getActionExitCode().equals(ActionReport.ExitCode.WARNING)){
                logger.log(Level.WARNING, KernelLoggerInfo.loadingApplicationWarning,
                        new Object[] { appName, report.getMessage()});
            } else if (report.getActionExitCode().equals(ActionReport.ExitCode.FAILURE)) {
                throw new Exception(report.getMessage());
            }
        } catch(Exception e) {
            logger.log(Level.SEVERE, KernelLoggerInfo.loadingApplicationErrorEnable, e);
            throw new RuntimeException(e);
        }
    }

    private void disableApplication(String appName) {
        Application app = applications.getApplication(appName);
        ApplicationRef appRef = domain.getApplicationRefInServer(server.getName(), appName);
        // if the application does not exist or application is not referenced
        // by the current server instance, do not unload
        if (app == null || appRef == null) {
            return;
        }

        ApplicationInfo appInfo = appRegistry.get(appName);
        if (appInfo == null || !appInfo.isLoaded()) {
            return;
        }

        try {
            ActionReport report = new HTMLActionReporter();
            UndeployCommandParameters commandParams =
                new UndeployCommandParameters();
            commandParams.name = appName;
            commandParams.target = server.getName();
            commandParams.origin = UndeployCommandParameters.Origin.unload;
            commandParams.command = UndeployCommandParameters.Command.disable;
            deployment.disable(commandParams, app, appInfo, report, logger);

            if (report.getActionExitCode().equals(ActionReport.ExitCode.FAILURE)) {
                throw new Exception(report.getMessage());
            }
        } catch(Exception e) {
            logger.log(Level.SEVERE, KernelLoggerInfo.loadingApplicationErrorDisable, e);
            throw new RuntimeException(e);
        }
    }
}
