#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ncursesw/ncurses.h>
#include <locale.h>
#include <iconv.h>
#include <netinet/in.h>

#include "env.h"
#include "error.h"
#include "nt_string.h"
#include "utils/nt_std_t.h"
#include "net/nt_http.h"
#include "net/nt_socket.h"
#include "net/nt_cookie.h"
#include "utils/file.h"
#include "_2ch/_2ch.h"
#include "_2ch/maru_2ch.h"
#include "ui/disp.h"
#include "ui/disp_win.h"
#include "ui/disp_string.h"

#define S_SIZE 	(1024)

static int draw_title(WINDOW *wp, wchar_t *title, attr_t attr);
static BOOL DoLoop(WINDOW *scrp);
static void print_error(WINDOW *wp, wchar_t *msg);


int main(int argc, char *argv[])
{
	int result = 1;
	WINDOW *scrp;

	if(0 != set_option(argc, argv)){
		return 1;
	}


	sleep(1);

	setlocale(LC_ALL, "ja_JP.UTF-8");

	scrp = initscr();
	if(!scrp){
		fputs("Couldn't initialize Curses libraly.\n", stderr);
		printf("Exit.");
		return 1;
	}

	if(!nt_2ch_model_init()){
		fputs("Failed to read the board menu data.\n", stderr);
		goto ERROR_TRAP;
	}

	if(!nt_init_board_menu()){
		fputs("Failed to initialize the board menu data.\n", stderr);
		goto ERROR_TRAP;
	}

	cbreak();
	noecho();

	if(DoLoop(scrp))
		result = 0;

	echo();
	nocbreak();

ERROR_TRAP:
	clear();


	nt_2ch_model_free(app_2ch_modelp);
	endwin();
	return (result);
}


