package com.dpforge.droidgif;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.SurfaceHolder;

import com.dpforge.droidgif.decoder2.GIFImage;
import com.dpforge.droidgif.decoder2.GIFImageFrame;

class RendererThread extends Thread {
	private final SurfaceHolder mHolder;
	private boolean mRunning;
	private GIFImage mImage;
	private int[] mBuffer;
	private Bitmap mFrameBitmap;
	private final Paint mPaint;

	private long mTotalDiff;
	private int mFrameIndex;

	RendererThread(final SurfaceHolder holder) {
		mHolder = holder;

		mPaint = new Paint();
		mPaint.setStyle(Paint.Style.FILL);
	}

	void setRunning(boolean running) {
		mRunning = running;
	}

	void setImage(final GIFImage image) {
		mImage = image;
		mBuffer = new int[image.height()*image.width()];
		mFrameBitmap = Bitmap.createBitmap(image.width(), image.height(), Bitmap.Config.ARGB_8888);
	}

	@Override
	public void run() {
		long lastDrawTime = System.currentTimeMillis();
		while (mRunning) {
			Canvas canvas = null;
			try {
				canvas = mHolder.lockCanvas();
				if (canvas != null && mImage != null) {
					final GIFImageFrame frame = mImage.getFrame(mFrameIndex);
					prepareBuffer(frame);
					drawBuffer(canvas);
					disposeBuffer(frame);
					mTotalDiff += System.currentTimeMillis() - lastDrawTime;
					lastDrawTime = System.currentTimeMillis();

					if (mTotalDiff > frame.delay()*10) {
						mFrameIndex = (mFrameIndex + 1)%mImage.framesCount();
						mTotalDiff = 0;
					}
				}
			} finally {
				if (canvas != null) {
					mHolder.unlockCanvasAndPost(canvas);
				}
			}
		}
	}

	private void prepareBuffer(final GIFImageFrame frame) {
		for (int y = 0; y < frame.height(); ++y) {
			for (int x = 0; x < frame.width(); ++x) {
				int left = frame.left() + x;
				int top = frame.top() + y;
				if (!frame.isTransparentPixel(x, y)) {
					mBuffer[top*mImage.width() + left] = frame.getColor(x, y) | 0xFF000000;
				}
			}
		}
	}

	private void drawBuffer(final Canvas canvas) {
		mFrameBitmap.setPixels(mBuffer, 0, mImage.width(), 0, 0, mImage.width(), mImage.height());
		canvas.drawBitmap(mFrameBitmap, 0, 0, mPaint);
	}

	private void disposeBuffer(final GIFImageFrame frame) {
		switch (frame.disposalMethod()) {
			case NOT_SPECIFIED:
			case NO_DISPOSE:
				// DO NOTHING
				break;
			case RESTORE_BACKGROUND:
				for (int i = 0; i < mBuffer.length; ++i) {
					mBuffer[i] = mImage.backgroundColor();
				}
				break;
			case RESTORE_PREVIOUS:
				// TODO: implement
				break;
		}
	}
}

@@ -340,16 +340,25 @@
 private 
+volatile 
 boolean 
@@ -763,16 +763,56 @@
 mage) %7B%0A
+%09%09synchronized (RendererThread.this) %7B%0A%09
 %09%09mImage
@@ -821,16 +821,17 @@
  image;%0A
+%09
 %09%09mBuffe
@@ -873,16 +873,17 @@
 dth()%5D;%0A
+%09
 %09%09mFrame
@@ -968,16 +968,59 @@
 _8888);%0A
+%09%09%09mFrameIndex = 0;%0A%09%09%09mTotalDiff = 0;%0A%09%09%7D%0A
 %09%7D%0A%0A%09@Ov
@@ -1183,24 +1183,66 @@
 ckCanvas();%0A
+%09%09%09%09synchronized (RendererThread.this) %7B%0A%09
 %09%09%09%09if (canv
@@ -1278,16 +1278,17 @@
  %7B%0A%09%09%09%09%09
+%09
 final GI
@@ -1342,16 +1342,17 @@
 );%0A%09%09%09%09%09
+%09
 prepareB
@@ -1361,24 +1361,25 @@
 fer(frame);%0A
+%09
 %09%09%09%09%09drawBuf
@@ -1396,16 +1396,17 @@
 );%0A%09%09%09%09%09
+%09
 disposeB
@@ -1415,24 +1415,25 @@
 fer(frame);%0A
+%09
 %09%09%09%09%09mTotalD
@@ -1487,16 +1487,17 @@
 e;%0A%09%09%09%09%09
+%09
 lastDraw
@@ -1533,24 +1533,25 @@
 is();%0A%0A%09%09%09%09%09
+%09
 if (mTotalDi
@@ -1554,16 +1554,17 @@
 alDiff %3E
+=
  frame.d
@@ -1572,24 +1572,25 @@
 lay()*10) %7B%0A
+%09
 %09%09%09%09%09%09mFrame
@@ -1635,32 +1635,33 @@
 sCount();%0A%09%09%09%09%09%09
+%09
 mTotalDiff = 0;%0A
@@ -1660,16 +1660,24 @@
 ff = 0;%0A
+%09%09%09%09%09%09%7D%0A
 %09%09%09%09%09%7D%0A%09

change renderer image at any time