package studio.junk.jam.coloritum.entities;

import com.badlogic.gdx.graphics.Color;

public enum Pigment {
	Yellow(new Color(0xfed500ff)), Orange(new Color(0xeb6b0aff)), Red(new Color(0xe20026ff)), Purple(
			new Color(0x4a2582ff)), Blue(new Color(0x0064acff)), Green(new Color(0x00924bff));

	/**
	 * Merging array.
	 * <p>
	 * Defines the results of all kinds of combining two pigments.
	 * <p>
	 * Per definition this array is symmetric (
	 * <code>merging[a][b] == merging[b][a]</code>).
	 */
	private static final Pigment[][] merging = new Pigment[Pigment.values().length][Pigment.values().length];

	/**
	 * Helper to fill the mergin.
	 * <p>
	 * Adds a symmetric result of combining two pigments.
	 * 
	 * @param a
	 *            first pigment
	 * @param b
	 *            second pigment
	 * @param res
	 *            the merging result
	 */
	private static final void addMerging(Pigment a, Pigment b, Pigment res) {
		merging[a.ordinal()][b.ordinal()] = res;
		merging[b.ordinal()][a.ordinal()] = res;
	}

	static {
		// defines Yellow mixes
		addMerging(Yellow, Yellow, Purple);
		addMerging(Yellow, Orange, Blue);
		addMerging(Yellow, Red, Blue);
		addMerging(Yellow, Purple, Red);
		addMerging(Yellow, Blue, Red);
		addMerging(Yellow, Green, Purple);

		// defines Orange
		addMerging(Orange, Orange, Blue);
		addMerging(Orange, Red, Green);
		addMerging(Orange, Purple, Green);
		addMerging(Orange, Blue, Purple);
		addMerging(Orange, Green, Purple);

		// defines Red
		addMerging(Red, Red, Green);
		addMerging(Red, Purple, Yellow);
		addMerging(Red, Blue, Yellow);
		addMerging(Red, Green, Blue);

		// defines Purple
		addMerging(Purple, Purple, Yellow);
		addMerging(Purple, Blue, Orange);
		addMerging(Purple, Green, Orange);

		// Blue
		addMerging(Blue, Blue, Orange);
		addMerging(Blue, Green, Red);

		// Green
		addMerging(Green, Green, Red);

		// test correctness
		for (Pigment[] ps : merging) {
			for (Pigment p : ps) {
				if (p == null) {
					System.err.println("incomplete mergin definition");
				}
			}
		}
	}

	/**
	 * The native color representing this pigment.
	 */
	public final Color color;

	/**
	 * Constructor with color mapping.
	 * 
	 * @param c
	 *            the of the pigment
	 */
	private Pigment(Color c) {
		color = c;
	}

	/**
	 * Returns the result of merging this pigment with the given one.
	 * 
	 * @param p
	 *            the pigment to merge with
	 * @return the merging result
	 */
	public Pigment merge(Pigment p) {
		return merging[this.ordinal()][p.ordinal()];
	}
}
