
public class MusicPath {
	public static final double[][] LIGHT_COORDS = new double[][] {
		// Planche 1
		{0.0383, 0}, {0.0766, 0}, {0.115, 0}, {0.1533, 0}, {0.1916, 0}, {0.23, 0}, //M1L1
		{0.2683, 0}, {0.306, 0}, {0.345, 0}, {0.383, 0}, {0.4216, 0}, {0.46, 0}, {0.4983, 0}, //M1L2
		{0.0333, 0.25}, {0.0666, 0.25}, {0.0999, 0.25}, {0.1333, 0.25}, //P1-1
		{0.3016, 0.25}, {0.3366, 0.25}, {0.3733, 0.25}, {0.4099, 0.25}, {0.4466, 0.25}, {0.4833, 0.25}, {0.5199, 0.25}, //P1-2
		{0.3366, 0.3}, {0.3366, 0.35}, //P1-3
		{0, 0.3075}, {0, 0.365}, {0, 0.4225}, //M1l1

		// Planche 2
		{0.5366, 0}, {0.575, 0}, {0.6133, 0}, {0.6516, 0}, {0.69, 0}, {0.7283, 0}, {0.7666, 0}, //M2L1
		{0.805, 0}, {0.8433, 0}, {0.8816, 0}, {0.92, 0}, {0.9583, 0}, //M2L2
		{0.5566, 0.25}, {0.5933, 0.25}, {0.6299, 0.25}, {0.6666, 0.25}, //P2-1
		{0.8366, 0.25}, {0.8699, 0.25}, {0.9032, 0.25}, {0.9366, 0.25}, {0.9699, 0.25}, //P2-2
		{1, 0.06}, {1, 0.115}, {1, 0.17}, {1, 0.225}, {1, 0.28}, {1, 0.335}, {1, 0.39}, //M2l1
		
		// Planche 3
		{0.3366, 0.4}, {0.3366, 0.45}, {0.3366, 0.5}, //P3-1
		{0.3366, 0.75}, {0.3366, 0.8}, //P3-2
		{0, 0.48}, {0, 0.5375}, {0, 0.595}, {0, 0.6525}, {0, 0.71}, {0, 0.7675}, //M3l1
		
		// Planche 4
		{1, 0.445}, {1, 0.5}, {1, 0.555}, {1, 0.61}, {1, 0.665}, {1, 0.72}, {1, 0.775}, //M4l1
		
		// Planche 5
		{0.0383, 1}, {0.0766, 1}, {0.115, 1}, {0.1533, 1}, {0.1916, 1}, {0.23, 1}, //M5L1
		{0.2683, 1}, {0.306, 1}, {0.345, 1}, {0.383, 1}, {0.4216, 1}, {0.46, 1}, {0.4983, 1}, //M5L2
		{0.3366, 0.85}, {0.3366, 0.9}, {0.3366, 0.95}, //P5-1
		{0, 0.8255}, {0, 0.8835}, {0, 0.9415}, //M5l1
		
		// Planche 6
		{0.5366, 1}, {0.575, 1}, {0.6133, 1}, {0.6516, 1}, {0.69, 1}, {0.7283, 1}, {0.7666, 1}, //M6L1
		{0.805, 1}, {0.8433, 1}, {0.8816, 1}, {0.92, 1}, {0.9583, 1}, //M6L2
		{1, 0.83}, {1, 0.885}, {1, 0.94} //M6l1
	};
	
	public static final String[] pathNames = new String[] {
			"Vertical down",
			"Vertical up",
			"Horizontal right to left",
			"Horizontal left to right",
			"Diagonal up right to down left",
			"Diagonal down left to up right",
			"Diagonal up left to down right",
			"Diagonal down right to up left",
			"Center out",
			"Center in",
			"Flashing",
	};
	public static final int VERTICAL_DOWN = 0;
	public static final int VERTICAL_UP = 1;
	public static final int HORIZONTAL_TO_LEFT = 2;
	public static final int HORIZONTAL_TO_RIGHT = 3;
	public static final int DIAGONAL_TOP_RIGHT_DOWN_LEFT = 4;
	public static final int DIAGONAL_DOWN_LEFT_TOP_RIGHT = 5;
	public static final int DIAGONAL_TOP_LEFT_DOWN_RIGHT = 6;
	public static final int DIAGONAL_DOWN_RIGHT_TOP_LEFT = 7;
	public static final int CENTER_OUT = 8;
	public static final int CENTER_IN = 9;
	public static final int ALL = 10;
	
