/*
 * This file is part of the Simutrans project under the Artistic License.
 * (see LICENSE.txt)
 */

#include "gui_theme.h"
#include "vehiclelist_frame.h"

#include "../builder/goods_manager.h"
#include "../builder/vehikelbauer.h"

#include "../simskin.h"
#include "../simintr.h"
#include "../world/simworld.h"

#include "../display/simgraph.h"

#include "../dataobj/translator.h"

#include "../descriptor/goods_desc.h"
#include "../descriptor/intro_dates.h"
#include "../descriptor/skin_desc.h"
#include "../descriptor/vehicle_desc.h"

#include "../utils/simstring.h"
#include "../utils/unicode.h"


int vehiclelist_stats_t::sort_mode = vehicle_builder_t::sb_intro_date;
bool vehiclelist_stats_t::reverse = false;

// for having uniform spaced columns
int vehiclelist_stats_t::img_width = 100;


vehiclelist_stats_t::vehiclelist_stats_t(const vehicle_desc_t *v) :
	details(&details_buf,0)
{
	veh = v;

	// width of image
	const image_id image = veh->get_image_id( ribi_t::dir_south, veh->get_freight_type() );
	const scr_rect r = gfx->get_base_image_offset(image);

	if( r.w > img_width ) {
		img_width = r.w + D_H_SPACE;
	}
	height = r.h;

	// name is the widest entry in column 1
	name_width = gfx->calc_text_width( translator::translate( veh->get_name(), world()->get_settings().get_name_language_id() ) );
	if( veh->get_power() > 0 ) {
		char str[ 256 ];
		sprintf( str, " (%s)", translator::translate( vehicle_builder_t::engine_type_names[ veh->get_engine_type() + 1 ] ) );
		name_width += gfx->calc_text_width( str );
	}
	scr_coord_val name_h = LINESPACE;

	// column 1
	part1.clear();
	if( sint64 fix_cost = world()->scale_with_month_length( veh->get_maintenance() ) ) {
		char tmp[ 128 ];
		money_to_string( tmp, veh->get_price() / 100.0, false );
		part1.printf( translator::translate( "Cost: %8s (%.2f$/km %.2f$/m)\n" ), tmp, veh->get_running_cost() / 100.0, fix_cost / 100.0 );
	}
	else {
		char tmp[ 128 ];
		money_to_string( tmp, veh->get_price() / 100.0, false );
		part1.printf( translator::translate( "Cost: %8s (%.2f$/km)\n" ), tmp, veh->get_running_cost() / 100.0 );
	}
	if( veh->get_capacity() > 0 ) { // must translate as "Capacity: %3d%s %s\n"
		part1.printf( translator::translate( "Capacity: %d%s %s\n" ),
			veh->get_capacity(),
			translator::translate( veh->get_freight_type()->get_mass() ),
			veh->get_freight_type()->get_catg() == 0 ? translator::translate( veh->get_freight_type()->get_name() ) : translator::translate( veh->get_freight_type()->get_catg_name() )
		);
		part1.printf("%s%s\n", translator::translate("Loading time:"), difftick_to_string(veh->get_loading_time(), false));
	}
	part1.printf( "%s %3d km/h\n", translator::translate( "Max. speed:" ), veh->get_topspeed() );
	if( veh->get_power() > 0 ) {
		if( veh->get_gear() != 64 ) {
			part1.printf( "%s %4d kW (x%0.2f)\n", translator::translate( "Power:" ), veh->get_power(), veh->get_gear() / 64.0 );
		}
		else {
			part1.printf( translator::translate( "Power: %4d kW\n" ), veh->get_power() );
		}
	}

	const scr_size text1_size = gfx->calc_multiline_text_size(part1);
	col1_width = text1_size.w + D_H_SPACE;

	// column 2
	part2.clear();
	part2.printf( "%s %4.1ft\n", translator::translate( "Weight:" ), veh->get_weight() / 1000.0 );
	part2.printf( "%s: %s - ", translator::translate( "Available" ), translator::get_short_date( veh->get_intro_year_month() / 12, veh->get_intro_year_month() % 12 ) );
	if( veh->get_retire_year_month() != DEFAULT_RETIRE_YEAR * 12 ) {
		part2.printf( "%s", translator::get_short_date( veh->get_retire_year_month() / 12, veh->get_retire_year_month() % 12 ) );
	}
	if( char const* const copyright = veh->get_copyright() ) {
		part2.append( "\n" );
		part2.printf( translator::translate( "Constructed by %s" ), copyright );
	}

	const scr_size text2_size = gfx->calc_multiline_text_size(part2);
	col2_width = text2_size.w;

	// we need to find out manually, if we have extra text to show
	if (strlen(veh->get_name()) < 238) {
		char ei[256];
		sprintf(ei, "obj_%s_details", veh->get_name());
		const char* translated_ei = translator::translate(ei);
		if (ei != translated_ei) {
			details_buf.append(translated_ei);
			details.set_width(col1_width + col2_width);
			name_h += details.get_size().h;
		}
	}

	height = max( height, max( text1_size.h, text2_size.h ) + name_h ) + D_V_SPACE;
}


