#include <mem.h>
#include <utilities.h>

#include "app.h"

int HandleSockAnsw(int msg, int param)
{
	UINT32			w;
	
	switch ( msg ) {
	
		case MSG_SOCKET_CREATE:
			dbg("SockAnsw: MSG_SOCKET_CREATE");
			SockConnect( ElfGetDItem(item_select)->host,ElfGetDItem(item_select)->port );
			break;
			
		case MSG_SOCKET_NOWRITE:
			dbg("SockAnsw: XOFF");
			break;
			
		case MSG_SOCKET_READY:
			dbg("SockAnsw: MSG_SOCKET_READY");
			SockSend( ElfGetDItem(item_select)->header, strlen(ElfGetDItem(item_select)->header) );
			break;
			
		case MSG_SOCKET_DATA: // входящие данные
			dbg("SockAnsw: MSG_SOCKET_DATA");
			// Проверяем статус закачки, чтобы не качать при остановленной закачке
			if (download_state == DOWNLOAD_STOPPED || download_state == DOWNLOAD_ERROR) return RESULT_OK;

			char tmp_buf[2028]; // Буфер приема даннях
			int nrecv = SockRead(tmp_buf, sizeof(tmp_buf)); // Получаем даные
			int hsize; // Длина HTTP заголовка
			int l_len = 0;    // Длина текущей строки
			char l_buf[512];  // Буфер текущей строки
			int n_CR = 0;     // Число CR в конце строки
			int n_LF = 0;     // Число LF в конце строки
			switch(http_state)
			{
				case HTTP_HEADER: // Принимаем заголовок HTTP
					download_state = DOWNLOAD_GET_INFO;
					//header_process (tmp_buf, "Content-Length", header_extract_number,  &ElfGetDItem(item_select)->file_size);
					do {
						l_len = 0;
						n_CR = 0;
						n_LF = 0;

						while (!(tmp_buf[l_len]=='\r' || tmp_buf[l_len]=='\n') && (l_len<nrecv)) // Считаем длину строки
							l_len++;

						strncpy(l_buf, tmp_buf, l_len); // Копируем строку в буфер
						l_buf[l_len] = 0;

						while(tmp_buf[l_len]=='\n' || tmp_buf[l_len]=='\r') {// Пропускаем CR и LF
						
							if (tmp_buf[l_len]=='\r') n_CR++; // Считаем все CR в конце строки
							if (tmp_buf[l_len]=='\n') n_LF++; // Считаем все LF в конце строки
							l_len++;
						}
						
						tmp_buf += l_len; // Переходим к следующей строке
						nrecv -= l_len;
						hsize += l_len;
						
						if (n_CR == 2 || n_LF == 2) break; // Конец заголовка. в основном кончается на \r\n\r\n, но бывают и исключения ;)
					} while (nrecv);
  
					http_state = HTTP_STREAM; // Дальше у нас идет чистый файл
					break;
				
				case HTTP_STREAM: // Принимаем данные
					if ( ElfGetDItem(item_select)->file_handle == FILE_INVALID ) {
						ElfGetDItem(item_select)->file_handle = DL_FsOpenFile(ElfGetDItem(item_select)->full_file_name, FILE_APPEND_MODE, 0); // пишем в конец файла
							if (ElfGetDItem(item_select)->file_handle == FILE_INVALID) {
								download_state = DOWNLOAD_ERROR;
								SockClose();
								return RESULT_FAIL;
							}
					}
					DL_FsWriteFile( tmp_buf + hsize, nrecv - hsize, 1, ElfGetDItem(item_select)->file_handle, &w );
					ElfGetDItem(item_select)->file_size = DL_FsGetFileSize( ElfGetDItem(item_select)->file_handle );
					hsize = 0;
					break;
			}
			
			break;
		
		case MSG_SOCKET_DISCONNECT: // сокет закрыт из-за таймаута
			dbg("SockAnsw: DELETE");
			download_state = DOWNLOAD_ERROR;
			SockClose();
			break;
		
		case MSG_SOCKET_ERROR:  // ошибка
			dbg("SockAnsw: ERROR");
			download_state = DOWNLOAD_ERROR;
			cprintf("\x8E Error: can't connect to internet\n");
			SockClose();
			break;
	}
	return RESULT_OK;
}

int SockCreatSocket() {

	dbg("SockCreatSocket");
	
	// Создаем сокет, ждем ответ
	if ( socket_create( SOCK_TCP, (const void *) HandleSockAnsw ) < 0 )  {
		dbg("SockCreatSocket: error! can't create socket!");
		download_state = DOWNLOAD_ERROR;
		return -1;
	}
	
	return 0;
}


int SockConnect(const char *hostname, int port) {

	dbgf("SockConnect: hostname = %s, port = %i", hostname, port);

		if ( socket_connect(hostname, port) != -1 ) {
			dbg("SockConnect: OK...");
            return true;
		} else {
			dbg("SockConnect: ERROR...");
			download_state = DOWNLOAD_ERROR;
            return false;
		}

	return true;
}


int SockClose( void ) {

    socket_close();
	free_socket();
	
}

int SockSend(const char *data, size_t data_len) {

	size_t 	len;
	
	len = socket_send(data, data_len);

	
#ifdef DEBUG
	cprintf("SockSend %i b \n", len);
#	ifdef DEBUG_DATA
		dbgf("SockSend:\n%s\n", data);
#	endif
#endif

	return len;
}

int SockRead(char *data, size_t data_len) {

	size_t 	len;
	
	len = socket_read(data, data_len);

	
#ifdef DEBUG
	cprintf("SockRead %i b \n", len);
#	ifdef DEBUG_DATA
		dbgf("SockRead:\n%s\n", data);
#	endif
#endif

	return len;
}
