import java.lang.*;
import java.applet.*;
import java.awt.*;
import java.net.*;

public class BlinkenSim extends Applet
{ 
  private int pixelX = 0;
  private int pixelY = 0;
  private int colors = 0;
  private int backgroundX = 0;
  private int backgroundY = 0;
  private int windowX = 0;
  private int windowY = 0;
  private int startX = 0;
  private int startY = 0;
  private int distanceX = 0;
  private int distanceY = 0;
  private Image backgroundImg;
  private Image overlayImg;
  private DynMcufClient mcuf;
  private FrameProcessor frameProc;

  public void init( )
  {
    String param;
    URL url;
    String host;
    int port = 0;

    param = getParameter( "pixelX" );
    if( param != null )
      pixelX = Integer.parseInt( param );
    if( pixelX < 1 || pixelX > 100 )
      pixelX = 26;
    param = getParameter( "pixelY" );
    if( param != null )
      pixelY = Integer.parseInt( param );
    if( pixelY < 1 || pixelY > 100 )
      pixelY = 20;
    param = getParameter( "colors" );
    if( param != null )
      colors = Integer.parseInt( param );
    if( colors < 1 || colors > 256 )
      colors = 8;
    param = getParameter( "backgroundX" );
    if( param != null )
      backgroundX = Integer.parseInt( param );
    if( backgroundX < 1 || backgroundX > 2048 )
      backgroundX = 144;
    param = getParameter( "backgroundY" );
    if( param != null )
      backgroundY = Integer.parseInt( param );
    if( backgroundY < 1 || backgroundY > 2048 )
      backgroundY = 108;
    param = getParameter( "windowX" );
    if( param != null )
      windowX = Integer.parseInt( param );
    if( windowX < 1 || windowX > 256 )
      windowX = 2;
    param = getParameter( "windowY" );
    if( param != null )
      windowY = Integer.parseInt( param );
    if( windowY < 1 || windowY > 256 )
      windowY = 4;
    param = getParameter( "startX" );
    if( param != null )
      startX = Integer.parseInt( param );
    if( startX < 1 || startX > 2048 )
      startX = 21;
    param = getParameter( "startY" );
    if( param != null )
      startY = Integer.parseInt( param );
    if( startY < 1 || startY > 2048 )
      startY = 5;
    param = getParameter( "distanceX" );
    if( param != null )
      distanceX = Integer.parseInt( param );
    if( distanceX < 1 || distanceX > 512 )
      distanceX = 2;
    param = getParameter( "distanceY" );
    if( param != null )
      distanceY = Integer.parseInt( param );
    if( distanceY < 1 || distanceY > 512 )
      distanceY = 24;

    url = getDocumentBase( );
    if( url != null )
    {
      backgroundImg = getImage( url, getParameter( "background" ) );
      overlayImg = getImage( url, getParameter( "overlay" ) );
    }
    else
    {
      try
      {
        url = new URL( "file:" + getParameter( "background" ) );
        backgroundImg = getImage( url );
      }
      catch( MalformedURLException e )
      {
        backgroundImg = createImage( -1, -1 );
      }
      try
      {
        url = new URL( "file:" + getParameter( "overlay" ) );
        overlayImg = getImage( url );
      }
      catch( MalformedURLException e )
      {
        overlayImg = createImage( -1, -1 );
      }
    }

    host = getParameter( "host" );
    if( host == null || host.length( ) <= 0 )
      host = "proxy.blinkenlights.de";
    
    param = getParameter( "port" );
    if( param != null )
      port = Integer.parseInt( param );
    if( port <= 0 || port > 65535 )
      port = 4242;

    mcuf = new DynMcufClient( );
    frameProc = new FrameProcessor( this );
    mcuf.start( host, port, frameProc );
  }

  public void stop( )
  {
    mcuf.stop( );
    mcuf = null;
    frameProc = null;
  }

  public void paint( Graphics g )
  {
    byte[][][] data;
    Image img;
    Graphics gBuf;
    int y, yy, x, xx, c;
    
    Frame frame = frameProc.getFrame( );
    frame.resize( pixelY, pixelX, 1 );
    data = frame.getData( );
    
    img = createImage( backgroundX, backgroundY );
    gBuf = img.getGraphics( );

    gBuf.drawImage( backgroundImg, 0, 0, this );

    for( y = 0, yy = startY; y < pixelY; y++, yy += distanceY )
    {
      for( x = 0, xx = startX; x < pixelX; x++, xx += distanceX )
      {
        c = ((data[y][x][0] & 0xFF) * (colors - 1) + 0x7F) / 0xFF;
        gBuf.drawImage( overlayImg, xx, yy, xx + windowX, yy + windowY,
                        c * windowX, 0, c * windowX + windowX, windowY, this );
      }
    }

    g.drawImage( img, 0, 0, this );
  }

  public void update( Graphics g )
  {
    paint( g );
  }
}
