package org.ovirt.engine.ui.webadmin.plugin;

import java.util.logging.Logger;

import org.ovirt.engine.ui.common.auth.CurrentUser;
import org.ovirt.engine.ui.common.auth.UserLoginChangeEvent;
import org.ovirt.engine.ui.common.auth.UserLoginChangeEvent.UserLoginChangeHandler;
import org.ovirt.engine.ui.webadmin.plugin.PluginManager.PluginInvocationCondition;
import org.ovirt.engine.ui.webadmin.plugin.entity.EntityObject;
import org.ovirt.engine.ui.webadmin.plugin.jsni.JsArrayHelper;
import org.ovirt.engine.ui.webadmin.plugin.restapi.RestApiSessionAcquiredEvent;
import org.ovirt.engine.ui.webadmin.plugin.restapi.RestApiSessionAcquiredEvent.RestApiSessionAcquiredHandler;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.ClusterSelectionChangeEvent;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.ClusterSelectionChangeEvent.ClusterSelectionChangeHandler;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.DataCenterSelectionChangeEvent;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.DataCenterSelectionChangeEvent.DataCenterSelectionChangeHandler;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.DiskSelectionChangeEvent;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.DiskSelectionChangeEvent.DiskSelectionChangeHandler;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.HostSelectionChangeEvent;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.HostSelectionChangeEvent.HostSelectionChangeHandler;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.StorageSelectionChangeEvent;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.StorageSelectionChangeEvent.StorageSelectionChangeHandler;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.TemplateSelectionChangeEvent;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.TemplateSelectionChangeEvent.TemplateSelectionChangeHandler;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.VirtualMachineSelectionChangeEvent;
import org.ovirt.engine.ui.webadmin.section.main.presenter.tab.VirtualMachineSelectionChangeEvent.VirtualMachineSelectionChangeHandler;
import org.ovirt.engine.ui.webadmin.system.MessageEventData;
import org.ovirt.engine.ui.webadmin.system.MessageReceivedEvent;
import org.ovirt.engine.ui.webadmin.system.MessageReceivedEvent.MessageReceivedHandler;

import com.google.gwt.event.shared.EventBus;
import com.google.inject.Inject;

/**
 * Handles WebAdmin application events to be consumed by UI plugins.
 * <p>
 * Should be bound as GIN eager singleton, created early on during application startup.
 */
public class PluginEventHandler {

    private static final Logger logger = Logger.getLogger(PluginEventHandler.class.getName());

    @Inject
    public PluginEventHandler(EventBus eventBus, final PluginManager manager, final CurrentUser user) {
        // User login and logout
        eventBus.addHandler(UserLoginChangeEvent.getType(), new UserLoginChangeHandler() {
            @Override
            public void onUserLoginChange(UserLoginChangeEvent event) {
                if (user.isLoggedIn()) {
                    manager.invokePluginsNowOrLater("UserLogin", //$NON-NLS-1$
                            JsArrayHelper.createStringArray(user.getFullUserName(), user.getUserId()));
                } else {
                    manager.invokePluginsNowOrLater("UserLogout", null); //$NON-NLS-1$
                }
            }
        });

        // Engine REST API session management
        eventBus.addHandler(RestApiSessionAcquiredEvent.getType(), new RestApiSessionAcquiredHandler() {
            @Override
            public void onRestApiSessionAcquired(RestApiSessionAcquiredEvent event) {
                manager.invokePluginsNowOrLater("RestApiSessionAcquired", //$NON-NLS-1$
                        JsArrayHelper.createStringArray(event.getSessionId()));
            }
        });

        // Standard main tab item selection handling
        eventBus.addHandler(ClusterSelectionChangeEvent.getType(), new ClusterSelectionChangeHandler() {
            @Override
            public void onClusterSelectionChange(ClusterSelectionChangeEvent event) {
                manager.invokePluginsNow("ClusterSelectionChange", EntityObject.arrayFrom(event.getSelectedItems())); //$NON-NLS-1$
            }
        });
        eventBus.addHandler(DataCenterSelectionChangeEvent.getType(), new DataCenterSelectionChangeHandler() {
            @Override
            public void onDataCenterSelectionChange(DataCenterSelectionChangeEvent event) {
                manager.invokePluginsNow("DataCenterSelectionChange", EntityObject.arrayFrom(event.getSelectedItems())); //$NON-NLS-1$
            }
        });
        eventBus.addHandler(DiskSelectionChangeEvent.getType(), new DiskSelectionChangeHandler() {
            @Override
            public void onDiskSelectionChange(DiskSelectionChangeEvent event) {
                manager.invokePluginsNow("DiskSelectionChange", EntityObject.arrayFrom(event.getSelectedItems())); //$NON-NLS-1$
            }
        });
        eventBus.addHandler(HostSelectionChangeEvent.getType(), new HostSelectionChangeHandler() {
            @Override
            public void onHostSelectionChange(HostSelectionChangeEvent event) {
                manager.invokePluginsNow("HostSelectionChange", EntityObject.arrayFrom(event.getSelectedItems())); //$NON-NLS-1$
            }
        });
        eventBus.addHandler(StorageSelectionChangeEvent.getType(), new StorageSelectionChangeHandler() {
            @Override
            public void onStorageSelectionChange(StorageSelectionChangeEvent event) {
                manager.invokePluginsNow("StorageSelectionChange", EntityObject.arrayFrom(event.getSelectedItems())); //$NON-NLS-1$
            }
        });
        eventBus.addHandler(TemplateSelectionChangeEvent.getType(), new TemplateSelectionChangeHandler() {
            @Override
            public void onTemplateSelectionChange(TemplateSelectionChangeEvent event) {
                manager.invokePluginsNow("TemplateSelectionChange", EntityObject.arrayFrom(event.getSelectedItems())); //$NON-NLS-1$
            }
        });
        eventBus.addHandler(VirtualMachineSelectionChangeEvent.getType(), new VirtualMachineSelectionChangeHandler() {
            @Override
            public void onVirtualMachineSelectionChange(VirtualMachineSelectionChangeEvent event) {
                manager.invokePluginsNow("VirtualMachineSelectionChange", EntityObject.arrayFrom(event.getSelectedItems())); //$NON-NLS-1$
            }
        });

        // Cross-window messaging
        eventBus.addHandler(MessageReceivedEvent.getType(), new MessageReceivedHandler() {
            @Override
            public void onMessageReceived(MessageReceivedEvent event) {
                final MessageEventData eventData = event.getData();

                manager.invokePluginsNowOrLater("MessageReceived", //$NON-NLS-1$
                        JsArrayHelper.createMixedArray(eventData.getData(), eventData.getSourceWindow()),
                        new PluginInvocationCondition() {
                            @Override
                            public boolean canInvoke(Plugin plugin) {
                                if (eventData.originMatches(plugin.getApiOptionsObject().getAllowedMessageOrigins())) {
                                    return true;
                                }

                                logger.info("Plugin [" + plugin.getName() //$NON-NLS-1$
                                        + "] rejected message event for origin [" + eventData.getOrigin() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
                                return false;
                            }
                        });
            }
        });
    }

}
