package org.realityforge.replicant.example.client.ui;

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 javax.annotation.Nonnull;
import org.realityforge.gwt.websockets.client.WebSocket;
import org.realityforge.gwt.websockets.client.event.CloseEvent;
import org.realityforge.gwt.websockets.client.event.ErrorEvent;
import org.realityforge.gwt.websockets.client.event.MessageEvent;
import org.realityforge.gwt.websockets.client.event.OpenEvent;

public final class SimpleUI
{
  private HTML _messages;
  private ScrollPanel _scrollPanel;
  private Button _disconnect;
  private Button _connect;
  private Button _send;

  public void SimpleUI()
  {
    final WebSocket webSocket = WebSocket.newWebSocketIfSupported();
    if ( null == webSocket )
    {
      Window.alert( "WebSocket not available!" );
    }
    else
    {
      registerListeners( webSocket );
      final TextBox url = new TextBox();
      final String moduleBaseURL = GWT.getModuleBaseURL();
      final String moduleName = GWT.getModuleName();
      final String webSocketURL =
        moduleBaseURL.substring( 0, moduleBaseURL.length() - moduleName.length() - 1 ).
          replaceFirst( "^http\\:", "ws:" ) + "chat";
      url.setValue( webSocketURL );
      final TextBox input = new TextBox();
      input.setValue( "Greetings!" );

      _connect = new Button( "Connect", new ClickHandler()
      {
        @Override
        public void onClick( final ClickEvent event )
        {
          _connect.setEnabled( false );
          webSocket.connect( url.getValue() );
        }
      } );
      _disconnect = new Button( "Disconnect", new ClickHandler()
      {
        @Override
        public void onClick( ClickEvent event )
        {
          webSocket.close();
          _disconnect.setEnabled( false );
        }
      } );
      _disconnect.setEnabled( false );
      _send = new Button( "Send", new ClickHandler()
      {
        @Override
        public void onClick( ClickEvent event )
        {
          webSocket.send( input.getValue() );
        }
      } );
      _send.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 );
      }

      {
        final FlowPanel controls = new FlowPanel();
        controls.add( input );
        controls.add( _send );
        RootPanel.get().add( controls );
      }
    }
  }

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

  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();
  }
}
@@ -366,16 +366,64 @@
 Button;%0A
+import com.google.gwt.user.client.ui.Composite;%0A
 import c
@@ -509,56 +509,8 @@
 ML;%0A
-import com.google.gwt.user.client.ui.RootPanel;%0A
 impo
@@ -601,16 +601,68 @@
 extBox;%0A
+import com.google.gwt.user.client.ui.VerticalPanel;%0A
 import j
@@ -1029,16 +1029,36 @@
 impleUI%0A
+  extends Composite%0A
 %7B%0A  priv
@@ -1193,16 +1193,48 @@
 n _send;
+%0A  private VerticalPanel _panel;
 %0A%0A  publ
@@ -2840,37 +2840,65 @@
 ages );%0A
+%0A
       
-RootPanel.get()
+_panel = new VerticalPanel();%0A      _panel
 .add( _s
@@ -3076,39 +3076,30 @@
  );%0A        
-RootPanel.get()
+_panel
 .add( contro
@@ -3247,23 +3247,14 @@
     
-RootPanel.get()
+_panel
 .add
@@ -3271,24 +3271,52 @@
  );%0A      %7D%0A
+      initWidget( _panel );%0A
     %7D%0A  %7D%0A%0A 

Convert to a composite