#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <wchar.h>

#include "utils/nt_std_t.h"
#include "utils/text.h"
#include "_2ch/model_2ch.h"

static nt_category_tp get_last_category(nt_2ch_model_tp modelp);

int parse_res_msg(nt_res_tp resp, size_t colmns)
{
	int i, len, start, lines;
	wchar_t ch;
	wchar_t *buf, *cptr, *srcp;
	int offset;
	nt_link_tp linkp;
	int consume_colmns;
	int buf_idx;

	assert(resp->msg);

	nt_res_msg_free(resp);
	resp->msg_line_num = 0;

	len = wcslen(resp->msg);

	if(len == 0)
		return 0;
	buf = malloc(sizeof(wchar_t) * (len + 11));
	if(!buf)
		return 0;
	buf_idx = 0;

	srcp = resp->msg;

	lines = 0;
	start = 0;
	consume_colmns = 0;
	for(i = 0; i < len; i++){
		ch = srcp[i];
		switch(ch){
		case L'&':
			if(len > (i+5)){
				if(srcp[i+1] == L'q' &&
					srcp[i+2] == L'u' &&
					srcp[i+3] == L'o' &&
					srcp[i+4] == L't' &&
					srcp[i+5] == L';'){
					ch = L'\"';
					buf[buf_idx] = ch;
					buf_idx++;
					i += 5;
					break;
				}
			}
			if(len > (i+4)){
				if(srcp[i+1] == L'a' &&
					srcp[i+2] == L'm' &&
					srcp[i+3] == L'p' &&
					srcp[i+4] == L';'){
					ch = L'&';
					buf[buf_idx] = ch;
					buf_idx++;
					i += 4;
					break;
				}
			}
			if(len > (i+3)){
				if(srcp[i+1] == L'g' &&
					srcp[i+2] == L't' &&
					srcp[i+3] == L';'){
					ch = L'>';
					buf[buf_idx] = ch;
					buf_idx++;
					i += 3;
					break;
				}else if(srcp[i+1] == L'l' &&
					srcp[i+2] == L't' &&
					srcp[i+3] == L';'){
					ch = L'<';
					buf[buf_idx] = ch;
					buf_idx++;
					i += 3;
					break;
				}
			}
			
			goto DEF_LABEL; 
		case L'<': 
			if(len > (i+3) && srcp[i+1] == L'b' &&
					srcp[i+2] == L'r' &&
					srcp[i+3] == L'>'){
				cptr = buf + start;
				buf[buf_idx] = L'\0';
				buf_idx++;
				linkp = nt_link_add_data(
						resp->msg_line_linkp, cptr);
				if(!linkp)
					goto END_FOR;
				if(resp->msg_line_linkp == NULL)
					resp->msg_line_linkp = linkp;

				consume_colmns = 0;
				lines++;
				start = buf_idx;
				i += 3;
				break;
			}else if(len > (i+7) && srcp[i+1] == L'a' &&
					srcp[i+2] == L' ' &&
					srcp[i+3] == L'h' &&
					srcp[i+4] == L'r' &&
					srcp[i+5] == L'e' &&
					srcp[i+6] == L'f' &&
					srcp[i+7] == L'='){
				cptr = wcschr(srcp+i+8, L'>');
				if(cptr){
					offset = cptr - &(srcp[i]);
					i += offset;
					break;
				}
			}else if(len > (i+3) && srcp[i+1] == L'/' &&
					srcp[i+2] == L'a' &&
					srcp[i+3] == L'>'){
				i += 3;
				break;
			}
		/* fall through */
		default:
DEF_LABEL:
			if(ch <= 128 || (ch >= 0xff66 && ch <= 0xff9d))
				offset = 1;
			else
				offset = 2;

			if(consume_colmns + offset > colmns){
				cptr = buf + start;
				buf[buf_idx] = L'\0';
				linkp = nt_link_add_data(
						resp->msg_line_linkp, cptr);
				if(!linkp)
					goto END_FOR;
				if(resp->msg_line_linkp == NULL)
					resp->msg_line_linkp = linkp;
					
				consume_colmns = 0;
				lines++;
				buf_idx++;
				start = buf_idx;
				i--;
			}else{
				consume_colmns += offset;
				buf[buf_idx] = ch;
				buf_idx++;
			}
			break;
		}/* end switch */
	} /* end for */
END_FOR:
	if(consume_colmns > 0){
		cptr = buf + start;
		buf[buf_idx] = L'\0';
		linkp = nt_link_add_data(
				resp->msg_line_linkp, cptr);
		if(linkp){
			if(resp->msg_line_linkp == NULL)
				resp->msg_line_linkp = linkp;
			lines++;
		}
	}
	resp->msg_line_num = lines;
	return lines;
}


