import java.awt.*;
import java.util.Observable;
import java.util.Observer;

/**
 * This class represents the small animation on the lower right.
 * It always shows the car distribution for a fixed time level. According to the value of
 * Geschw. we set the pause between two pictures to 100-Geschw milliseconds.
 * @author B.Düring
 * @author S.Holst
 */
public class AnimatedCanvas extends Canvas
    implements Animation
{
    class MyObservable extends Observable
    {

        public void hasStopped()
        {
            setChanged();
            notifyObservers();
            clearChanged();
        }

        MyObservable()
        {
        }
    }


    public AnimatedCanvas()
    {
        m_thread = null;
        data = null;
        cols = 0;
        rows = 0;
        rowcount = 0;
        xscale = 1.0F;
        yscale = 1.0F;
        speed = 50;
        obs = new MyObservable();
    }

    public void addObserver(Observer observer)
    {
        obs.addObserver(observer);
    }

    public void clear()
    {
        stop();
        Rectangle rectangle = m_graphics.getClipBounds();
        m_graphics.clearRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
    }

    private float getScale(int i, int j)
    {
        return (float)j / (float)i;
    }

    private float getScale(int i, int j, int k)
    {
        double d = 0.0D;
        for(int l = 0; l < i; l++)
        {
            double d1 = d;
            for(int i1 = 0; i1 < j; i1++)
                d = Math.max(d, data[i1][l]);

            d = Math.max(d, d1);
        }

        return (float)((double)k / d);
    }

    public boolean isInitialized()
    {
        return cols != 0 && rows != 0 && data != null;
    }

    public boolean isRunning()
    {
        return m_thread != null;
    }

    public void paint(Graphics g)
    {
        if(bgImage != null)
            g.drawImage(bgImage, 0, 0, this);
    }

    public void run()
    {
        int ai[] = new int[cols];
        int ai1[] = new int[cols];
        Dimension dimension = getSize();
        Rectangle rectangle = new Rectangle(0, 0, dimension.width, dimension.height);
        xscale = getScale(cols, getBounds().width - 6);
        yscale = getScale(cols, rows, getBounds().height - 6);
        for(rowcount = 0; rowcount < rows; rowcount++)
            try
            {
                long l = System.currentTimeMillis();
                m_dblbuffer.clearRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
                for(int i = 0; i < cols; i++)
                {
                    ai[i] = (int)((float)i * xscale) + 3;
                    ai1[i] = (int)((1.0D - data[rowcount][i]) * (double)yscale) + 3;
                }

                m_dblbuffer.drawPolyline(ai, ai1, cols);
                m_dblbuffer.draw3DRect(0, 0, dimension.width - 1, dimension.height - 1, false);
                rowcount++;
                m_graphics.drawImage(bgImage, 0, 0, this);
                if(rowcount >= rows)
                    rowcount = 0;
                Thread.sleep(Math.max(0L, ((long)(100 - speed) + l) - System.currentTimeMillis()));
            }
            catch(InterruptedException _ex)
            {
                stop();
            }

        obs.hasStopped();
        m_thread = null;
    }

    public void setData(double ad[][])
    {
        if(ad != null)
            if(isRunning())
            {
                stop();
                rows = ad.length;
                cols = ad[0].length;
                data = ad;
                start();
            } else
            {
                rows = ad.length;
                cols = ad[0].length;
                data = ad;
            }
    }

    public void setSize(int i, int j)
    {
        if(isRunning())
        {
            stop();
            super.setSize(i, j);
            start();
        } else
        {
            super.setSize(i, j);
        }
    }

    public void setSize(Dimension dimension)
    {
        setSize(dimension.width, dimension.height);
    }

    public void setSpeed(int i)
    {
        if(i > 0 && i < 101)
            speed = i;
    }

    public boolean start()
    {
        m_graphics = getGraphics();
        bgImage = createImage(getSize().width, getSize().height);
        m_dblbuffer = bgImage.getGraphics();
        if(isInitialized())
        {
            if(isRunning())
                stop();
            m_thread = new Thread(this);
            m_thread.start();
        }
        return isRunning();
    }

    public void stop()
    {
        if(isRunning())
        {
            m_thread.stop();
            m_thread = null;
        }
    }

    private Graphics m_graphics;
    private Graphics m_dblbuffer;
    private Image bgImage;
    private Thread m_thread;
    private double data[][];
    private int cols;
    private int rows;
    private int rowcount;
    private float xscale;
    private float yscale;
    private int speed;
    private MyObservable obs;
}
