/*
 * Water - a thread that moves and updates the water
 *
 * by Adam Doppelt
 * http://www.cs.brown.edu/people/amd/
 */
import java.awt.*;

public class Water extends Thread {
    final static Color START_COLOR = Color.white;
    final static int BEHIND_SLEEP = 50;
    
    Color color_;
    int row_, col_;
    int x1_, y1_, x2_, y2_;
    boolean lastR_, lastG_, lastB_;
    int delay_;
    
    Board board_;
    boolean visible_;
    int slice_, direction_;
    Piece piece_;

    public Water(Board board, Piece piece, int row, int col) {
	board_ = board;
	row_ = row;
	col_ = col;
	piece_ = piece;
	slice_ = 0;
	color_ = START_COLOR;
	visible_ = true;
	lastR_ = false;
	lastG_ = false;
	lastB_ = false;
	direction_ = Piece.EAST;
	piece_.WaterEnters(this);
	delay_ = Score.GetWaterDelay();
	start();
    }
    
    public boolean Advance() {
	if (slice_ == Piece.SLICES)
	    return MoveToNextPiece();
	else {
	    
 	    piece_.AdjustWater(this, slice_);
 	    board_.DrawWater(this);
 	    ++slice_;
 	    piece_.AdjustWater(this, slice_);
 	    board_.DrawWater(this);
 	    ++slice_;
 	    piece_.AdjustWater(this, slice_);
 	    board_.DrawWater(this);
 	    ++slice_;
 	    piece_.AdjustWater(this, slice_);
 	    board_.DrawWater(this);
 	    ++slice_;
 	    piece_.AdjustWater(this, slice_);
 	    board_.DrawWater(this);
 	    ++slice_;
 	    piece_.AdjustWater(this, slice_);
 	    board_.DrawWater(this);
 	    ++slice_;
 	    piece_.AdjustWater(this, slice_);
 	    board_.DrawWater(this);
 	    ++slice_;
 	    piece_.AdjustWater(this, slice_);
 	    board_.DrawWater(this);
 	    ++slice_;
	    piece_.AdjustWater(this, slice_);
	    ++slice_;

	    piece_.AdjustWater(this, slice_);
	    ++slice_;
	    return true;
	}
    }

    public int GetDirection() {
	return direction_;
    }

    public void SetDirection(int direction) {
	direction_ = direction;
    }
    
    public void SetVisible(boolean visible) {
	visible_ = visible;
    }

    public void SetColor(boolean r, boolean g, boolean b, double percent) {
	double newR, newG, newB;

	if (r)
	    newR = lastR_ ? (1.0 - percent) : percent;
	else
	    newR = lastR_ ? 1.0 : 0.0;

	if (g)
	    newG = lastG_ ? (1.0 - percent) : percent;
	else
	    newG = lastG_ ? 1.0 : 0.0;

	if (b)
	    newB = lastB_ ? (1.0 - percent) : percent;
	else
	    newB = lastB_ ? 1.0 : 0.0;
	
	color_ = new Color((float)newR, (float)newG, (float)newB);
    }

    public void SetTileOffset(int x1, int y1, int x2, int y2) {
	x1_ = col_ * (Piece.SIZE + 1) + x1 + 1;
	x2_ = col_ * (Piece.SIZE + 1) + x2 + 1;	
	y1_ = row_ * (Piece.SIZE + 1) + y1 + 1;
	y2_ = row_ * (Piece.SIZE + 1) + y2 + 1;	
    }

    private boolean MoveToNextPiece() {
	switch (direction_) {
	  case Piece.NORTH: row_--; break;
	  case Piece.SOUTH: row_++; break;
	  case Piece.EAST: col_++; break;
	  case Piece.WEST: col_--; break; 	    
	}

	piece_ = board_.PieceAt(row_, col_);
	if (piece_ != null) {
	    if (piece_.IsDirectionLegal(direction_)) {
		slice_ = 0;
		piece_.WaterEnters(this);


		lastR_ = color_.getRed() == 255;
		lastG_ = color_.getGreen() == 255;
		lastB_ = color_.getBlue() == 255;

		// HACK!
		visible_ = false;

		Score.AnotherPiece();
		return true;
	    }
	    else
		return false;
	}
	else
	    return false;
    }
    
    public void Draw(Graphics g) {
	g.setColor(color_);
	g.drawLine(x1_, y1_, x2_, y2_);
	g.setColor(Piece.PIPE_COLOR);
	g.drawLine(x1_, y1_, x1_, y1_);
	g.drawLine(x2_, y2_, x2_, y2_);	
    }
    
    public synchronized void run() {
	setPriority(NORM_PRIORITY + 1);
	long time = System.currentTimeMillis();
	while(Advance()) {
	    if (visible_)
		board_.DrawWater(this);
	    try {
		time += delay_;
		long toSleep = time - System.currentTimeMillis();
		if (toSleep > 0)
		    sleep(toSleep);
		else {
		    sleep(BEHIND_SLEEP);
		    time = System.currentTimeMillis();
		}
	    }
	    catch (InterruptedException e) { ; }
	}
	board_.WaterDied();
    }
}