BOOL parse_thread(nt_thread_tp threadp, const wchar_t *linep)
{
	wchar_t buf[1024*3+1];
	nt_res_tp resp;
	wchar_t *cptr1, *cptr2, *cptr3, *cptr4;
	wchar_t *name, *mail, *misc, *msg;
	if(!linep)
		return FALSE;
	int len = wcslen(linep);
	if(len <= 0)
		return FALSE;
	if(len >= sizeof(buf))
		return FALSE;

	wcscpy(buf, linep);
	cptr1 = wcsstr(buf, L"<>");
	if(!cptr1)
		return FALSE;

	cptr2 = wcsstr(cptr1+2, L"<>");
	if(!cptr2)
		return FALSE;

	cptr3 = wcsstr(cptr2+2, L"<>");
	if(!cptr3)
		return FALSE;

	cptr4 = wcsstr(cptr3+2, L"<>");
	if(cptr4)
		*cptr4 = L'\0';

	name = buf;
	mail = cptr1 + 2;
	misc = cptr2 + 2;
	msg = cptr3 + 2;
	*cptr1 = *cptr2 = *cptr3 = L'\0';

	name = buf;

	resp = nt_res_alloc(threadp, name, mail, misc, msg);
	if(!resp)
		return FALSE;
	threadp->num_res++;
	resp->seq_no = threadp->num_res;

	return TRUE;
}


BOOL parse_board(nt_board_tp boardp, const wchar_t *linep)
{
	wchar_t buf[256+1];
	nt_thread_tp threadp;
	wchar_t *cptr1, *cptr2, *cptr3;
	int len, num_res;

	len = wcslen(linep);
	if(sizeof(buf)-1 < len)
		return FALSE;
	if(len >= sizeof(buf))
		return FALSE;

	wcscpy(buf, linep);
	cptr1 = wcsstr(buf, L"<>");
	if(!cptr1)
		return FALSE;
	*cptr1 = L'\0';
	cptr1 += 2;
	cptr2 = wcsrchr(cptr1, L'(');
	if(cptr2)
		cptr3 = wcsrchr(cptr2, L')');
	if(cptr2 && cptr3){
		*cptr2 = L'\0';
		*cptr3 = L'\0';
		num_res = wcstol(cptr2+1, NULL, 0);
	}else{
		num_res = 0;
	}
	threadp = nt_thread_alloc(boardp, cptr1, buf, num_res);
	if(!threadp)
		return FALSE;
	/* threadp = malloc(sizeof(nt_thread_t));
	if(!threadp)
		return FALSE;

	threadp->name = nt_w_trim(cptr1);
	threadp->address = nt_w_trim(buf);
	threadp->num_res = num_res; */
	return TRUE;
}


BOOL parse_board_menu(nt_2ch_model_tp modelp,
		const wchar_t *linep)
{

	wchar_t name[1024*2];
	int len;
	wchar_t *cptr1, *cptr2, *cptr3, *cptr4;
	wchar_t *addressp;
	nt_category_tp categoryp;
	int offset;

	assert(modelp);
	assert(linep);

	cptr1 = wcsstr(linep, L"<BR><B>");
	if(cptr1){
		cptr2 = wcsstr(cptr1, L"</B><BR>");
		if(!cptr2)
			return FALSE;
		cptr1 += 7;
		len = cptr2 - cptr1;
		wcsncpy(name, cptr1, len);
		name[len] = L'\0';
		if(!nt_category_alloc(modelp, name))
			return FALSE;
		return TRUE;
	}
	cptr1 = wcsstr(linep, L"<A HREF=");
	if(cptr1 == linep){
		cptr2 = wcsstr(cptr1, L"/>");
		if(!cptr2){
			cptr2 = wcsstr(cptr1,L".machi.to");
			if(!cptr2)
				return FALSE;
			cptr2 = wcsstr(cptr1, L" TARGET=_blank>");
			if(!cptr2)
				return FALSE;
			offset = 15;
		}else{
			offset = 2;
		}
		cptr3 = wcsstr(cptr2, L"</A>");
		if(!cptr3)
			return FALSE;
		cptr1 += 8;
		len = cptr2 - cptr1;
		wcsncpy(name, cptr1, len);
		name[len] = L'\0';
		addressp = name;
		cptr2 += offset;
		cptr4 = &(name[len+1]);
		len = cptr3 - cptr2;
		wcsncpy(cptr4, cptr2, len);
		cptr4[len] = L'\0';
		categoryp = get_last_category(modelp);
		if(!categoryp)
			return FALSE;
		if(!nt_board_alloc(categoryp, cptr4, addressp))
			return FALSE;
		return TRUE;
	}
	return FALSE;
}

static nt_category_tp get_last_category(nt_2ch_model_tp modelp)
{
	nt_category_tp categoryp;

	nt_link_tp linkp = modelp->categorylistp;
	if(!linkp)
		return NULL;
	linkp = linkp->prev;
	categoryp = (nt_category_tp)linkp->data;
	return categoryp;
}
