#include "AUDIO.h"
#include "WS2812.h"
#include "sound_v1.wav.h"

#include "cy8c624abzi_s2d44.h"
#include "cybsp.h"
#include "cycfg_peripherals.h"

void SetAllLeds(uint8_t r, uint8_t g, uint8_t b) {
	for (size_t j = 0; j < 4; j++) {
		WS2812_SetLed(j, r, g, b);
	}
}

void SetLedRainbow(size_t ledIndex, int animationPosition) {
#define RBW_UP offset
#define RBW_DOWN (255 - offset - 1)

	int phase = animationPosition / 255;
	uint8_t offset = (uint8_t)(animationPosition % 255);

	uint8_t r, g, b;
	if (phase == 0) {
		r = 255;
		g = RBW_UP;
		b = 0;
	} else if (phase == 1) {
		r = RBW_DOWN;
		g = 255;
		b = 0;
	} else if (phase == 2) {
		r = 0;
		g = 255;
		b = RBW_UP;
	} else if (phase == 3) {
		r = 0;
		g = RBW_DOWN;
		b = 255;
	} else if (phase == 4) {
		r = RBW_UP;
		g = 0;
		b = 255;
	} else if (phase == 5) {
		r = 255;
		g = 0;
		b = RBW_DOWN;
	} else {
		r = 255;
		g = 0;
		b = 0;
	}

	WS2812_SetLed(ledIndex, r, g, b);
}

int main(void) {
	cy_rslt_t status;

	status = cybsp_init();
	CY_ASSERT(status == CY_RSLT_SUCCESS);

	__enable_irq();

	WS2812_Init();
	// AUDIO_Init();

	for (;;) {
		if (Cy_GPIO_Read(GPIO_PRT10, 1) == 0) {
			// left ghost pop up
			SetAllLeds(0, 0, 0);
			for (int i = 0; i < 10; i++) {
				WS2812_SetLed(0, 25 * i + 5, 0, 0);
				WS2812_Transmit();
				cyhal_system_delay_ms(5);
			}

			// left ghost alternate
			for (int i = 0; i < 10; i++) {
				WS2812_SetLed(0, 150, 0, 0);
				WS2812_Transmit();
				cyhal_system_delay_ms(300);

				WS2812_SetLed(0, 255, 0, 0);
				WS2812_Transmit();
				cyhal_system_delay_ms(300);
			}

			// ghost round and  change color
			int activeGhost = 0;
			int dir = 1;
			int animationPosition = 0;
			for (int i = 0; i < 100; i++) {
				int prevGhost = activeGhost;
				activeGhost += dir;
				if (activeGhost == 4) {
					activeGhost = 2;
					dir = -1;
				} else if (activeGhost == -1) {
					activeGhost = 1;
					dir = 1;
				}

				if (i < 70) {
					WS2812_SetLed(prevGhost, 0, 0, 0);
				}
				SetLedRainbow(activeGhost, animationPosition);
				WS2812_Transmit();
				cyhal_system_delay_ms(60);

				animationPosition += 15;
			}

			// left and right full white
			SetAllLeds(0, 0, 0);
			WS2812_SetLed(0, 255, 255, 255);
			WS2812_SetLed(3, 255, 255, 255);
			WS2812_Transmit();
			cyhal_system_delay_ms(1200);

			// disapear
			for (int i = 255; i >= 0; i--) {
				WS2812_SetLed(0, i, i, i);
				WS2812_SetLed(3, i, i, i);
				WS2812_Transmit();
				cyhal_system_delay_ms(3);
			}

			// block for quick retrigger
			status = cyhal_system_delay_ms(10000);
			CY_ASSERT(status == CY_RSLT_SUCCESS);

			// wait if still movement detected
			while (Cy_GPIO_Read(GPIO_PRT10, 1) == 0) {
			}
		}
	}
}
