/* 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <wchar.h>
#include <ncursesw/ncurses.h>

#include "env.h"
#include "utils/nt_std_t.h"
#include "_2ch/model_2ch.h"
#include "_2ch/search_2ch.h"
#include "ui/disp.h"
#include "ui/disp_string.h"


typedef struct tag_thread_search_ctx_t *thread_search_ctx_tp;
typedef struct tag_thread_search_ctx_t{
	int prev_state;
	int cur_cursor;
	int scroll_y;
	int item_count;
	nt_link_tp thread_list;
}thread_search_ctx_t;

static thread_search_ctx_tp init_context();
static void free_searched_thread(void *ptr)
{
	nt_searched_thread_handle h_searched_thread;
	h_searched_thread = (nt_searched_thread_handle)ptr;
	nt_searched_thread_release_ref(h_searched_thread);
}

int disp_thread_search(nt_window_tp wp, 
		int prev_state,  nt_link_tp thread_list, 
		nt_searched_thread_handle *h_sel_threadp)
{
	thread_search_ctx_tp ctxp;
	nt_searched_thread_handle h_sthread;
	nt_link_tp linkp;
	attr_t attr;
	int row, num, ch_num;
	wchar_t wc[128];
	const wchar_t *board_name, *title;
	
	*h_sel_threadp = NULL;

	ctxp = (thread_search_ctx_tp)wp->data;
	if(!ctxp){
		ctxp = init_context();
		if(!ctxp)
			return DISP_STATE_ERROR;
			
		wp->data = ctxp;
	}
	if(prev_state != DISP_STATE_SEARCH_THREAD)
		ctxp->prev_state = prev_state;
	if(thread_list){
		if(ctxp->thread_list){
			nt_all_link_free(
				ctxp->thread_list, free_searched_thread);
		}
		ctxp->thread_list = thread_list;
		ctxp->item_count = nt_link_num(ctxp->thread_list);
	}
	switch(wp->key){
	case NT_KEY_CLOSE:
	case KEY_LEFT:
		return ctxp->prev_state;
	case NT_KEY_SELECT:
	case KEY_RIGHT:
		if(!ctxp->thread_list)
			break;
		num = 0;
		linkp = ctxp->thread_list;
		do{
			if(ctxp->cur_cursor == num){
				*h_sel_threadp = 
					(nt_searched_thread_handle)linkp->data;
				nt_searched_thread_add_ref(*h_sel_threadp);
				return DISP_STATE_SEARCH_THREAD;
			}
			num++;
			linkp = linkp->next;
		}while(linkp != ctxp->thread_list);
		break;
	case NT_KEY_UP:
	case KEY_UP:
		if(ctxp->cur_cursor > 0)
			ctxp->cur_cursor--;
		if(ctxp->scroll_y > (ctxp->cur_cursor*2))
			ctxp->scroll_y = (ctxp->cur_cursor*2);
		break;
	case NT_KEY_DOWN:
	case KEY_DOWN:
		if(ctxp->cur_cursor < (ctxp->item_count-1))
			ctxp->cur_cursor++;
		if((ctxp->scroll_y + wp->lines) <= (ctxp->cur_cursor*2)+1){
			ctxp->scroll_y = (ctxp->cur_cursor+1) * 2 - wp->lines;
		}
		break;
	case NT_KEY_PAGEUP:
	case KEY_PPAGE:
		ctxp->cur_cursor *= 2;
		ctxp->cur_cursor -= ctxp->scroll_y;
		ctxp->scroll_y -= wp->lines;
		if(ctxp->scroll_y < 0)
			ctxp->scroll_y = 0;
		ctxp->cur_cursor += ctxp->scroll_y;
		ctxp->cur_cursor /= 2;
		break;
	case NT_KEY_PAGEDOWN:
	case KEY_NPAGE:
		ctxp->cur_cursor *= 2;
		ctxp->cur_cursor -= ctxp->scroll_y;
		ctxp->scroll_y += wp->lines;
		if(ctxp->scroll_y + wp->lines > (ctxp->item_count*2)){
			ctxp->scroll_y =
				(ctxp->item_count*2) - wp->lines;
		}
		ctxp->cur_cursor += ctxp->scroll_y;
		ctxp->cur_cursor /= 2;
		break;
	case NT_KEY_BOTTOM:
	case KEY_END:
		ctxp->cur_cursor *= 2;
		ctxp->cur_cursor -= ctxp->scroll_y;
		ctxp->scroll_y =
				(ctxp->item_count*2) - wp->lines;
		ctxp->cur_cursor += ctxp->scroll_y;
		ctxp->cur_cursor /= 2;
		break;
	default:
		//wmove(wp->wp, 1, 1); 
		//nt_add_wch(wp->wp, (wchar_t)wp->key, 0);
		break;
	}
	
	if(ctxp->thread_list){
		row = 0;
		num = 1;
		linkp = ctxp->thread_list;
		do{
			if(row >= ctxp->scroll_y + wp->lines)
				break;
			if(ctxp->cur_cursor+1 == num)
				attr = WA_BOLD;
			else
				attr = 0;
			
			h_sthread = (nt_searched_thread_handle)linkp->data;
			
			board_name = nt_searched_thread_get_board_name(h_sthread);
			title = nt_searched_thread_get_title(h_sthread);
			if(-1 == swprintf(wc, sizeof(wc)/sizeof(wchar_t)-1, 
					L"%4d. %ls [%ls]", num, title, board_name)){
				break;
			}
			if(row >= ctxp->scroll_y){
				wmove(wp->wp, row-ctxp->scroll_y, 0); 
				nt_add_wnstr(wp->wp, wc, attr, wp->cols);
			}
			row++;
			if(row >= ctxp->scroll_y + wp->lines)
				break;
			if(row >= ctxp->scroll_y){
				wmove(wp->wp, row-ctxp->scroll_y, 0); 
				nt_add_wnch(wp->wp, L' ', attr | WA_UNDERLINE, wp->cols);
				ch_num = nt_get_wc_count_within_colmns(wc, wp->cols);
				if( wcslen(wc) - ch_num > 0){
					wmove(wp->wp, row-ctxp->scroll_y, 6);
					nt_add_wnstr(wp->wp, wc + ch_num, attr | WA_UNDERLINE, wp->cols - 5);
				}
			}
			row++;
			num++;
			linkp = linkp->next;
		}while(linkp != ctxp->thread_list);
	}
	return DISP_STATE_SEARCH_THREAD;
}

static thread_search_ctx_tp init_context()
{
	thread_search_ctx_tp ctxp;
	
	ctxp = malloc(sizeof(thread_search_ctx_t));
	if(!ctxp)
		return NULL;
	ctxp->prev_state = DISP_STATE_SEARCH_THREAD;
	ctxp->thread_list = NULL;
	ctxp->cur_cursor = 0;
	ctxp->scroll_y = 0;
	ctxp->item_count = 0;
	return ctxp;
}

void free_search_thread_ctx(void *ptr)
{
	thread_search_ctx_tp ctxp;
	
	assert(ptr);
	
	ctxp = (thread_search_ctx_tp)ptr;
	if(ctxp->thread_list){
		nt_all_link_free(
			ctxp->thread_list, free_searched_thread);
	}
	
	free(ctxp);
}
