#include "flash-loader.hpp"
#include "graphics/color.hpp"
#include <cmath>
#include "quadspi.h"
#include "CDCCommandStream.h"
#include "USBManager.h"

#include <cstring>
#include <stdio.h>
#include <stdlib.h>
using namespace blit;

extern QSPI_HandleTypeDef hqspi;
extern CDCCommandStream g_commandStream;

FlashLoader flashLoader;

extern USBManager g_usbManager;

// c calls to c++ object
void init()
{
	flashLoader.Init();
}

void render(uint32_t time)
{
	flashLoader.Render(time);
}

void update(uint32_t time)
{
	flashLoader.Update(time);
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// Init() Register command handlers
void FlashLoader::Init()
{
	blit::set_screen_mode(ScreenMode::hires);

	// register PROG
	g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'P', 'R', 'O', 'G'>::value, this);

	// register SAVE
	g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'S', 'A', 'V', 'E'>::value, this);

	// register LS
	g_commandStream.AddCommandHandler(CDCCommandHandler::CDCFourCCMake<'_', '_', 'L', 'S'>::value, this);

	m_uCurrentFile = persist.selected_menu_item;
}


// FSInit() Read a page worth of *.BIN filenames from the SDCard
void FlashLoader::FSInit(void)
{
	// needed as init is called before sdcard is mounted currently.
	m_uFileCount = 0;

	volatile FRESULT fr;     /* Return value */
	DIR dj;         /* Directory search object */
	FILINFO fno;    /* File information */
	Size s;			/* Size of rendered texts */

	fr = f_findfirst(&dj, &fno, "", "*.BIN");

	while (fr == FR_OK && fno.fname[0] && m_uFileCount < MAX_FILENAMES)
	{
		if(fno.fname[0]!='.')
		{
			strncpy(m_filemeta[m_uFileCount].sFilename, fno.fname, MAX_FILENAME_LENGTH);
			s = screen.measure_text(m_filemeta[m_uFileCount].sFilename, minimal_font, true);
			if (s.w > m_max_width_name) m_max_width_name = s.w;

			m_filemeta[m_uFileCount].fstFilesize = fno.fsize;
			sprintf(m_filemeta[m_uFileCount].sFilesize, "%lu", m_filemeta[m_uFileCount].fstFilesize);
			s = screen.measure_text(m_filemeta[m_uFileCount].sFilesize, minimal_font, true);
			if (s.w > m_max_width_size) m_max_width_size = s.w;

			m_uFileCount++;
		}
		fr = f_findnext(&dj, &fno);
	}

	if(m_uCurrentFile > m_uFileCount) {
		m_uCurrentFile = m_uFileCount;
	}

	f_closedir(&dj);

	m_bFsInit = true;
}


// Flash(): Flash a file from the SDCard to external flash
bool FlashLoader::Flash(const char *pszFilename)
{
	bool bResult = false;

	FIL file;
	FRESULT res = f_open(&file, pszFilename, FA_READ);
	if(!res)
	{
		// get file length
		FSIZE_t uSize = f_size(&file);
		FSIZE_t uTotalBytesRead = 0;
		size_t uOffset = 0;

		if(uSize)
		{
			// quick and dirty erase
			QSPI_WriteEnable(&hqspi);
			qspi_chip_erase();

			bool bFinished = false;

			while(!bFinished)
			{
				// limited ram so a bit at a time
				UINT uBytesRead = 0;
				res = f_read(&file, (void *)m_buffer, BUFFER_SIZE, &uBytesRead);

				if(!res)
				{
					if(uBytesRead)
					{
						if(QSPI_OK == qspi_write_buffer(uOffset, m_buffer, uBytesRead))
						{
							if(QSPI_OK == qspi_read_buffer(uOffset, m_verifyBuffer, uBytesRead))
							{
								// compare buffers
								bool bVerified = true;
								for(uint32_t uB = 0; bVerified && uB < uBytesRead; uB++)
									bVerified = m_buffer[uB] == m_verifyBuffer[uB];

								if(bVerified)
								{
									uOffset += uBytesRead;
									uTotalBytesRead += uBytesRead;
								}
								else
									bFinished = true;
							}
							else
								bFinished = true;
						}
						else
							bFinished = true;
					}

					if(uBytesRead < BUFFER_SIZE)
					{
						bFinished = true;
						bResult = uTotalBytesRead == uSize;
					}
				}
				else
					bFinished = true;
			}
		}

		f_close(&file);
	}

	return bResult;
}


