/*
 *  Copyright 2022 Red Hat
 *
 *  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
 *
 *      https://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.hal.core.finder;

import javax.inject.Inject;

import org.jboss.hal.spi.Callback;

import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.HandlerRegistration;
import com.gwtplatform.mvp.client.proxy.NavigationEvent;

import static elemental2.dom.DomGlobal.clearTimeout;
import static elemental2.dom.DomGlobal.console;
import static elemental2.dom.DomGlobal.document;
import static elemental2.dom.DomGlobal.setTimeout;
import static org.jboss.hal.resources.CSS.withProgress;
import static org.jboss.hal.resources.UIConstants.MEDIUM_TIMEOUT;

/**
 * Class to monitor item actions and show a progress indicator if they take longer than a given timeout. Relies on an unique
 * item id implemented by {@link ItemDisplay#getId()} and specified in the column setup.
 */
public class ItemMonitor {

    public static void startProgress(final String itemId) {
        elemental2.dom.Element element = document.getElementById(itemId);
        if (element != null && !element.classList.contains(withProgress)) {
            element.classList.add(withProgress);
            console.log("### Started progress for item %s", itemId);
        }
    }

    public static void stopProgress(final String itemId) {
        elemental2.dom.Element element = document.getElementById(itemId);
        if (element != null) {
            element.classList.remove(withProgress);
            console.log("### Stopped progress for item %s", itemId);
        }
    }

    private final EventBus eventBus;
    private double timeoutHandle = -1;
    private HandlerRegistration handlerRegistration;

    @Inject
    public ItemMonitor(final EventBus eventBus) {
        this.eventBus = eventBus;
    }

    /**
     * Wraps and monitors an item action which triggers a place request.
     */
    public <T> ItemActionHandler<T> monitorPlaceRequest(final String itemId, final String nameToken,
            final Callback callback) {
        return itm -> {
            callback.execute();
            startProgress(itemId);
            timeoutHandle = setTimeout(whatever -> handlerRegistration = eventBus.addHandler(NavigationEvent.getType(),
                    navigationEvent -> {
                        if (nameToken.equals(navigationEvent.getRequest().getNameToken())) {
                            handlerRegistration.removeHandler();
                            clearTimeout(timeoutHandle);
                            stopProgress(itemId);
                        }
                    }), MEDIUM_TIMEOUT);
        };
    }
}

@@ -765,58 +765,51 @@
 om.g
-oogle.web.bindery.event.shared.HandlerRegistration
+wtplatform.mvp.client.proxy.NavigationEvent
 ;%0Aim
@@ -860,337 +860,121 @@
 tion
-Event;%0A%0Aimport static elemental2.dom.DomGlobal.clearTimeout;%0Aimport static elemental2.dom.DomGlobal.console;%0Aimport static elemental2.dom.DomGlobal.document;%0Aimport static elemental2.dom.DomGlobal.setTimeout;%0Aimport static org.jboss.hal.resources.CSS.withProgress;%0Aimport static org.jboss.hal.resources.UIConstants.MEDIUM_TIMEOUT
+Handler;%0A%0Aimport static elemental2.dom.DomGlobal.document;%0Aimport static org.jboss.hal.resources.CSS.withProgress
 ;%0A%0A/
@@ -1219,16 +1219,45 @@
 Monitor 
+implements NavigationHandler 
 %7B%0A%0A    p
@@ -1514,77 +1514,8 @@
 s);%0A
-            console.log(%22### Started progress for item %25s%22, itemId);%0A
     
@@ -1755,98 +1755,110 @@
     
+%7D%0A
     
-console.log(%22### Stopped progress for item %25s%22,
+%7D%0A%0A    private String
  itemId
-)
 ;%0A    
- 
-   %7D%0A    %7D%0A%0A    private 
+private String nameToken;%0A%0A    @Inject%0A    public ItemMonitor(
 fina
@@ -1880,161 +1880,161 @@
 tBus
-;
+) %7B
 %0A    
-private double timeoutHandle = -1;%0A    private HandlerRegistration handlerRegistration;%0A%0A    @Inject%0A    public ItemMonitor(final EventBus e
+    eventBus.addHandler(NavigationEvent.getType(), this);%0A    %7D%0A%0A    @Override%0A    public void onNavigation(final NavigationEvent navigationE
 vent
-Bus
 ) %7B%0A
@@ -2045,33 +2045,139 @@
     
-this.eventBus = eventBus;
+if (activeMonitor() && nameToken.equals(navigationEvent.getRequest().getNameToken())) %7B%0A            stopCurrentMonitor();%0A        %7D
 %0A   
@@ -2482,31 +2482,41 @@
    start
-Progress(itemId
+Monitor(itemId, nameToken
 );%0A     
@@ -2522,392 +2522,416 @@
     
+%7D;%0A
     
-timeoutHandle = setTimeout(whatever -%3E handlerRegistration = eventBus.addHandler(NavigationEvent.getType(),%0A                    navigationEvent -%3E %7B%0A                        if (nameToken.equals(navigationEvent.getRequest().getNameToken())) %7B%0A                            handlerRegistration.removeHandler();%0A                            clearTimeout(timeoutHandle);%0A                
+%7D%0A%0A    private void startMonitor(final String itemId, final String nameToken) %7B%0A        // first make sure to cancel a running monitor%0A        stopCurrentMonitor();%0A%0A        // register new monitor and start progress indicator%0A        this.itemId = itemId;%0A        this.nameToken = nameToken;%0A        startProgress(itemId);%0A    %7D%0A%0A    private void stopCurrentMonitor() %7B%0A        if (itemId != null) %7B%0A
     
@@ -2964,32 +2964,34 @@
 d);%0A        
+%7D%0A
         
         %7D%0A  
@@ -2982,68 +2982,154 @@
     
-        %7D%0A    
+this.itemId = null;%0A        this.nameToken = null;%0A
     
+%7D%0A%0A
     
-        %7D), MEDIUM_TIMEOUT);%0A        %7D
+private boolean activeMonitor() %7B%0A        return itemId != null && nameToken != null
 ;%0A  

Fix ItemMonitor