/*******************************************************************************
 * 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);

	}

}