// Render() Call relevant render based on state
void FlashLoader::Render(uint32_t time)
{
	switch(m_state)
	{
		case stFlashFile:
		case stLS:
			RenderFlashFile(time);
			break;

		case stSaveFile:
			RenderSaveFile(time);
			break;

		case stFlashCDC:
			RenderFlashCDC(time);
			break;

		case stSwitch:
			blit_switch_execution();
		break;

		case stMassStorage:
			RenderMassStorage(time);
		break;
	}
}

void FlashLoader::RenderMassStorage(uint32_t time)
{
	static uint8_t uActivityAnim = 0;

	screen.pen = Pen(0,0,0);
	screen.rectangle(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
	screen.pen = Pen(255, 255, 255);
	char buffer[128];
	sprintf(buffer, "Mass Storage mode (%s)", g_usbManager.GetStateName());
	screen.text(buffer, minimal_font, ROW(0));

	if(uActivityAnim)
	{
		screen.pen = Pen(0, 255, 0, uActivityAnim);
		screen.circle(Point(320-6, 6), 6);
		uActivityAnim = uActivityAnim>>1;

	}
	else
	{
		if(g_usbManager.HasHadActivity())
			uActivityAnim = 255;
	}


	if(g_usbManager.GetState() == USBManager::usbsMSCUnmounted)
	{
		// Swicth back to CDC
		g_usbManager.SetType(USBManager::usbtCDC);
		FSInit();
		m_state = stFlashFile;
	}
}

// RenderSaveFile() Render file save progress %
void FlashLoader::RenderSaveFile(uint32_t time)
{
	screen.pen = Pen(0,0,0);
	screen.rectangle(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
	screen.pen = Pen(255, 255, 255);
	char buffer[128];
	sprintf(buffer, "Saving %.2u%%", (uint16_t)m_fPercent);
	screen.text(buffer, minimal_font, ROW(0));
}


// RenderFlashCDC() Render flashing progress %
void FlashLoader::RenderFlashCDC(uint32_t time)
{
	screen.pen = Pen(0,0,0);
	screen.rectangle(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
	screen.pen = Pen(255, 255, 255);

	char buffer[128];
	sprintf(buffer, "Flashing %.2u%%", (uint16_t)m_fPercent);
	screen.text(buffer, minimal_font, ROW(0));
}


// RenderFlashFile() Render main ui for selecting files to flash
void FlashLoader::RenderFlashFile(uint32_t time)
{
	static uint32_t lastRepeat = 0;

	if(!m_bFsInit)
		FSInit();

	bool button_a = buttons.pressed & Button::A;
	bool button_x = buttons.pressed & Button::X;
	bool button_y = buttons.pressed & Button::Y;

	bool button_up = buttons.pressed & Button::DPAD_UP;
	bool button_down = buttons.pressed & Button::DPAD_DOWN;

	bool button_home = buttons.pressed & Button::HOME;

	if(time - lastRepeat > 150 || button_up || button_down) {
		button_up = buttons & Button::DPAD_UP;
		button_down = buttons & Button::DPAD_DOWN;
		lastRepeat = time;
	}

	screen.pen = Pen(0,0,0);
	screen.rectangle(Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
	screen.pen = Pen(255, 255, 255);

	// just display
	if(m_uFileCount)
	{
		screen.pen = Pen(50, 50, 70);
		screen.rectangle(Rect(0, ROW_HEIGHT*m_uCurrentFile, SCREEN_WIDTH, ROW_HEIGHT));
		screen.pen = Pen(255, 255, 255);

		for(uint8_t uF = 0; uF < m_uFileCount; uF++) {
			// TODO: A single line of text should probably vertically center in a 10px bounding box
			// but in this case it needs to be fudged to 14 pixels
			screen.text(m_filemeta[uF].sFilename, minimal_font, Rect(ROW(uF).x + 5, ROW(uF).y, m_max_width_name, 14), true, TextAlign::center_v);
			screen.line(Point(m_max_width_name + 10, ROW(uF).y), Point(m_max_width_name + 10, ROW(uF).y + 14));
			screen.text(m_filemeta[uF].sFilesize, minimal_font, Rect(m_max_width_name + 16, ROW(uF).y, m_max_width_size, 14), true, TextAlign::center_right);
		}
	}
	else
	{
		screen.text("No Files Found.", minimal_font, ROW(0));
	}

	if(button_home)
	{
		// switch to mass media
		g_usbManager.SetType(USBManager::usbtMSC);
		m_state = stMassStorage;

	}

	if(button_up)
	{
		if(m_uCurrentFile > 0) {
			m_uCurrentFile--;
		} else {
			m_uCurrentFile = m_uFileCount - 1;
		}
	}

	if(button_down)
	{
		if(m_uCurrentFile < (m_uFileCount - 1)) {
			m_uCurrentFile++;
		} else {
			m_uCurrentFile = 0;
		}
	}

	if(button_a)
	{
		if(Flash(m_filemeta[m_uCurrentFile].sFilename)) {
			blit_switch_execution();
		}
	}

	if (button_x)
	{
		// Sort by filename
		std::sort(&m_filemeta[0], &m_filemeta[m_uFileCount], [](auto a, auto b) { return strcmp(a.sFilename, b.sFilename) <= 0; });
	}

	if (button_y)
	{
		// Sort by filesize
		std::sort(&m_filemeta[0], &m_filemeta[m_uFileCount], [](auto a, auto b) { return a.fstFilesize <= b.fstFilesize; });
	}

	persist.selected_menu_item = m_uCurrentFile;
}


void FlashLoader::Update(uint32_t time)
{
	if(m_state == stLS)
	{
		FSInit();
		m_state = stFlashFile;
	}
}




//////////////////////////////////////////////////////////////////////
// Streaming Code
//  The streaming code works with a simple state machine,
//  current state is in m_parseState, the states parse index is
//  in m_uParseState
//////////////////////////////////////////////////////////////////////

// StreamInit() Initialise state machine
bool FlashLoader::StreamInit(CDCFourCC uCommand)
{
	//printf("streamInit()\n\r");
	m_fPercent = 0.0f;
	bool bNeedStream = true;
	switch(uCommand)
	{
		case CDCCommandHandler::CDCFourCCMake<'P', 'R', 'O', 'G'>::value:
			m_state = stFlashCDC;
			m_parseState = stFilename;
			m_uParseIndex = 0;
		break;

		case CDCCommandHandler::CDCFourCCMake<'S', 'A', 'V', 'E'>::value:
			m_state = stSaveFile;
			m_parseState = stFilename;
			m_uParseIndex = 0;
		break;

		case CDCCommandHandler::CDCFourCCMake<'_', '_', 'L', 'S'>::value:
			m_state = stLS;
			bNeedStream = false;
		break;

	}
	return bNeedStream;
}


// FlashData() Flash data to the QSPI flash
// Note: currently qspi_write_buffer only works for sizes of 256 max
bool FlashLoader::FlashData(uint32_t uOffset, uint8_t *pBuffer, uint32_t uLen)
{
	bool bResult = false;
	if(QSPI_OK == qspi_write_buffer(uOffset, pBuffer, uLen))
	{
		if(QSPI_OK == qspi_read_buffer(uOffset, m_verifyBuffer, uLen))
		{
			// compare buffers
			bResult = true;

			for(uint32_t uB = 0; bResult && uB < uLen; uB++)
				bResult = pBuffer[uB] == m_verifyBuffer[uB];
		}
	}
	return bResult;
}


// SaveData() Saves date to file on SDCard
bool FlashLoader::SaveData(uint8_t *pBuffer, uint32_t uLen)
{
	UINT uWritten;
	FRESULT res = f_write(&m_file, pBuffer, uLen, &uWritten);

	return !res && (uWritten == uLen);

}


// StreamData() Handle streamed data
// State machine has three states:
// stFilename : Parse filename
// stLength   : Parse length, this is sent as an ascii string
// stData     : The binary data (.bin file)
CDCCommandHandler::StreamResult FlashLoader::StreamData(CDCDataStream &dataStream)
{
	CDCCommandHandler::StreamResult result = srContinue;
	uint8_t byte;
	while(dataStream.GetStreamLength() && result == srContinue)
	{
		switch (m_parseState)
		{
			case stFilename:
				if(m_uParseIndex < MAX_FILENAME)
				{
					while(result == srContinue && m_parseState == stFilename && dataStream.Get(byte))
					{
						m_sFilename[m_uParseIndex++] = byte;
						if (byte == 0)
						{
							m_parseState = stLength;
							m_uParseIndex = 0;
						}
					}
				}
				else
				{
					printf("Failed to read filename\n\r");
					result =srError;
				}
			break;


			case stLength:
				if(m_uParseIndex < MAX_FILELEN)
				{
					while(result == srContinue && m_parseState == stLength && dataStream.Get(byte))
					{
						m_sFilelen[m_uParseIndex++] = byte;
						if (byte == 0)
						{
							m_parseState = stData;
							m_uParseIndex = 0;
							char *pEndPtr;
							m_uFilelen = strtoul(m_sFilelen, &pEndPtr, 10);
							if(m_uFilelen)
							{
								// init file or flash
								switch(m_state)
								{
									case stSaveFile:
									{
										FRESULT res = f_open(&m_file, m_sFilename, FA_CREATE_ALWAYS | FA_WRITE);
										if(res)
										{
											printf("Failed to create file (%s)\n\r", m_sFilename);
											result = srError;
										}
									}
									break;

									case stFlashCDC:
										QSPI_WriteEnable(&hqspi);
										qspi_chip_erase();
									break;

									default:
									break;
								}
							}
							else
							{
								printf("Failed to parse filelen\n\r");
								result =srError;
							}
						}
					}
				}
				else
				{
					printf("Failed to read filelen\n\r");
					result =srError;
				}
			break;

			case stData:
					while((result == srContinue) && (m_parseState == stData) && (m_uParseIndex <= m_uFilelen) && dataStream.Get(byte))
					{
						uint32_t uByteOffset = m_uParseIndex % PAGE_SIZE;
						m_buffer[uByteOffset] = byte;

						// check buffer needs writing
						volatile uint32_t uWriteLen = 0;
						bool bEOS = false;
						if (m_uParseIndex == m_uFilelen-1)
						{
							uWriteLen = uByteOffset+1;
							bEOS = true;
						}
						else
							if(uByteOffset == PAGE_SIZE-1)
								uWriteLen = PAGE_SIZE;

						if(uWriteLen)
						{
							switch(m_state)
							{
								case stSaveFile:
									// save data
									if(!SaveData(m_buffer, uWriteLen))
									{
										printf("Failed to save to SDCard\n\r");
										result = srError;
									}

									// end of stream close up
									if(bEOS)
									{
										f_close(&m_file);
										m_bFsInit = false;
										m_state = stFlashFile;
										if(result != srError)
											result = srFinish;
									}
								break;

								case stFlashCDC:
								{
									// save data
									volatile uint32_t uPage = (m_uParseIndex / PAGE_SIZE);
									if(!FlashData(uPage*PAGE_SIZE, m_buffer, uWriteLen))
									{
										printf("Failed to write to flash\n\r");
										result = srError;
									}

									// end of stream close up
									if(bEOS)
									{
										if(result != srError)
										{
											result = srFinish;
											m_state = stSwitch;
										}
										else
											m_state = stFlashFile;
									}
								}
								break;

								default:
								break;
							}
						}

						m_uParseIndex++;
						m_uBytesHandled = m_uParseIndex;
						m_fPercent = ((float)m_uParseIndex/(float)m_uFilelen)* 100.0f;
					}
			break;
		}
	}

	if(result==srError)
		m_state = stFlashFile;

	return result;
}

