
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 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[] 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) ((1-y) * effectDuration);}
	private int tickLateVerticalUp(double y) {return (int) (y * effectDuration);}
	private int tickLateHorizontalToRight(double x) {return (int) ((1-x) * effectDuration);}
	private int tickLateHorizontalToLeft(double x) {return (int) (x * effectDuration);}
	private int tickLateDiagTRDL(double x, double y) {return (int) ((x - y) / 2d * (double) effectDuration);}
	private int tickLateDiagDLTR(double x, double y) {return (int) ((-x + y) / 2d * (double) effectDuration);}
	private int tickLateDiagDRTL(double x, double y) {return (int) ((x + y) / 2d * (double) effectDuration);}
	private int tickLateDiagTLDR(double x, double y) {return (int) ((-x - y) / 2d * (double) effectDuration);}
	private int tickLateCenterOut(double x, double y) {return (int) ((1 - (x-0.5)*(x-0.5) - (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);}
	private int tickLateCenterIn(double x, double y) {return (int) (((x-0.5)*(x-0.5) + (y-0.5)*(y-0.5)) * 2 * (double) effectDuration);}

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