void vehiclelist_stats_t::draw( scr_coord offset )
{
	uint32 month = world()->get_current_month();
	offset += pos;

	offset.x += D_MARGIN_LEFT;
	offset.y += D_V_SPACE/2;

	const image_id image = veh->get_image_id( ribi_t::dir_south, veh->get_freight_type() );
	const scr_rect r = gfx->get_base_image_offset(image);
	gfx->draw_base_img(image, offset.x - r.x, offset.y - r.y, world()->get_active_player_nr(), false, true CLIP_NUM_DEFAULT);

	// first name
	offset.x += img_width;
	int dx = gfx->draw_text(
		offset.x, offset.y,
		translator::translate( veh->get_name(), world()->get_settings().get_name_language_id() ),
		ALIGN_LEFT|DT_CLIP,
		veh->is_future(month) ? SYSCOL_TEXT_HIGHLIGHT : (veh->is_available(month) ? SYSCOL_TEXT : gui_theme_t::gui_color_obsolete),
		false
	);

	if( veh->get_power() > 0 ) {
		char str[ 256 ];
		sprintf( str, " (%s)", translator::translate( vehicle_builder_t::engine_type_names[ veh->get_engine_type() + 1 ] ) );
		gfx->draw_text( offset.x+dx, offset.y, str, ALIGN_LEFT|DT_CLIP, SYSCOL_TEXT, false );
	}

	// maybe there are detailed text to the vehicle?
	int yyy = offset.y + LINESPACE;
	if (details_buf.len()>0) {
		details.draw(scr_coord(offset.x, yyy));
		yyy += details.get_size().h;
	}

	// now the rest in two columns
	gfx->draw_multiline_text( offset.x, yyy, part1, SYSCOL_TEXT );

	gfx->draw_multiline_text( offset.x + col1_width, yyy, part2, SYSCOL_TEXT );
}


const char *vehiclelist_stats_t::get_text() const
{
	return translator::translate( veh->get_name() );
}


bool vehiclelist_stats_t::compare(const gui_component_t *aa, const gui_component_t *bb)
{
	bool result = vehicle_builder_t::compare_vehicles( dynamic_cast<const vehiclelist_stats_t*>(aa)->veh, dynamic_cast<const vehiclelist_stats_t*>(bb)->veh, (vehicle_builder_t::sort_mode_t)vehiclelist_stats_t::sort_mode );
	return vehiclelist_stats_t::reverse ? !result : result;
}


vehiclelist_frame_t::vehiclelist_frame_t() :
	gui_frame_t( translator::translate("vh_title") ),
	scrolly(gui_scrolled_list_t::windowskin, vehiclelist_stats_t::compare)
{
	name_filter[0] = 0;
	scrolly.set_cmp( vehiclelist_stats_t::compare );
	scrolly.set_checkered(true);

	set_table_layout(3,0);

	new_component<gui_label_t>("Filter:");
	name_filter_input.set_text(name_filter, lengthof(name_filter));
	name_filter_input.set_notify_all_changes_delay(0);
	add_component(&name_filter_input,2);
	name_filter_input.add_listener(this);

	// next rows
	bt_obsolete.init(button_t::square_state, "Show obsolete");
	bt_obsolete.add_listener(this);
	add_component(&bt_obsolete);

	bt_future.init(button_t::square_state, "Show future");
	bt_future.add_listener(this);
	bt_future.pressed = true;
	add_component(&bt_future);

	ware_filter.clear_elements();
	ware_filter.new_component<gui_scrolled_list_t::const_text_scrollitem_t>(translator::translate("All"), SYSCOL_TEXT);
	idx_to_ware.append(NULL);
	for (int i = 0; i < goods_manager_t::get_count(); i++) {
		const goods_desc_t* ware = goods_manager_t::get_info(i);
		if (ware == goods_manager_t::none) {
			continue;
		}
		if (ware->get_catg() == 0) {
			ware_filter.new_component<gui_scrolled_list_t::const_text_scrollitem_t>(translator::translate(ware->get_name()), SYSCOL_TEXT);
			idx_to_ware.append(ware);
		}
	}
	// now add other good categories
	for (int i = 1; i < goods_manager_t::get_max_catg_index(); i++) {
		const goods_desc_t* ware = goods_manager_t::get_info_catg(i);
		if (ware->get_catg() != 0) {
			ware_filter.new_component<gui_scrolled_list_t::const_text_scrollitem_t>(translator::translate(ware->get_catg_name()), SYSCOL_TEXT);
			idx_to_ware.append(ware);
		}
	}
	ware_filter.set_selection(0);
	ware_filter.add_listener(this);
	add_component(&ware_filter);

	// second row
	new_component<gui_label_t>( "hl_txt_sort" );

	sort_by.clear_elements();
	for( int i = 0; i < vehicle_builder_t::sb_length; i++ ) {
		sort_by.new_component<gui_scrolled_list_t::const_text_scrollitem_t>(translator::translate(vehicle_builder_t::vehicle_sort_by[i]), SYSCOL_TEXT);
	}
	sort_by.set_selection( vehiclelist_stats_t::sort_mode );
	sort_by.add_listener( this );
	add_component( &sort_by );

	sorteddir.init( button_t::sortarrow_state, NULL );
	sorteddir.pressed = vehiclelist_stats_t::reverse;
	sorteddir.add_listener( this );
	add_component( &sorteddir );

	tabs.init_tabs(&scrolly);
	tabs.add_listener(this);
	add_component(&tabs,3);

	fill_list();

	set_resizemode(diagonal_resize);
	scrolly.set_maximize(true);
	reset_min_windowsize();
}


