/*
 *  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;

import javax.inject.Inject;

import org.jboss.elemento.Elements;
import org.jboss.hal.flow.Progress;
import org.jboss.hal.resources.Names;
import org.jboss.hal.resources.Resources;
import org.jboss.hal.spi.Footer;
import org.jboss.hal.spi.Message;
import org.jboss.hal.spi.MessageEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gwt.core.client.GWT;
import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.mvp.client.proxy.PlaceManager;

import static elemental2.dom.DomGlobal.document;
import static org.jboss.hal.resources.CSS.withProgress;

public class ExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(ExceptionHandler.class);
    private static boolean pendingLifecycleAction = false;

    static void setPendingLifecycleAction(boolean value) {
        pendingLifecycleAction = value;
        logger.debug("ExceptionHandler.pendingLifecycleAction = {}", pendingLifecycleAction);
    }

    private final EventBus eventBus;
    private final PlaceManager placeManager;
    private final Progress progress;
    private final Resources resources;

    @Inject
    public ExceptionHandler(EventBus eventBus,
            PlaceManager placeManager,
            @Footer Progress progress,
            Resources resources) {
        this.eventBus = eventBus;
        this.placeManager = placeManager;
        this.progress = progress;
        this.resources = resources;
    }

    public void afterBootstrap() {
        GWT.setUncaughtExceptionHandler(e -> {
            if (!pendingLifecycleAction) {
                String errorMessage = e != null ? e.getMessage() : Names.NOT_AVAILABLE;
                logger.error("Uncaught exception: {}", errorMessage);
                placeManager.unlock();
                progress.finish();
                stopProgress();
                MessageEvent.fire(eventBus, Message.error(resources.messages().unknownError(), errorMessage));
            }
        });
    }

    private void stopProgress() {
        Elements.stream(document.querySelectorAll("." + withProgress))
                .forEach(element -> element.classList.remove(withProgress));
    }
}

@@ -1127,48 +1127,296 @@
 ort 
-static elemental2.dom.DomGlobal.document
+elemental2.dom.Event;%0Aimport elemental2.dom.EventInit;%0Aimport elemental2.promise.Promise;%0Aimport jsinterop.annotations.JsPackage;%0Aimport jsinterop.annotations.JsType;%0Aimport jsinterop.base.Js;%0A%0Aimport static elemental2.dom.DomGlobal.document;%0Aimport static elemental2.dom.DomGlobal.window
 ;%0Aim
@@ -2368,24 +2368,302 @@
 otstrap() %7B%0A
+        window.addEventListener(%22unhandledrejection%22, e -%3E %7B%0A            if (!pendingLifecycleAction) %7B%0A                PromiseRejectionEvent event = Js.cast(e);%0A                handleError(%22Unhandled promise rejection%22, String.valueOf(event.reason));%0A            %7D%0A        %7D);%0A
         GWT.
@@ -2760,29 +2760,41 @@
     
-String errorMessage =
+handleError(%22Uncaught exception%22,
  e !
@@ -2838,16 +2838,17 @@
 VAILABLE
+)
 ;%0A      
@@ -2854,53 +2854,133 @@
     
+   %7D%0A
        
-logger.error(%22Uncaught exception
+ %7D);%0A    %7D%0A%0A    private void handleError(String type, String errorMessage) %7B%0A        logger.error(%22%7B%7D
 : %7B%7D%22,
+ type,
  err
@@ -2999,24 +2999,16 @@
         
-  
-      
 placeMan
@@ -3030,24 +3030,16 @@
         
-  
-      
 progress
@@ -3061,28 +3061,144 @@
     
-        stop
+Elements.stream(document.querySelectorAll(%22.%22 + withProgress))%0A                .forEach(element -%3E element.classList.remove(with
 Progress
 ();%0A
@@ -3193,28 +3193,20 @@
 Progress
-(
+)
 );%0A
-        
         
@@ -3308,66 +3308,213 @@
     
+%7D%0A%0A
     
-    %7D%0A        %7D);%0A    %7D
+@SuppressWarnings(%7B%22RedundantCast%22, %22unused%22%7D)%0A    @JsType(isNative = true, namespace = JsPackage.GLOBAL)%0A    static class PromiseRejectionEvent extends Event %7B
 %0A%0A    
+ 
-private void stopProgress
+   public PromiseRejectionEvent
 () %7B
@@ -3526,70 +3526,142 @@
     
+    
-Elements.stream(document.querySelectorAll(%22.%22 + withProgress))
+// This super call is here only for the code to compile; it is never executed.%0A            super((String) null, (EventInit) null);
 %0A   
@@ -3661,32 +3661,35 @@
 l);%0A        
+%7D%0A%0A
         
 .forEach(ele
@@ -3680,67 +3680,49 @@
     
-.forEach(element -%3E element.classList.remove(withProgress))
+Promise%3C?%3E promise;%0A        Object reason
 ;%0A  

Add global promise rejection handler