#ifndef __tagpick_h__
#include "tagpick.h"
#endif

#include <XDialog.h>
#include <XPopup.h>
#include <XList.h>
#include <XDynArray.h>
#include <XTextControls.h>
#include <XButtons.h>
#include <XMessages.h>
#include <XStringUtil.h>
#include "RevengeApp.h"
#include <assert.h>
#include <ctype.h>
#include "RevengeResources.h"


static int single_file_by_default = true;


class pick_info {
public:
	tag_file *limit_file;
	bool use_single_file;
	
	tag chosen_id;
	tag type;
	
	XGPDynArray< tag_entry > entries;
	
	XGListControl *l_tags;
	XGStaticText *t_id;
	XGStaticText *t_size;
	XGStaticText *t_file;
};


extern "C" {

static int tag_sorter( const void *a, const void *b )
{
	tag_entry *ea, *eb;
	ea = *(tag_entry **)a;
	eb = *(tag_entry **)b;
	
	const char *ca = get_entry_name(ea);
	const char *cb = get_entry_name(eb);
	
	while (*ca && tolower(*ca) == tolower(*cb)) {
		++ca;
		++cb;
	}
	return tolower(*ca) - tolower(*cb);
}
}


void update_info_fields( XGDialog *d, pick_info *info )
{
	int sel = info->l_tags->GetValue();
	if (sel < 0 || sel >= info->entries.Length()) {
		d->SetEnabled( 100, false );
		info->t_id->SetTitle("");
		info->t_size->SetTitle("");
		info->t_file->SetTitle("");
		info->chosen_id = -1;
	} else {
		d->SetEnabled( 100, true );
		info->chosen_id = get_entry_id(info->entries[sel]);
		info->t_id->SetTitle( tagstr(info->chosen_id) );
		char buf[256];
		sprintf( buf, "%d", get_entry_size( info->entries[sel] ) );
		info->t_size->SetTitle( buf );
		TRevengeApp::GetTagFilePath( buf, get_entry_file(info->entries[sel]) );
		info->t_file->SetTitle( buf );
	}
}


void add_file_tags( pick_info *info, tag_file *f )
{
	tag_group *g = get_group_in_file( f, info->type, false );
	if (!g) return;
	tag_entry *e = 0;
	int pos = info->entries.Length();
	while ((e = get_next_entry_in_group(g,e)) != 0) {
		info->entries.Insert( pos, e );
		++pos;
	}
}

static void rebuild_tag_list( XGDialog *d, pick_info *info )
{
	info->entries.DeleteAll();
	
	if (info->limit_file && info->use_single_file)
	{
		add_file_tags( info, info->limit_file );
	}
	else
	{
		tag_file *f = 0;
		while( (f = get_next_tag_file(f)) != 0 )
		{
			tag_group *g = get_group_in_file( f, info->type, false );
			if( !g )
				continue;
				
			if( !get_next_entry_in_group( g, 0 ) )
				continue;
				
			add_file_tags( info, f );
		}
	}
	
	tag_entry **list = &(info->entries[0]);
	qsort( list, info->entries.Length(), sizeof(tag_entry *), tag_sorter );
	
	info->l_tags->DeleteAll();
	info->l_tags->SetUpdate( false );
	
	int j = 0;
	for (int i = 0; i < info->entries.Length(); ++i) {
		char name[256];
		sprintf( name, "%s (%s)", get_entry_name(info->entries[i]), tagstr(get_entry_id(info->entries[i])) );
		info->l_tags->Insert( i, name );
		if (get_entry_id(info->entries[i]) == info->chosen_id) j = i;
	}
	
	info->l_tags->SetUpdate( true );
	if (info->l_tags->Length()) {
		info->l_tags->SetValue(j);
	}
	update_info_fields(d,info);
}


static long PickProc( XGDialog *dlog, void *data, long msg, long arg, void *parg )
{
	pick_info *info = (pick_info *)data;
	
//	XGCommandButton* pShowAll = dynamic_cast<XGCommandButton *>(dlog->FindViewByID( 6 ));
//	XGCommandButton *pShowCurrent = dynamic_cast<XGCommandButton *>(dlog->FindViewByID( 7 ));
	
	switch (msg) {
		case KXGDialogMessage:
			switch (arg) {
				case KXGDMInitDialog: {
						char namebuf[256];
						
						dlog->SetValue( info->use_single_file ? 6 : 7, 1 );
						if (!info->limit_file)
						{
							dlog->SetEnabled( 6, false );
							dlog->SetEnabled( 7, false );
						}
						
						sprintf( namebuf, "Pick %s (%s)", get_singular_name_for_type(info->type), tagstr(info->type) );
						dlog->SetTitle( namebuf );
						info->l_tags = dynamic_cast<XGListControl *>(dlog->FindViewByID(2));
						info->t_id = dynamic_cast<XGStaticText *>(dlog->FindViewByID(3));
						info->t_size = dynamic_cast<XGStaticText *>(dlog->FindViewByID(4));
						info->t_file = dynamic_cast<XGStaticText *>(dlog->FindViewByID(5));
						
						rebuild_tag_list( dlog, info );
						return 0;
					} break;
				default:
					break;
			} break;
		case KXGPopValue:
			switch (arg) {
				case 1:	// file popup
					rebuild_tag_list( dlog, info );
					return 0;
				default:
					break;
			} break;
		case KXGListValue:
			switch (arg) {
				case 2:	// tag list
					update_info_fields( dlog, info );
					return 0;
				default:
					break;
			} break;
		case KXGControlClick:
			switch (arg) {
				case 1:		// file popup
					return 0;
				
				case 6: // use limit file
					if (info->limit_file && !info->use_single_file)
					{
						dlog->SetValue( 6, 1 );
						dlog->SetValue( 7, 0 );
						info->use_single_file = single_file_by_default = true;
						rebuild_tag_list( dlog, info );
					}
					return 0;
					
				case 7: // use limit file
					if (info->use_single_file)
					{
						dlog->SetValue( 6, 0 );
						dlog->SetValue( 7, 1 );
						info->use_single_file = single_file_by_default = false;
						rebuild_tag_list( dlog, info );
					}
					return 0;
					
				case 100:	// ok
					dlog->EndDialog(1);
					return 0;
				case 101:	// cancel
					dlog->EndDialog(0);
					return 0;
				case 102:	// none
					info->chosen_id = -1;
					dlog->EndDialog(1);
					return 0;
			} break;
		default:
			break;
	}
	
	return -1;
}


tag pick_tag_of_type( tag type, tag default_id, tag_file *limit_file )
{
	pick_info info;
	if (limit_file)
	{
		tag_group *g = get_group_in_file( limit_file, type, false );
		if (!g || !get_next_entry_in_group( g, 0 ))
		{
			limit_file = 0;
		}
	}
	info.limit_file = limit_file;
	info.use_single_file = limit_file ? single_file_by_default && (get_entry_in_file( limit_file, type, default_id ) || get_entry( type, default_id ) == 0) : false;
	info.chosen_id = default_id;
	info.type = type;
	bool ok = XGDialog::ModalDialog( KWindowPickTag, PickProc, &info );
	if (ok) {
		if (!get_entry( type, info.chosen_id )) return -1;
		return info.chosen_id;
	}
	return 0;
}