/**
 * This method is called if an action is triggered
 */
bool vehiclelist_frame_t::action_triggered( gui_action_creator_t *comp,value_t v)
{
	if(comp == &sort_by) {
		vehiclelist_stats_t::sort_mode = max(0,v.i);
		fill_list();
	}
	else if(comp == &ware_filter) {
		fill_list();
	}
	else if(comp == &sorteddir) {
		vehiclelist_stats_t::reverse = !vehiclelist_stats_t::reverse;
		sorteddir.set_text( vehiclelist_stats_t::reverse ? "hl_btn_sort_desc" : "hl_btn_sort_asc");
		scrolly.sort(0);
		sorteddir.pressed = vehiclelist_stats_t::reverse;
	}
	else if(comp == &bt_obsolete) {
		bt_obsolete.pressed ^= 1;
		fill_list();
	}
	else if(comp == &bt_future) {
		bt_future.pressed ^= 1;
		fill_list();
	}
	else if(comp == &tabs) {
		fill_list();
	}
	else if(comp == &name_filter_input) {
		fill_list();
	}
	return true;
}


void vehiclelist_frame_t::fill_list()
{
	scrolly.clear_elements();
	vehiclelist_stats_t::img_width = 32; // reset col1 width
	uint32 month = world()->get_current_month();
	const goods_desc_t *ware = idx_to_ware[ max( 0, ware_filter.get_selection() ) ];
	// adding all vehiles, i.e. iterate over all available waytypes
	for (uint32 i = 1; i < tabs.get_count(); i++) {
		if(  tabs.get_active_tab_index()>0  &&  (sint32)i!=tabs.get_active_tab_index()  ) {
			// wrong waytype
			continue;
		}
		for(vehicle_desc_t const* const veh : vehicle_builder_t::get_info(tabs.get_tab_waytype(i)) ) {
			if(  bt_obsolete.pressed  ||  !veh->is_retired( month )  ) {
				if(  bt_future.pressed  ||  !veh->is_future( month )  ) {
					if(  name_filter[0]==0  ||  utf8caseutf8(translator::translate(veh->get_name()),name_filter)  ) {
						if(  ware  ) {
							const goods_desc_t *vware = veh->get_freight_type();
							if(  (ware->get_catg_index() > 0  &&  vware->get_catg_index() == ware->get_catg_index())  ||  vware->get_index() == ware->get_index()  ) {
								scrolly.new_component<vehiclelist_stats_t>( veh );
							}
						}
						else {
							scrolly.new_component<vehiclelist_stats_t>( veh );
						}
					}
				}
			}
		}
	}
	if( vehiclelist_stats_t::sort_mode != 0 ) {
		scrolly.sort(0);
	}
	else {
		scrolly.set_size( scrolly.get_size() );
	}
}

void vehiclelist_frame_t::rdwr(loadsave_t* file)
{
	scr_size size = get_windowsize();

	size.rdwr(file);
	tabs.rdwr(file);
	scrolly.rdwr(file);
	ware_filter.rdwr(file);
	sort_by.rdwr(file);
	file->rdwr_bool(sorteddir.pressed);
	file->rdwr_bool(bt_obsolete.pressed);
	file->rdwr_bool(bt_future.pressed);
	if (file->is_version_atleast(123, 2)) {
		file->rdwr_str(name_filter, lengthof(name_filter));
	}
	if (file->is_loading()) {
		vehiclelist_stats_t::reverse = sorteddir.pressed;
		vehiclelist_stats_t::sort_mode = sort_by.get_selection();
		fill_list();
		set_windowsize(size);
	}
}
