/* Copyright 2013 Akira Ohta (akohta001@gmail.com)
    This file is part of ntch.

    The ntch is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    The ntch is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ntch.  If not, see <http://www.gnu.org/licenses/>.
    
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <wchar.h>
#include <limits.h>

#define MODEL_2CH_PRIVATE_DATA

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

static nt_category_handle get_last_category(nt_2ch_model_tp modelp);


BOOL parse_thread(nt_thread_handle h_thread, const wchar_t *linep)
{
	wchar_t buf[1024*3+1];
	nt_res_handle h_res;
	nt_res_tp resp;
	wchar_t *cptr1, *cptr2, *cptr3, *cptr4;
	wchar_t *name, *mail, *misc, *msg;
	
	assert(h_thread);
	assert(h_thread->chk_sum == NT_2CH_THREAD_CHK_SUM);
	
	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';

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

	h_res = nt_res_alloc(h_thread, name, mail, misc, msg);
	if(!h_res)
		return FALSE;
	
	nt_res_release_ref(h_res);
	
	resp = (nt_res_tp)h_res;
	resp->seq_no = ((nt_thread_tp)h_thread)->num_res;
	return TRUE;
}

BOOL parse_thread_machi_bbs(nt_thread_handle h_thread, const wchar_t *linep)
{
	wchar_t buf[1024*3+1];
	nt_res_handle h_res;
	nt_res_tp resp;
	wchar_t *cptr1, *cptr2, *cptr3, *cptr4;
	wchar_t *name, *mail, *misc, *msg;
	long num;
	
	assert(h_thread);
	assert(h_thread->chk_sum == NT_2CH_THREAD_CHK_SUM);
	
	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)
		return FALSE;

	*cptr1 = *cptr2 = *cptr3 = *cptr4 = L'\0';
	num = wcstol(buf, NULL, 10);
	if(num == 0 || num == LONG_MIN || num == LONG_MAX)
		return FALSE;
	name = cptr1 + 2;
	mail = cptr2 + 2;
	misc = cptr3 + 2;
	msg = cptr4 + 2;
	cptr4 = wcsstr(msg, L"<>");
	if(cptr4)
		*cptr4 = L'\0';

	h_res = nt_res_alloc(h_thread, name, mail, misc, msg);
	if(!h_res)
		return FALSE;
	
	nt_res_release_ref(h_res);
	
	resp = (nt_res_tp)h_res;
	resp->seq_no = (int)num;
	return TRUE;
}


wchar_t* parse_thread_title(const wchar_t *linep)
{
	wchar_t buf[1024*3+1];
	wchar_t *cptr;
	if(!linep)
		return FALSE;
	int len = wcslen(linep);
	if(len <= 0)
		return FALSE;
	if(len >= sizeof(buf))
		return FALSE;

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

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

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

	cptr = wcsstr(cptr+2, L"<>");
	if(!cptr)
		return NULL;
	return nt_w_str_clone(cptr + 2);
}


BOOL parse_board(nt_board_handle h_board, const wchar_t *linep)
{
	wchar_t buf[256+1];
	nt_thread_handle h_thread;
	wchar_t *cptr1, *cptr2, *cptr3;
	int len, num_res;

	assert(h_board);
	assert(h_board->chk_sum == NT_2CH_BOARD_CHK_SUM);
	
	len = wcslen(linep);
	if(sizeof(buf)-1 < len*sizeof(wchar_t))
		return FALSE;
	if(len*sizeof(wchar_t) >= sizeof(buf))
		return FALSE;

	wcscpy(buf, linep);
	cptr1 = wcsstr(buf, L"<>");
	if(!cptr1){
		cptr1 = wcsstr(buf, L",");
		if(!cptr1)
			return FALSE;
		*cptr1 = L'\0';
		cptr1++;
	}else{
		*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;
	}
	h_thread = nt_thread_alloc(
			h_board, cptr1, buf, num_res);
	if(!h_thread)
		return FALSE;
	
	nt_thread_release_ref(h_thread);
	
	return TRUE;
}


BOOL parse_board_menu(nt_2ch_model_handle h_model,
		const wchar_t *linep)
{
	nt_category_handle h_category;
	nt_board_handle h_board;
	wchar_t name[1024*2];
	int len;
	wchar_t *cptr1, *cptr2, *cptr3, *cptr4;
	wchar_t *addressp;
	int offset;

	assert(h_model);
	assert(h_model->chk_sum == NT_2CH_MODEL_CHK_SUM);
	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';
		h_category = nt_category_alloc(h_model, name);
		if(!h_category)
			return FALSE;
		nt_category_release_ref(h_category);
		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';
		h_category = get_last_category((nt_2ch_model_tp)h_model);
		if(!h_category)
			return FALSE;
		nt_category_release_ref(h_category);
		h_board = nt_board_alloc(h_category, cptr4, addressp);
		if(!h_board)
			return FALSE;
		nt_board_release_ref(h_board);
		return TRUE;
	}
	return FALSE;
}

static nt_category_handle 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;
	nt_category_add_ref(&categoryp->handle);
	return &categoryp->handle;
}
