package org.realityforge.gwt.eventsource.example.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TextBox;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import org.realityforge.gwt.eventsource.client.EventSource;
import org.realityforge.gwt.eventsource.client.event.CloseEvent;
import org.realityforge.gwt.eventsource.client.event.ErrorEvent;
import org.realityforge.gwt.eventsource.client.event.MessageEvent;
import org.realityforge.gwt.eventsource.client.event.OpenEvent;

public final class Example
  implements EntryPoint
{
  private static final Logger LOG = Logger.getLogger( Example.class.getName() );

  private HTML _messages;
  private ScrollPanel _scrollPanel;
  private Button _disconnect;
  private Button _connect;

  public void onModuleLoad()
  {
    final EventSource eventSource = EventSource.newEventSourceIfSupported();
    if ( null == eventSource )
    {
      Window.alert( "EventSource not available!" );
    }
    else
    {
      registerListeners( eventSource );
      final TextBox url = new TextBox();
      final String moduleBaseURL = GWT.getModuleBaseURL();
      final String moduleName = GWT.getModuleName();
      final String eventSourceURL =
        moduleBaseURL.substring( 0, moduleBaseURL.length() - moduleName.length() - 1 ) + "api/time";
      url.setValue( eventSourceURL );

      _connect = new Button( "Connect", new ClickHandler()
      {
        @Override
        public void onClick( final ClickEvent event )
        {
          _connect.setEnabled( false );
          eventSource.connect( url.getValue() );
          log( eventSource, "Opening EventSource." );
        }
      } );
      _disconnect = new Button( "Disconnect", new ClickHandler()
      {
        @Override
        public void onClick( ClickEvent event )
        {
          eventSource.close();
          _disconnect.setEnabled( false );
          log( eventSource, "Closed EventSource." );
        }
      } );
      _disconnect.setEnabled( false );

      _messages = new HTML();
      _scrollPanel = new ScrollPanel();
      _scrollPanel.setHeight( "250px" );
      _scrollPanel.add( _messages );
      RootPanel.get().add( _scrollPanel );

      {
        final FlowPanel controls = new FlowPanel();
        controls.add( url );
        controls.add( _connect );
        controls.add( _disconnect );
        RootPanel.get().add( controls );
      }
    }
  }

  private void registerListeners( final EventSource eventSource )
  {
    eventSource.addOpenHandler( new OpenEvent.Handler()
    {
      @Override
      public void onOpenEvent( @Nonnull final OpenEvent event )
      {
        appendText( "open", "silver" );
        _disconnect.setEnabled( true );
        log( eventSource, "EventSource Open Complete." );
      }
    } );
    eventSource.addCloseHandler( new CloseEvent.Handler()
    {
      @Override
      public void onCloseEvent( @Nonnull final CloseEvent event )
      {
        appendText( "close", "silver" );
        _connect.setEnabled( true );
        _disconnect.setEnabled( false );
        log( eventSource, "EventSource Close Complete." );
      }
    } );
    eventSource.addErrorHandler( new ErrorEvent.Handler()
    {
      @Override
      public void onErrorEvent( @Nonnull final ErrorEvent event )
      {
        appendText( "error", "red" );
        _connect.setEnabled( false );
        _disconnect.setEnabled( false );
        log( eventSource, "EventSource Error." );
      }
    } );
    eventSource.addMessageHandler( new MessageEvent.Handler()
    {
      @Override
      public void onMessageEvent( @Nonnull final MessageEvent event )
      {
        appendText( "message: " + event.getData(), "black" );
        log( eventSource, "EventSource Message: " + event.getData() + "." );
      }
    } );
  }

  private void appendText( final String text, final String color )
  {
    final DivElement div = Document.get().createDivElement();
    div.setInnerText( text );
    div.setAttribute( "style", "color:" + color );
    _messages.getElement().appendChild( div );
    _scrollPanel.scrollToBottom();
  }

  private void log( final EventSource eventSource, final String message )
  {
    final String suffix;
    if ( EventSource.ReadyState.CLOSED != eventSource.getReadyState() )
    {
      suffix = " URL: " + eventSource.getURL() +
               " WithCredentials: " + eventSource.getWithCredentials();
    }
    else
    {
      suffix = "";
    }

    LOG.warning( message + " ReadyState: " + eventSource.getReadyState().name() + suffix );
  }
}

@@ -1253,26 +1253,21 @@
 Button _
-disconnect
+close
 ;%0A  priv
@@ -1278,23 +1278,20 @@
 Button _
-connect
+open
 ;%0A%0A  pub
@@ -1881,23 +1881,20 @@
 %0A      _
-connect
+open
  = new B
@@ -1905,15 +1905,12 @@
 n( %22
-Connect
+Open
 %22, n
@@ -2020,39 +2020,36 @@
    %7B%0A          _
-connect
+open
 .setEnabled( fal
@@ -2076,23 +2076,20 @@
 tSource.
-connect
+open
 ( url.ge
@@ -2182,26 +2182,21 @@
 %0A      _
-disconnect
+close
  = new B
@@ -2207,18 +2207,13 @@
 n( %22
-Disconnect
+Close
 %22, n
@@ -2352,34 +2352,29 @@
 %0A          _
-disconnect
+close
 .setEnabled(
@@ -2460,34 +2460,29 @@
 %7D );%0A      _
-disconnect
+close
 .setEnabled(
@@ -2796,23 +2796,20 @@
 s.add( _
-connect
+open
  );%0A    
@@ -2827,26 +2827,21 @@
 s.add( _
-disconnect
+close
  );%0A    
@@ -3161,34 +3161,29 @@
 );%0A        _
-disconnect
+close
 .setEnabled(
@@ -3462,39 +3462,36 @@
 er%22 );%0A        _
-connect
+open
 .setEnabled( tru
@@ -3500,34 +3500,29 @@
 );%0A        _
-disconnect
+close
 .setEnabled(
@@ -3808,23 +3808,20 @@
        _
-connect
+open
 .setEnab
@@ -3847,18 +3847,13 @@
    _
-disconnect
+close
 .set

Rename Connect => Open and Disconnect => Close to match terminology of underlying system