/*
 * Copyright 2012 JBoss Inc
 *
 * 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
 *
 *       http://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.uberfire.client.common;

import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.DecoratedPopupPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import org.uberfire.client.animations.LinearFadeInAnimation;
import org.uberfire.client.animations.LinearFadeOutAnimation;

/**
 * A simple pop-up to show messages while "long running" activities take place
 */
public class BusyPopup extends DecoratedPopupPanel {

    interface LoadingViewBinder
            extends
            UiBinder<Widget, BusyPopup> {

    }

    private static LoadingViewBinder uiBinder = GWT.create( LoadingViewBinder.class );

    private static Timer deferredShowTimer = new Timer() {
        @Override
        public void run() {
            fadeInAnimation.run( 250 );
        }
    };

    private static MessageState state = MessageState.HIDDEN;

    @UiField
    Label message;

    private static final BusyPopup INSTANCE = new BusyPopup();

    private static final LinearFadeInAnimation fadeInAnimation = new LinearFadeInAnimation( INSTANCE ) {

        @Override
        public void onStart() {
            state = MessageState.SHOWING;
            super.onStart();
            INSTANCE.center();
        }

        @Override
        public void onComplete() {
            state = MessageState.VISIBLE;
            super.onComplete();
        }
    };

    private static final LinearFadeOutAnimation fadeOutAnimation = new LinearFadeOutAnimation( INSTANCE ) {

        @Override
        public void onStart() {
            state = MessageState.HIDING;
            super.onStart();
        }

        @Override
        public void onComplete() {
            super.onComplete();
            INSTANCE.hide();
            state = MessageState.HIDDEN;
        }
    };

    private BusyPopup() {
        setWidget( uiBinder.createAndBindUi( this ) );

        //Make sure it appears on top of other popups
        getElement().getStyle().setZIndex( Integer.MAX_VALUE );
        setGlassEnabled( true );
    }

    public static void showMessage( final String message ) {
        if ( state == MessageState.SHOWING || state == MessageState.VISIBLE ) {
            return;
        }
        INSTANCE.message.setText( message );
        deferredShowTimer.schedule( 250 );
    }

    public static void close() {
        if ( state == MessageState.HIDING || state == MessageState.HIDDEN ) {
            return;
        }
        deferredShowTimer.cancel();
        if ( state == MessageState.VISIBLE ) {
            fadeOutAnimation.run( 250 );
        }
    }

    private enum MessageState {
        SHOWING,
        VISIBLE,
        HIDING,
        HIDDEN
    }

}

@@ -1619,22 +1619,23 @@
 geState.
-HIDDEN
+DORMANT
 ;%0A%0A    @
@@ -1928,37 +1928,8 @@
 NG;%0A
-            super.onStart();%0A
     
@@ -1951,24 +1951,53 @@
 E.center();%0A
+            super.onStart();%0A
         %7D%0A%0A 
@@ -2446,33 +2446,43 @@
        s
-uper.onComplete()
+tate = MessageState.DORMANT
 ;%0A      
@@ -2521,34 +2521,25 @@
    s
-tate = MessageState.HIDDEN
+uper.onComplete()
 ;%0A  
@@ -2855,34 +2855,38 @@
 age ) %7B%0A        
-if
+switch
  ( state == Mess
@@ -2882,42 +2882,165 @@
 ate 
-== MessageState.SHOWING %7C%7C
+) %7B%0A            case DORMANT:%0A                INSTANCE.message.setText( message );%0A                deferredShowTimer.schedule( 250 );%0A               
  state =
 = Me
@@ -3027,33 +3027,32 @@
          state =
-=
  MessageState.VI
@@ -3045,36 +3045,191 @@
 essageState.
-VISIBLE ) %7B%0A
+PENDING;%0A                break;%0A            case PENDING:%0A            case SHOWING:%0A            case VISIBLE:%0A                INSTANCE.message.setText( message );%0A    
             
@@ -3220,38 +3220,105 @@
                 
+b
 re
-turn
+ak;%0A            case HIDING:%0A                fadeOutAnimation.cancel()
 ;%0A        %7D%0A    
@@ -3303,34 +3303,32 @@
 ncel();%0A        
-%7D%0A
         INSTANCE
@@ -3368,42 +3368,55 @@
     
-deferredShowTimer.schedule( 250 );
+        fadeInAnimation.onComplete();%0A        %7D
 %0A   
@@ -3452,34 +3452,38 @@
 ose() %7B%0A        
-if
+switch
  ( state == Mess
@@ -3479,66 +3479,37 @@
 ate 
-== MessageState.HIDING %7C%7C state == MessageState.HIDDEN ) %7B
+) %7B%0A            case DORMANT:
 %0A   
@@ -3521,14 +3521,17 @@
     
-return
+    break
 ;%0A  
@@ -3540,18 +3540,36 @@
     
-%7D%0A
+    case PENDING:%0A  
         
 defe
@@ -3556,32 +3556,38 @@
 DING:%0A          
+      
 deferredShowTime
@@ -3610,47 +3610,189 @@
     
-if ( state == MessageState.
+        break;%0A            case SHOWING:%0A                fadeInAnimation.cancel();%0A                fadeOutAnimation.run( 250 );%0A                break;%0A            case 
 VISIBLE
- ) %7B%0A
+:%0A    
     
@@ -3820,32 +3820,103 @@
 ion.run( 250 );%0A
+                break;%0A            case HIDING:%0A                break;%0A
         %7D%0A    %7D%0A
@@ -3948,16 +3948,50 @@
 State %7B%0A
+        DORMANT,%0A        PENDING,%0A
         
@@ -4034,24 +4034,8 @@
 DING
-,%0A        HIDDEN
 %0A   

Fix BusyPopup race condition