static BOOL DoLoop(WINDOW *scrp)
{
	int ch, state, num;
	int disp_state, nresult;
	nt_window_tp bwinp = NULL;
	nt_window_tp twinp = NULL;
	nt_window_tp rwinp = NULL;
	char buf[256];
	wchar_t wch, *title;
	wchar_t *status_msg = NULL;
	BOOL result = FALSE;
	nt_write_data_tp writep = NULL;
	nt_maru_2ch_tp marup = NULL;
	nt_cookie_tp cookiep;

	disp_state = DISP_STATE_BOARDMENU; 
	cookiep = nt_load_cookies(USR_COOKIE_PATH);

	if(MARU_ID && MARU_PW) 
		marup = nt_maru_2ch_alloc(MARU_ID, MARU_PW);

	ch = NT_KEY_NONE;
	bwinp = nt_disp_win_alloc(scrp, LINES-1, COLS, 1, 0, buf);
	if(!bwinp)
		return FALSE;
	twinp = nt_disp_win_alloc(scrp, LINES-1, COLS, 1, 0, buf);
	if(!twinp)
		return FALSE;
	rwinp = nt_disp_win_alloc(scrp, LINES-1, COLS, 1, 0, buf);
	if(!rwinp)
		return FALSE;


	while(1){
		if(FORCE_REFRESH)
			wclear(scrp);
		else
			werase(scrp);
		switch(disp_state){
		case DISP_STATE_BOARDMENU:
			werase(bwinp->wp);
			bwinp->key = ch;
			draw_title(scrp, L"板一覧", WA_REVERSE);
			if(!nt_disp_win_move(scrp, bwinp, LINES-1, COLS, 1, 0))
				goto END_WHILE;
			state = disp_board_menu(bwinp, app_2ch_modelp);
			if(DISP_STATE_ERROR == state){
				goto END_WHILE;
			}else if(DISP_STATE_THREADTITLE == state){
				if(nt_read_board(app_2ch_modelp)){
					disp_state = state;
					if(twinp->data){
						free_threadlist_ctx(twinp->data);
						twinp->data = NULL;
					}
					ch = NT_KEY_NONE;
					continue;
				}else{
					print_error(scrp, NT_ERR_MSG_COUDLNOT_READ_BOARD);
				}
			}
			break;
		case DISP_STATE_THREADTITLE:
			werase(twinp->wp);
			twinp->key = ch;
			twinp->status_msg = NULL;
			title = app_2ch_modelp->selected_boardp->name;
			draw_title(scrp, title, WA_REVERSE);
			if(!nt_disp_win_move(scrp, twinp, LINES-1, COLS, 1, 0))
				goto END_WHILE;
			state = disp_threadlist(twinp, app_2ch_modelp);
			if(DISP_STATE_ERROR == state){
				goto END_WHILE;
			}else {
				if(DISP_STATE_BOARDMENU == state){
					disp_state = state;
					ch = NT_KEY_NONE;
					continue;
				}else if(DISP_STATE_REFRESH == state){
					if(nt_read_board(app_2ch_modelp)){
						if(twinp->data){
							free_threadlist_ctx(twinp->data);
							twinp->data = NULL;
						}
						ch = NT_KEY_NONE;
						status_msg = NT_INFO_REFRESH_BOARD_SUCCESS;
						continue;
					}else{
						status_msg = NT_ERR_MSG_COUDLNOT_READ_BOARD;
					}
				}else if(DISP_STATE_RESLIST == state){
					if(!nt_read_thread(app_2ch_modelp)){
						wclear(scrp);
						ch = NT_KEY_NONE;
						continue;
					}
					if(rwinp->data){
						free_reslist_ctx(rwinp->data);
						rwinp->data = NULL;
					}
					disp_state = state;
					ch = NT_KEY_NONE;
					continue;
				}else{
					status_msg = twinp->status_msg;
				}
			}
			break;
		case DISP_STATE_RESLIST:
			werase(rwinp->wp);
			title = app_2ch_modelp->selected_threadp->name;
			num = draw_title(scrp, title, WA_REVERSE);
			if(!nt_disp_win_move(scrp, rwinp, 
						LINES - num, COLS, num, 0))
				goto END_WHILE;
			rwinp->key = ch;
			state = disp_reslist(rwinp, app_2ch_modelp);
			if(DISP_STATE_ERROR == state){
				goto END_WHILE;
			}else if(state == DISP_STATE_REFRESH){
					ch = NT_KEY_NONE;
					if(!nt_read_thread(app_2ch_modelp)){
						status_msg = NT_ERR_MSG_REFRESH_THREAD_FAILED;
						wclear(scrp);
						continue;
					}
					if(rwinp->data){
						free_reslist_ctx(rwinp->data);
						rwinp->data = NULL;
					}
					status_msg = NT_INFO_REFRESH_THREAD_SUCCESS;
					wclear(scrp);
					continue;
			}else if(state != DISP_STATE_RESLIST){
				disp_state = state;
				ch = NT_KEY_NONE;
				continue;
			}
			break;
		case DISP_STATE_EDITOR:
			disp_state = DISP_STATE_RESLIST;
			ch = NT_KEY_NONE;
			if(writep)
				nt_write_data_free(writep);
			writep = nt_write_data_alloc();
			if(!writep)
				goto END_WHILE;
			if(disp_editor(writep)){
				if(marup && !marup->sid)
					get_session_id(marup);
				if(nt_write_msg(app_2ch_modelp, 
						writep, cookiep, marup)){
					disp_state = DISP_STATE_HTML_RESULT;
					continue;
				}
			}
			status_msg = writep->status_msg;
			wclear(scrp);
			continue;
		case DISP_STATE_HTML_RESULT:
			nresult = disp_html_result(writep);
			if(0 == nresult){
				if(!nt_read_thread(app_2ch_modelp))
					break;
				if(rwinp->data){
					free_reslist_ctx(rwinp->data);
					rwinp->data = NULL;
				}
			}else if(1 == nresult){
				if(nt_write_msg(app_2ch_modelp, 
						writep, cookiep, marup)){
					if(0 == disp_html_result(writep)){
						if(!nt_read_thread(app_2ch_modelp))
							break;
						if(rwinp->data){
							free_reslist_ctx(rwinp->data);
							rwinp->data = NULL;
						}
					}
				}
			}
			disp_state = DISP_STATE_RESLIST;
			ch = NT_KEY_NONE;
			status_msg = writep->status_msg;
			wclear(scrp);
			continue;
		default:
		 	goto END_WHILE;
		}/* end switch*/

		if(status_msg){
			print_error(scrp, status_msg);
			status_msg = NULL;
		}

		move(LINES-1,COLS-1);
		touchwin(scrp);
		wrefresh(scrp);
		ch = getch();
		switch(ch){
		case NT_KEY_UP:
		case NT_KEY_DOWN:
		case NT_KEY_LEFT:
		case NT_KEY_RIGHT:
		case NT_KEY_PAGEUP:
		case NT_KEY_PAGEDOWN:
		case NT_KEY_SELECT:
		case NT_KEY_ADD:
		case NT_KEY_DEL:
		case NT_KEY_BOTTOM:
		case NT_KEY_REFRESH:
			break;
		case NT_KEY_CLOSE:
			wclear(scrp);
			break;
		case NT_KEY_COMMAND1:
		case NT_KEY_COMMAND2:
		case NT_KEY_COMMAND3:
			echo();
			nocbreak();
			wch = ch;
			move(LINES-1,0);
			nt_add_wch(scrp,wch,0);
			getstr(buf);
			cbreak();
			noecho();
			break;
		case NT_KEY_ERASE:
			wclear(scrp);
			break;
		case NT_KEY_QUIT:
			result = TRUE;
			goto END_WHILE;
		}/* end switch*/
	}/* end while */
END_WHILE:
	if(cookiep)
		nt_unload_cookie(cookiep);
	if(marup)
		nt_maru_2ch_free(marup);
	if(writep)
		nt_write_data_free(writep);
	free_board_menu_ctx(bwinp->data);
	free_threadlist_ctx(twinp->data);
	free_reslist_ctx(rwinp->data);
	nt_disp_win_free(bwinp);
	nt_disp_win_free(twinp);
	nt_disp_win_free(rwinp);
	return result;
}

static int draw_title(WINDOW *wp, wchar_t *title, attr_t attr)
{
	move(0,0);
	int  num;
	num = nt_get_wc_count_within_colmns(title, COLS-1);
	if(num == 0)
		return 0;
	
	nt_add_wnch(wp, L' ', attr, COLS);
	move(0,1);
	nt_add_wnstr(wp, title, WA_REVERSE, COLS - 1);
	return 1;
}



static void print_error(WINDOW *wp, wchar_t *msg)
{
	move(LINES-1,0);
	nt_add_wstr(wp, msg, 0);
}