	private int animation;
	private int effectDuration;
	private double[][] lightsCoords;
	
	public MusicPath(int animation, int effectDuration) { this(animation, effectDuration, LIGHT_COORDS); }
	public MusicPath(int animation, int effectDuration, double[][] lightsCoords) {
		this.animation = animation;
		this.effectDuration = effectDuration;
		this.lightsCoords = lightsCoords;
	}

	public int getAnimation() { return animation; }
	public int getEffectDuration() { return effectDuration; }
	
	public int[] calculateTickDelais() { // tick in ms
		int[] ticksDelais = new int[lightsCoords.length];
		for(int i=0; i<ticksDelais.length; i++) {
			ticksDelais[i] = 0;
			if(animation == VERTICAL_DOWN
					|| animation == VERTICAL_UP
					|| animation == HORIZONTAL_TO_LEFT
					|| animation == HORIZONTAL_TO_RIGHT
					|| animation == DIAGONAL_TOP_RIGHT_DOWN_LEFT
					|| animation == DIAGONAL_DOWN_LEFT_TOP_RIGHT
					|| animation == DIAGONAL_TOP_LEFT_DOWN_RIGHT
					|| animation == DIAGONAL_DOWN_RIGHT_TOP_LEFT
					|| animation == CENTER_OUT
					|| animation == CENTER_IN) {
				switch (animation) {
				case VERTICAL_DOWN:
					ticksDelais[i] -= tickLateVerticalDown(LIGHT_COORDS[i][1]);
					break;
				case VERTICAL_UP:
					ticksDelais[i] -= tickLateVerticalUp(LIGHT_COORDS[i][1]);
					break;
				case HORIZONTAL_TO_LEFT:
					ticksDelais[i] -= tickLateHorizontalToLeft(LIGHT_COORDS[i][0]);
					break;
				case HORIZONTAL_TO_RIGHT:
					ticksDelais[i] -= tickLateHorizontalToRight(LIGHT_COORDS[i][0]);
					break;
				case DIAGONAL_TOP_RIGHT_DOWN_LEFT:
					ticksDelais[i] -= tickLateDiagTRDL(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
					break;
				case DIAGONAL_DOWN_LEFT_TOP_RIGHT:
					ticksDelais[i] -= tickLateDiagDLTR(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
					break;
				case DIAGONAL_TOP_LEFT_DOWN_RIGHT:
					ticksDelais[i] -= tickLateDiagTLDR(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
					break;
				case DIAGONAL_DOWN_RIGHT_TOP_LEFT:
					ticksDelais[i] -= tickLateDiagDRTL(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
					break;
				case CENTER_OUT:
					ticksDelais[i] -= tickLateCenterOut(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
					break;
				case CENTER_IN:
					ticksDelais[i] -= tickLateCenterIn(LIGHT_COORDS[i][0], LIGHT_COORDS[i][1]);
					break;
				}
			}
			else if(animation == ALL);
		}
		return ticksDelais;
	}

	private int tickLateVerticalDown(double y) {return (int) (y * effectDuration);}
	private int tickLateVerticalUp(double y) {return (int) ((1-y) * effectDuration);}
	private int tickLateHorizontalToRight(double x) {return (int) (x * effectDuration);}
	private int tickLateHorizontalToLeft(double x) {return (int) ((1 - x) * effectDuration);}
	private int tickLateDiagTRDL(double x, double y) {return (int) ((1 - x + y) / 2d * (double) effectDuration);}
	private int tickLateDiagDLTR(double x, double y) {return (int) ((1 + x - y) / 2d * (double) effectDuration);}
	private int tickLateDiagTLDR(double x, double y) {return (int) ((x + y) / 2d * (double) effectDuration);}
	private int tickLateDiagDRTL(double x, double y) {return (int) ((2 - x - y) / 2d * (double) effectDuration);}
	private int tickLateCenterOut(double x, double y) {return (int) (((x-0.5)*(x-0.5) + (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);}
	private int tickLateCenterIn(double x, double y) {return (int) ((0.5d - (x-0.5)*(x-0.5) - (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);}

	public int getNumberOfLights() {
		return this.lightsCoords.length;
	}
}
