/*******************************************************************************
 * Copyright (c) 2004, 2010 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.draw2d.test;

import java.util.Stack;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.SWTGraphics;
import org.eclipse.draw2d.rap.swt.graphics.LineAttributes;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.Path;
import org.eclipse.swt.graphics.Pattern;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Resource;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class AdvancedGraphicsTests extends AbstractFixtureTestCase {

	static final int LINE[] = new int[] { 5, 5, 20, 20, 35, 5, 50, 5 };
	static final int POLY[] = new int[] { 5, 5, 45, 15, 20, 30, 20, 20, 45, 35,
			5, 45 };
	private static final int PREVIEW_DELAY = 250;
	private SWTGraphics g;

	private Image image;
	private GC imageGC;
	private Path path1;
	private Path path2;
	private Stack resources = new Stack();

	private void assertImageEquality(int width, int height) {
		ImageData data = image.getImageData();
		int src, dst;
		PaletteData palette = data.palette;
		for (int y = 0; y < height; y++)
			for (int x = 0; x < width; x++) {
				src = data.getPixel(x, y);
				dst = data.getPixel(x, y + height);

				if (src != dst) {
					RGB rgb1 = palette.getRGB(src);
					RGB rgb2 = palette.getRGB(dst);
					// HACK, image operations seem to differ by as much as 4
					if (Math.abs(rgb1.red - rgb2.red) > 4
							|| Math.abs(rgb1.green - rgb2.green) > 4
							|| Math.abs(rgb1.blue - rgb2.blue) > 4)
						assertEquals("Discrepancy at coordinates <" + x + ", "
								+ y + ">", rgb1, rgb2);
				}
			}
	}

	private void displayImage() {
		final Shell shell = new Shell(SWT.DIALOG_TRIM);
		shell.addPaintListener(new PaintListener() {
			public void paintControl(PaintEvent e) {
				e.gc.drawImage(image, 0, 0);
			}
		});
		shell.setBounds(100, 100, 800, 600);
		shell.open();
		Display d = shell.getDisplay();
		d.timerExec(PREVIEW_DELAY, new Runnable() {
			public void run() {
				if (!shell.isDisposed())
					shell.close();
			}
		});
		while (!shell.isDisposed())
			while (!d.readAndDispatch())
				d.sleep();

	}

	private void performTestcase(Runnable painter, Runnable tests[]) {
		g.pushState();
		painter.run();
		for (int i = 0; i < tests.length; i++) {
			g.translate(100, 0);
			tests[i].run();
			g.pushState();
			painter.run();
		}

		for (int i = 0; i <= tests.length; i++) {
			g.popState();
			g.translate(0, 100);
			painter.run();
		}

		displayImage();
		assertImageEquality(100 * tests.length, 100);
	}

	protected void setUp() throws Exception {
		super.setUp();
		path1 = new Path(null);
		path1.moveTo(20, 5);
		path1.quadTo(40, 5, 50, 25);
		path1.quadTo(20, 25, 20, 45);
		path1.lineTo(0, 25);
		path1.close();

		path2 = new Path(null);
		path2.moveTo(15, 30);
		path2.cubicTo(50, 0, 50, 30, 20, 60);
		path2.close();

		image = new Image(Display.getDefault(), 800, 600);
		imageGC = new GC(image.getDevice(), SWT.NONE);
		g = new SWTGraphics(imageGC);

		resources.push(path1);
		resources.push(path2);
		resources.push(image);
		resources.push(imageGC);
	}

	protected void tearDown() throws Exception {
		g.dispose();
		while (!resources.isEmpty())
			((Resource) resources.pop()).dispose();
		super.tearDown();
	}

	public void testAntialias() {
		class AntialiasSettings implements Runnable {
			private final Color color;
			private final int normal;
			private final int text;

			AntialiasSettings(int text, int normal, Color color) {
				this.text = text;
				this.normal = normal;
				this.color = color;
			}

			public void run() {
				g.setAntialias(normal);
				g.setTextAntialias(text);
				g.setForegroundColor(color);
			}
		}

		g.setLineWidthFloat(9);
		g.pushState();

		Runnable tests[] = new Runnable[4];
		tests[0] = new AntialiasSettings(SWT.ON, SWT.ON, ColorConstants.red());
		tests[1] = new AntialiasSettings(SWT.OFF, SWT.OFF,
				ColorConstants.blue());
		tests[2] = new AntialiasSettings(SWT.DEFAULT, SWT.ON,
				ColorConstants.black());
		tests[3] = new AntialiasSettings(SWT.ON, SWT.DEFAULT,
				ColorConstants.darkGreen());
		performTestcase(new Runnable() {
			public void run() {
				g.drawPolyline(LINE);
				g.drawString("OWVO", 35, 20);
			}
		}, tests);
	}

	public void testFillRules() {

		class FillRules implements Runnable {
			private final int aa;
			private final int rule;

			FillRules(int rule, int aa) {
				this.rule = rule;
				this.aa = aa;
			}

			public void run() {
				g.setFillRule(rule);
				// $TODO
				g.setAntialias(aa);
			}
		}
		g.setBackgroundColor(ColorConstants.red());
		g.pushState();

		Runnable tests[] = new Runnable[3];
		tests[0] = new FillRules(org.eclipse.draw2d.rap.swt.SWT.FILL_EVEN_ODD,
				SWT.ON);
		tests[1] = new FillRules(org.eclipse.draw2d.rap.swt.SWT.FILL_WINDING,
				SWT.OFF);
		tests[2] = new FillRules(org.eclipse.draw2d.rap.swt.SWT.FILL_EVEN_ODD,
				SWT.DEFAULT);
		performTestcase(new Runnable() {
			public void run() {
				g.fillPolygon(POLY);
			}
		}, tests);
	}

	// public void testInterpolation() {
	// class InterpolationSettings implements Runnable {
	// private final int level;
	// InterpolationSettings (int level) {
	// this.level = level;
	// }
	// public void run() {
	// g.setInterpolation(level);
	// }
	// }
	//
	// g.pushState();
	//
	// Runnable tests[] = new Runnable[4];
	// tests[0] = new InterpolationSettings(SWT.HIGH);
	// tests[1] = new InterpolationSettings(SWT.LOW);
	// tests[2] = new InterpolationSettings(SWT.NONE);
	// tests[3] = new InterpolationSettings(SWT.DEFAULT);
	// performTestcase(new Runnable() {
	// public void run() {
	// g.drawImage(TestImages.depth_24, 0, 0, 400, 400, 0, 0, 75, 75);
	// }
	// }, tests);
	// }

	public void testLineJoinCap() {

		class LineSettings implements Runnable {
			private final int cap;
			private final int style;
			private final int join;

			LineSettings(int join, int cap, int style) {
				this.join = join;
				this.cap = cap;
				this.style = style;
			}

			public void run() {
				g.setLineCap(cap);
				g.setLineJoin(join);
				g.setLineStyle(style);
			}
		}

		g.setLineWidthFloat(9);
		g.pushState();

		Runnable[] tests = new Runnable[] {
				new LineSettings(SWT.JOIN_ROUND, SWT.CAP_ROUND,
						org.eclipse.draw2d.rap.swt.SWT.LINE_DASH),
				new LineSettings(SWT.JOIN_BEVEL, SWT.CAP_FLAT,
						org.eclipse.draw2d.rap.swt.SWT.LINE_DOT),
				new LineSettings(SWT.JOIN_ROUND, SWT.CAP_SQUARE,
						org.eclipse.draw2d.rap.swt.SWT.LINE_SOLID) };

		performTestcase(new Runnable() {
			public void run() {
				g.drawPolyline(LINE);
			}
		}, tests);
	}

	public void testLineJoinCapAA() {
		g.setAntialias(SWT.ON);
		testLineJoinCap();
	}

	public void testLineAttributes() {
		class LineSettings implements Runnable {
			private LineAttributes attributes;

			public LineSettings(LineAttributes attributes) {
				this.attributes = attributes;
			}

			public void run() {
				g.setLineAttributes(attributes);
			}
		}

		float[] dash = new float[] { 2.5f, 3, 8 };

		Runnable[] tests = new Runnable[] {
				new LineSettings(new LineAttributes(0.0f, SWT.CAP_FLAT,
						SWT.JOIN_MITER,
						org.eclipse.draw2d.rap.swt.SWT.LINE_SOLID, null, 0, 10)),
				new LineSettings(new LineAttributes(1.0f, SWT.CAP_FLAT,
						SWT.JOIN_MITER,
						org.eclipse.draw2d.rap.swt.SWT.LINE_SOLID, null, 0, 10)),
				new LineSettings(new LineAttributes(2.5f, SWT.CAP_FLAT,
						SWT.JOIN_MITER,
						org.eclipse.draw2d.rap.swt.SWT.LINE_SOLID, null, 0, 10)),
				new LineSettings(new LineAttributes(5.0f, SWT.CAP_FLAT,
						SWT.JOIN_MITER,
						org.eclipse.draw2d.rap.swt.SWT.LINE_DASH, null, 0, 10)),
				new LineSettings(new LineAttributes(5.0f, SWT.CAP_FLAT,
						SWT.JOIN_ROUND,
						org.eclipse.draw2d.rap.swt.SWT.LINE_DASHDOTDOT, null,
						0, 10)),
				new LineSettings(new LineAttributes(4.5f, SWT.CAP_FLAT,
						SWT.JOIN_MITER,
						org.eclipse.draw2d.rap.swt.SWT.LINE_SOLID, null, 0, 10)),
				new LineSettings(
						new LineAttributes(9.0f, SWT.CAP_FLAT, SWT.JOIN_ROUND,
								org.eclipse.draw2d.rap.swt.SWT.LINE_CUSTOM,
								dash, 0, 10)),
				new LineSettings(
						new LineAttributes(9.5f, SWT.CAP_FLAT, SWT.JOIN_ROUND,
								org.eclipse.draw2d.rap.swt.SWT.LINE_CUSTOM,
								dash, 5, 10)), };

		performTestcase(new Runnable() {
			public void run() {
				g.drawPolyline(LINE);
			}
		}, tests);
	}

	public void testLineAttributesAA() {
		g.setAntialias(SWT.ON);
		testLineAttributes();
	}

	// public void testPathDraw() {
	//
	// class PathSettings implements Runnable {
	// private final int antialias;
	// private final Color color;
	// private final int style;
	// private final int width;
	// PathSettings(int antialias, int width, int style, Color color) {
	// this.antialias = antialias;
	// this.width = width;
	// this.style = style;
	// this.color = color;
	// }
	// public void run() {
	// g.setAntialias(antialias);
	// g.setLineWidth(width);
	// g.setLineStyle(style);
	// g.setForegroundColor(color);
	// }
	// }
	//
	// g.setBackgroundColor(ColorConstants.darkBlue);
	//
	// Runnable tests[] = new Runnable[5];
	// tests[0] = new PathSettings(SWT.ON, 3, SWT.LINE_SOLID,
	// ColorConstants.darkBlue);
	// tests[1] = new PathSettings(SWT.OFF, 0, SWT.LINE_DOT,
	// ColorConstants.red);
	// tests[2] = new PathSettings(SWT.DEFAULT, 1, SWT.LINE_DOT,
	// ColorConstants.darkBlue);
	// tests[3] = new PathSettings(SWT.DEFAULT, 2, SWT.LINE_DOT,
	// ColorConstants.darkGreen);
	// tests[4] = new PathSettings(SWT.ON, 2, SWT.LINE_DASHDOTDOT,
	// ColorConstants.black);
	// performTestcase(new Runnable() {
	// public void run() {
	// g.drawPath(path1);
	// g.drawPath(path2);
	// }
	// }, tests);
	//
	// path1.dispose();
	// }

	// public void testPathFill() {
	//
	// class PathSettings implements Runnable {
	// private final int antialias;
	// private final int alpha;
	// PathSettings(int antialias, int alpha) {
	// this.antialias = antialias;
	// this.alpha = alpha;
	// }
	// public void run() {
	// g.setAntialias(antialias);
	// g.setAlpha(alpha);
	// }
	// }
	//
	// g.setBackgroundColor(ColorConstants.darkBlue);
	//
	// Runnable tests[] = new Runnable[4];
	// tests[0] = new PathSettings(SWT.ON, 200);
	// tests[1] = new PathSettings(SWT.OFF, 100);
	// tests[2] = new PathSettings(SWT.DEFAULT, 200);
	// tests[3] = new PathSettings(SWT.ON, 150);
	// performTestcase(new Runnable() {
	// public void run() {
	// g.setFillRule(SWT.FILL_EVEN_ODD);
	// g.fillPath(path1);
	// g.fillPath(path2);
	// }
	// }, tests);
	//
	// path1.dispose();
	// }

	public void testPatterns() {

		class SetPattern implements Runnable {
			private final Pattern bg;
			private final Pattern fg;

			SetPattern(Pattern bg, Pattern fg) {
				this.bg = bg;
				this.fg = fg;
			}

			public void run() {
				g.setBackgroundPattern(bg);
				g.setForegroundPattern(fg);
			}
		}

		// Initial state
		Font f = new Font(null, "Helvetica", 50, SWT.BOLD);
		resources.push(f);
		g.setFont(f);
		g.setBackgroundColor(ColorConstants.yellow());
		g.pushState();

		Pattern gradient = new Pattern(null, 0, 0, 80, 40,
				ColorConstants.gray(), ColorConstants.black());
		Pattern image = new Pattern(null, TestImages.depth_24);

		resources.push(gradient);
		resources.push(image);

		Runnable tests[] = new Runnable[1];
		tests[0] = new SetPattern(image, gradient);
		performTestcase(new Runnable() {
			public void run() {
				g.fillText("W", 0, 0);
			}
		}, tests);

	}

}