/*
 * Copyright (C) Volition, Inc. 1999.  All rights reserved.
 *
 * All source code herein is the property of Volition, Inc. You may not sell 
 * or otherwise commercially exploit the source or things you created based on the 
 * source.
 *
*/

// DumpStats.cpp : implementation file
//

#include "stdafx.h"
#include "FRED.h"
#include "DumpStats.h"
#include "asteroid/asteroid.h"
#include "cfile/cfile.h"
#include "gamesnd/eventmusic.h"
#include "globalincs/linklist.h"
#include "jumpnode/jumpnode.h"
#include "math/bitarray.h"
#include "mission/missiongoals.h"
#include "nebula/neb.h"
#include "object/object.h"
#include "object/waypoint.h"
#include "species_defs/species_defs.h"
#include "starfield/starfield.h"
#include "weapon/weapon.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// DumpStats dialog


DumpStats::DumpStats(CWnd* pParent /*=NULL*/)
	: CDialog(DumpStats::IDD, pParent)
{
	//{{AFX_DATA_INIT(DumpStats)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


void DumpStats::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(DumpStats)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(DumpStats, CDialog)
	//{{AFX_MSG_MAP(DumpStats)
	ON_BN_CLICKED(IDC_DUMP_TO_FILE, OnDumpToFile)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// DumpStats message handlers

BOOL DumpStats::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	CString buffer;
	int i;

	// get author, title, etc
	get_mission_stats(buffer);

	// get nebula, stars, etc.
	get_background_stats(buffer);

	// get number or ships, waypoints, start points, etc.
	get_object_stats(buffer);

	// get objectives / goals
	get_objectives_and_goals(buffer);

	// get ship selection for player wings
	get_ship_weapon_selection(buffer);

	// get messaging info
	get_messaging_info(buffer);

	// get species ship breakdown
	get_species_ship_breakdown(buffer);

	// get default loadouts
	get_default_ship_loadouts(buffer);

	int num_tab_stops = 5;
	int tab_stops[5];
	for (i=0; i<5; i++) {
		tab_stops[i] = (i+1) * 16;
	}

	((CEdit*) GetDlgItem(IDC_STATS_TEXT))->SetTabStops(num_tab_stops, tab_stops);
	((CEdit*) GetDlgItem(IDC_STATS_TEXT))->SetWindowText(buffer);
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

void DumpStats::OnDumpToFile() 
{
	// TODO: Add your control notification handler code here

	// get dump from window
	CString buffer;
	((CEdit*) GetDlgItem(IDC_STATS_TEXT))->GetWindowText(buffer);

	CString dump_filename;
	dump_filename.Format("%s.dmp", Mission_filename);

	CFILE *fp;

	fp = cfopen((char *)LPCTSTR(dump_filename), "wt", CF_TYPE_MISSIONS);
	cfputs((char *)LPCTSTR(buffer), fp);
	cfclose(fp);
}

void DumpStats::get_mission_stats(CString &buffer)
{
	CString temp;

	// Mission info
	buffer += "\t MISSION INFO\r\n";

	temp.Format("Title: %s\r\n", The_mission.name.c_str());
	buffer += temp;

	temp.Format("Filename: %s\r\n", Mission_filename);
	buffer += temp;

	temp.Format("Author: %s\r\n", The_mission.author.c_str());
	buffer += temp;

	temp.Format("Description: %s\r\n", The_mission.mission_desc);
	buffer += temp;

	temp.Format("Notes: %s\r\n", The_mission.notes);
	buffer += temp;

	if (The_mission.game_type & MISSION_TYPE_SINGLE) {
		temp.Format("Mission type: Single Player\r\n");
	} else if (The_mission.game_type & MISSION_TYPE_MULTI_COOP) {
		temp.Format("Mission type: Multi Coop\r\n");
	} else if (The_mission.game_type & MISSION_TYPE_MULTI_TEAMS) {
		temp.Format("Mission type: Multi Team vs. Team\r\n");
	} else if (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT) {
		temp.Format("Mission type: Dogfight\r\n");
	}
	buffer += temp;

	if (The_mission.game_type & MISSION_TYPE_MULTI) {
		temp.Format("\tNum respawns: %d\r\n", The_mission.num_respawns);
		buffer += temp;
	}

	if (Current_soundtrack_num >= 0) {
		temp.Format("\tMusic: %s\r\n", Soundtracks[Current_soundtrack_num].name);
		buffer += temp;
	}

	if (The_mission.flags[Mission::Mission_Flags::Red_alert]) {
		buffer += "\tRed Alert\r\n";
	}

	if (The_mission.flags[Mission::Mission_Flags::Scramble]) {
		buffer += "\tScramble\r\n";
	}

	if (The_mission.flags[Mission::Mission_Flags::No_promotion]) {
		buffer += "\tNo Promotions\r\n";
	}

	if (The_mission.support_ships.max_support_ships == 0) {
		buffer += "\tNo Support ships\r\n";
	}

	temp.Format("Squadron: %s,  Squadron logo: %s\r\n", The_mission.squad_name, The_mission.squad_filename);
	buffer += temp;
}

void DumpStats::get_background_stats(CString &buffer)
{
	CString temp;

	// Background
	buffer += "\r\n\tBACKGROUND INFO\r\n";

	// Num stars
	temp.Format("Num_stars: %d\r\n", Num_stars);
	buffer += temp;

	// Suns
	temp.Format("Num_suns: %d\r\n", stars_get_num_suns());
	buffer += temp;
	
	for (int i=0; i<stars_get_num_suns(); i++) {
		temp.Format("\tSun%d bitmap name: %s\r\n", i, stars_get_sun_name(i));
		buffer += temp;
		//temp.Format("Sun%d glow name: %s\r\n", i, Suns[i].glow_filename);
		//buffer += temp;
	}

	// Starfield bitmaps
	temp.Format("Num_starfield_bitmaps: %d\r\n", stars_get_num_bitmaps());
	buffer += temp;

	for (int i=0; i<stars_get_num_bitmaps(); i++) {
		temp.Format("\tStarfield%d bitmap name: %s\r\n", i, stars_get_bitmap_name(i));
		buffer += temp;
	}

	// Asteroids
	temp.Format("Num Field Debris Chunks: %d\r\n", Asteroid_field.num_initial_asteroids);
	buffer += temp;
	if (Asteroid_field.num_initial_asteroids > 0) {
		// active or passive
		if (Asteroid_field.field_type == FT_ACTIVE) {
			temp.Format("\tActive Field\r\n");
			buffer += temp;

			temp.Format("\tAsteroid Debris\r\n");
			buffer += temp;
		} else {
			// passive
			temp.Format("\tPassive Field\r\n");
			buffer += temp;

			if (Asteroid_field.debris_genre == DG_ASTEROID) {
				temp.Format("\tAsteroid Debris\r\n");
				buffer += temp;
			} else {
				temp.Format("\tShip Debris\r\n");
				buffer += temp;

				temp.Format("\t\tTypes: ");
				for (size_t j = 0; j < Asteroid_field.field_debris_type.size(); j++) {
					temp += CString(Asteroid_info[Asteroid_field.field_debris_type[j]].name) + ", ";
				}

				temp += "\r\n";

				buffer += temp;
			}
		}
	}

	// Nebula mission
	int nebula_mission = (The_mission.flags[Mission::Mission_Flags::Fullneb]);
	temp = "Nebula mission:";
	if (nebula_mission) {
		temp += " Yes\r\n";
	} else {
		temp += " No\r\n";
	}
	buffer += temp;

	if (nebula_mission) {
		// range
		temp.Format("\tNebula awacs range: %.0f\r\n", Neb2_awacs);
		buffer += temp;

		// list of poofs
		for (size_t i=0; i<Poof_info.size(); i++) {
			if (get_bit(Neb2_poof_flags.get(), i)) {
				temp.Format("\tNebula poof: %s\r\n", Poof_info[i].name);
				buffer += temp;
			}
		}

		// nebula texture
		if (strlen(Neb2_texture_name) > 0) { //-V805
			temp.Format("\tNebula texture: %s\r\n", Neb2_texture_name);
			buffer += temp;
		}
	} else {
		// FS! nebula pattern
		if (Nebula_index >= 0) {
			temp.Format("\tOld style FS1 nebula filename: %s\r\n", Nebula_filenames[Nebula_index]);
			buffer += temp;
		}
	}

	// Subspace mission
	temp = "Subspace mission:";
	if (The_mission.flags[Mission::Mission_Flags::Subspace]) {
		temp += " Yes\r\n";
	} else {
		temp += " No\r\n";
	}
	buffer += temp;
}

void DumpStats::get_object_stats(CString &buffer)
{
	object *objp;
	int obj_type_count[MAX_OBJECT_TYPES];
	CString temp;
	int num_small_ships, num_big_ships, num_huge_ships;
	int i;

	memset(obj_type_count,0, sizeof(obj_type_count));
	num_small_ships = num_big_ships = num_huge_ships= 0;

	for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {

		// inc big ship or small ship count
		if ( (objp->type == OBJ_SHIP) || (objp->type == OBJ_START) ) {
			if ( Ship_info[Ships[objp->instance].ship_info_index].is_small_ship() ) {
				num_small_ships++;
			} else if ( Ship_info[Ships[objp->instance].ship_info_index].is_big_or_huge() ) {
				num_big_ships++;
			}
		}

		obj_type_count[objp->type]++;
	}

	// Statistics
	buffer += "\r\n\tMISSION STATISTICS\r\n";

	// OBJ_START is also a OBJ_SHIP
	// not counting num_waves (for wings)
	obj_type_count[OBJ_SHIP] += obj_type_count[OBJ_START];

	for (i=0; i<MAX_OBJECT_TYPES; i++) {
		if (obj_type_count[i] > 0) {
			switch(i) {
			case OBJ_SHIP:
				temp.Format("Ship Count: %d\r\n", obj_type_count[i]);
				buffer += temp;
				break;

			case OBJ_START:
				temp.Format("Start Count: %d\r\n", obj_type_count[i]);
				buffer += temp;
				break;

			case OBJ_WAYPOINT:
				temp.Format("Waypoint Count: %d\r\n", obj_type_count[i]);
				buffer += temp;
				break;

			case OBJ_WING:
				temp.Format("Wing Count: %d\r\n", obj_type_count[i]);
				buffer += temp;
				break;

			case OBJ_JUMP_NODE:
				temp.Format("Jump Node Count: %d\r\n", obj_type_count[i]);
				buffer += temp;
				break;

			default:
				Int3();
				break;
			}
		}
	}

	buffer += "\r\nSHIPS\r\n";
	temp.Format("\tNum small ships: %d\r\n", num_small_ships);
	buffer += temp;

	temp.Format("\tNum big ships: %d\r\n", num_big_ships);
	buffer += temp;

	temp.Format("\tNum huge ships: %d\r\n", num_huge_ships);
	buffer += temp;

	// Waypoints
	size_t total_waypoints = 0;
	buffer += "\r\nWAYPOINTS\r\n";

	for (const auto &ii: Waypoint_lists) {
		temp.Format("\tWaypoint: %s, count: %d\r\n", ii.get_name(), ii.get_waypoints().size());
		buffer += temp;
		total_waypoints += ii.get_waypoints().size();
	}

	if (total_waypoints > 0) {
		temp.Format("\ttotal_waypoints: " SIZE_T_ARG "\r\n", total_waypoints);
		buffer += temp;
	}

	// Jumpnodes
	buffer += "\r\nJUMPNODES\r\n";

	SCP_list<CJumpNode>::iterator jnp;
	for (jnp = Jump_nodes.begin(); jnp != Jump_nodes.end(); ++jnp) {
		temp.Format("\tJumpnode: %s\r\n", jnp->GetName());
		buffer += temp;
	}

	if (!Jump_nodes.empty()) {
		temp.Format("\ttotal_jumpnodes: " SIZE_T_ARG "\r\n", Jump_nodes.size());
		buffer += temp;
	}


	// Wings
	int num_counted_wings = 0;
	buffer += "\r\nWINGS\r\n";
	for (i=0; i<MAX_WINGS; i++) {
		if (Wings[i].wave_count > 0) {
			temp.Format("\tWing Name: %s,  wave_count: %d,  num_waves: %d\r\n", Wings[i].name, Wings[i].wave_count, Wings[i].num_waves);
			buffer += temp;

			num_counted_wings++;
			if (num_counted_wings == Num_wings) {
				break;
			}
		}
	}

	// Escort
	buffer += "\r\nESCORT\r\n";
	for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
		if ( (objp->type == OBJ_SHIP) || (objp->type == OBJ_START) ) {
			if (Ships[objp->instance].flags[Ship::Ship_Flags::Escort]) {
				temp.Format("\tShip name: %s, priority: %d\r\n", Ships[objp->instance].ship_name, Ships[objp->instance].escort_priority);
				buffer += temp;
			}
		}
	}

	// Hotkeys
	buffer += "\r\nHOTKEYS\r\n";

	// ship hotkeys
	for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
		if ( (objp->type == OBJ_SHIP) || (objp->type == OBJ_START) ) {
			if (Ships[objp->instance].hotkey != -1) {
				temp.Format("\tShip name: %s, hotkey: F%d\r\n", Ships[objp->instance].ship_name, (Ships[objp->instance].hotkey + 5));
				buffer += temp;
			}
		}
	}

	// wing hotkeys
	for (i=0; i<MAX_WINGS; i++) {
		if (Wings[i].wave_count > 0) {
			if (Wings[i].hotkey != -1) {
				temp.Format("\tWing name: %s, hotkey: F%d\r\n", Wings[i].name, (Wings[i].hotkey + 5));
				buffer += temp;
			}
		}
	}

}

void DumpStats::get_objectives_and_goals(CString &buffer)
{
	CString temp;
	int i;

	buffer += "\r\nOBJECTIVES AND GOALS\r\n";

	// objectives
	for (i=0; i<(int)Mission_events.size(); i++) {
		// name, objective_text, objective_key_text
		if ( Mission_events[i].objective_text.empty() ) {
			continue;
		}
		temp.Format("\tObjective: %s,  text: %s,  key_text: %s\r\n", Mission_events[i].name.c_str(), Mission_events[i].objective_text.c_str(), Mission_events[i].objective_key_text.c_str());
		buffer += temp;
	}

	buffer += "\r\n";

	// goals
	for (i=0; i<(int)Mission_goals.size(); i++) {
		temp.Format("\tGoal: %s, text: %s", Mission_goals[i].name.c_str(), Mission_goals[i].message.c_str());
		buffer += temp;

		switch(Mission_goals[i].type & GOAL_TYPE_MASK) {
		case PRIMARY_GOAL:
			buffer += ",  type: primary\r\n";
			break;

		case SECONDARY_GOAL:
			buffer += ",  type: secondary\r\n";
			break;

		case BONUS_GOAL:
			buffer += ",  type: bonus\r\n";
			break;

		default:
			Int3();
			break;
		}
	}

}

void DumpStats::get_ship_weapon_selection(CString &buffer)
{
	CString temp;
	int i,j;

	buffer += "\r\nSHIP WEAPON/SELECTION\r\n";
	buffer += "Reported numbers are in addition to assigned ships and their default weapons\r\n";

	for (i=0; i<Num_teams; i++) {
		temp.Format("Team %d\r\n", i);
		buffer += temp;

		// ships
		for (j=0; j<Team_data[i].num_ship_choices; j++) {
			temp.Format("\tShip name: %s, count %d", Ship_info[Ships[Team_data[i].ship_list[j]].ship_info_index].name, Team_data[i].ship_count[j]);
			buffer += temp;

			if (Team_data[i].ship_list[j] == Team_data[i].default_ship) {
				temp = "  DEFAULT SHIP\r\n";
			} else {
				temp = "\r\n";
			}
			buffer += temp;
		}

		buffer += "\r\n";

		// weapons
		for (j=0; j<Team_data[i].num_weapon_choices; j++) {
			//if (Team_data[i].weaponry_pool[j] > 0) 
			temp.Format("\tWeapon name: %s, count %d\r\n", Weapon_info[Team_data[i].weaponry_pool[j]].name, Team_data[i].weaponry_count[j]);
			buffer += temp;
			
		}
	}

}

void DumpStats::get_messaging_info(CString &buffer)
{
	CString temp;
	object *objp;
	ship *shipp;

	buffer += "\r\nSHIP ACCEPTED ORDERS\r\n";

	// go through all ships and check (.orders_accepted against default_orders)
	for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
		if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
			shipp = &Ships[objp->instance];

			if (shipp->orders_accepted != ship_get_default_orders_accepted(&Ship_info[shipp->ship_info_index])) {
				temp.Format("\tShip: %s with nonstandard accepted orders\r\n", shipp->ship_name);
				buffer += temp;
			}
		}
	}
}

void DumpStats::get_species_ship_breakdown(CString &buffer)
{
	CString temp;
	int i;
	int species;
	object *objp;
	ship *shipp;

	buffer += "\r\nSHIP SPECIES BREAKDOWN\r\n";


	for (species=0; (uint) species < Species_info.size(); species++) {
		buffer += Species_info[species].species_name;
		buffer += "\r\n";

		// fighter wings
		buffer += "\tFighter wings:\r\n";
		for (i=0; i<MAX_WINGS; i++) {
			if (Wings[i].wave_count > 0) {
				int wing_leader_shipnum = Wings[i].ship_index[Wings[i].special_ship];
				if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].species == species) {
					if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].flags[Ship::Info_Flags::Fighter]) {
						temp.Format("\t\tWing: %s, count: %d, waves: %d, type: %s\r\n", Wings[i].name, Wings[i].wave_count, Wings[i].num_waves, Ship_info[Ships[wing_leader_shipnum].ship_info_index].name);
						buffer += temp;
					}
				}
			}
		}

		// bomber wings
		buffer += "\tBomber wings:\r\n";
		for (i=0; i<MAX_WINGS; i++) {
			if (Wings[i].wave_count > 0) {
				int wing_leader_shipnum = Wings[i].ship_index[Wings[i].special_ship];
				if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].species == species) {
					if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].flags[Ship::Info_Flags::Bomber]) {
						temp.Format("\t\tWing: %s, count: %d, waves: %d, type: %s\r\n", Wings[i].name, Wings[i].wave_count, Wings[i].num_waves, Ship_info[Ships[wing_leader_shipnum].ship_info_index].name);
						buffer += temp;
					}
				}
			}
		}

		buffer += "\tFreighters, Cargo, Transports:\r\n";
		// freighters and transports (cargo)
		for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
			if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
				shipp = &Ships[objp->instance];

				if (Ship_info[shipp->ship_info_index].species == species) {
					//if (shipp->wingnum == -1)
					//if (shipp->cargo1 > 0)
                    if (Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Freighter] || Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Transport] || Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Cargo]) {
						temp.Format("\t\tName: %s Type: %s, Cargo: %s\r\n", shipp->ship_name, Ship_info[shipp->ship_info_index].name, Cargo_names[shipp->cargo1]);
						buffer += temp;
					}
				}
			}
		}

		buffer += "\tNav buoy, Escape pod, Sentry gun:\r\n";
		for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
			if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
				shipp = &Ships[objp->instance];

				if (Ship_info[shipp->ship_info_index].species == species) {
					//if (shipp->wingnum == -1)
					//if (shipp->cargo1 > 0)
                    if (Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Navbuoy] || Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Escapepod] || Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Sentrygun]) {
						temp.Format("\t\tName: %s, Type: %s Cargo: %s\r\n", shipp->ship_name, Ship_info[shipp->ship_info_index].name, Cargo_names[shipp->cargo1]);
						buffer += temp;
					}
				}
			}
		}


		// cruiser
		buffer += "\tCruiser:\r\n";
		for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
			if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
				shipp = &Ships[objp->instance];

				if (Ship_info[shipp->ship_info_index].species == species) {
					//if (shipp->wingnum == -1)
					//if (shipp->cargo1 > 0)
					if (Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Cruiser]) {
						temp.Format("\t\tName: %s, Type: %s, Cargo: %s\r\n", shipp->ship_name, Ship_info[shipp->ship_info_index].name, Cargo_names[shipp->cargo1]);
						buffer += temp;
					}
				}
			}
		}

		// dry dock, cap, super cap
		buffer += "\tDry dock, Capital, Supercap:\r\n";
		for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
			if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
				shipp = &Ships[objp->instance];

				if (Ship_info[shipp->ship_info_index].species == species) {
					//if (shipp->wingnum == -1)
					//if (shipp->cargo1 > 0)
                    if (Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Drydock] || Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Capital] || Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Supercap]) {
						temp.Format("\t\tName: %s, Type: %s, Cargo: %s\r\n", shipp->ship_name, Ship_info[shipp->ship_info_index].name, Cargo_names[shipp->cargo1]);
						buffer += temp;
					}
				}
			}
		}

		buffer += "\r\n";
	}
}

void dump_loadout(ship *shipp, CString &loadout)
{
	CString temp;
	char *weapon_name;

	loadout = "";

//	PRIMARY
	int pri_idx, sec_idx;

	for (pri_idx=0; pri_idx < shipp->weapons.num_primary_banks; pri_idx++) {
		if (shipp->weapons.primary_bank_weapons[pri_idx] == -1) {
			weapon_name = "none";
		} else {
			weapon_name = Weapon_info[shipp->weapons.primary_bank_weapons[pri_idx]].name;
		} 
		temp.Format("\t\t\tPrimary[%d]: %s\r\n", pri_idx+1, weapon_name);
		loadout += temp;
	}

// SECONDARY
	for (sec_idx=0; sec_idx < shipp->weapons.num_secondary_banks; sec_idx++) {
		if (shipp->weapons.secondary_bank_weapons[sec_idx] == -1) {
			weapon_name = "none";
		} else {
			weapon_name = Weapon_info[shipp->weapons.secondary_bank_weapons[sec_idx]].name;
		} 
		temp.Format("\t\t\tSecondary[%d]: %s\r\n", sec_idx+1, weapon_name);
		loadout += temp;
	}

// TURRET
	ship_subsys *ss;
	for (ss = GET_FIRST(&shipp->subsys_list); ss != END_OF_LIST(&shipp->subsys_list); ss = GET_NEXT(ss) ) {
		if ( (ss->system_info->type == SUBSYSTEM_TURRET) ) {
//			ss->weapons.num_primary_banks, ss->weapons.num_secondary_banks, ss->weapons.primary_bank_weapons[3], ss->weapons.secondary_bank_weapons[2]
//			ss->system_info->primary_banks, ss->system_info->secondary_banks
			temp.Format("\t\t\tTurret: %s\r\n", ss->system_info->subobj_name);
			loadout += temp;

			// PRIMARY
			for (pri_idx=0; pri_idx < ss->weapons.num_primary_banks; pri_idx++) {
				if (ss->weapons.primary_bank_weapons[pri_idx] == -1) {
					weapon_name = "none";
				} else {
					weapon_name = Weapon_info[ss->weapons.primary_bank_weapons[pri_idx]].name;
				} 
				temp.Format("\t\t\t\tPrimary[%d]: %s\r\n", pri_idx+1, weapon_name);
				loadout += temp;
			}

			// SECONDARY
			for (sec_idx=0; sec_idx < ss->weapons.num_secondary_banks; sec_idx++) {
				if (ss->weapons.secondary_bank_weapons[sec_idx] == -1) {
					weapon_name = "none";
				} else {
					weapon_name = Weapon_info[ss->weapons.secondary_bank_weapons[sec_idx]].name;
				} 
				temp.Format("\t\t\t\tSecondary[%d]: %s\r\n", sec_idx+1, weapon_name);
				loadout += temp;
			}
		}
	}

}

void DumpStats::get_default_ship_loadouts(CString &buffer)
{
	int i;
	int species;
	object *objp;
	ship *shipp;
	CString temp, loadout;

	buffer += "\r\nSHIP SPECIES BREAKDOWN\r\n";


	for (species=0; (uint) species < Species_info.size(); species++) {
		buffer += Species_info[species].species_name;
		buffer += "\r\n";

		// fighter wings
		buffer += "\tFighter wings:\r\n";
		for (i=0; i<MAX_WINGS; i++) {
			if (Wings[i].wave_count > 0) {
				int wing_leader_shipnum = Wings[i].ship_index[Wings[i].special_ship];
				if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].species == species) {
					if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].flags[Ship::Info_Flags::Fighter]) {
						temp.Format("\t\tWing: %s\r\n", Wings[i].name);
						buffer += temp;
						dump_loadout(&Ships[wing_leader_shipnum], loadout);
						buffer += loadout;
					}
				}
			}
		}

		// bomber wings
		buffer += "\tBomber wings:\r\n";
		for (i=0; i<MAX_WINGS; i++) {
			if (Wings[i].wave_count > 0) {
				int wing_leader_shipnum = Wings[i].ship_index[Wings[i].special_ship];
				if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].species == species) {
					if (Ship_info[Ships[wing_leader_shipnum].ship_info_index].flags[Ship::Info_Flags::Bomber]) {
						temp.Format("\t\tWing: %s\r\n", Wings[i].name);
						buffer += temp;
						dump_loadout(&Ships[wing_leader_shipnum], loadout);
						buffer += loadout;
					}
				}
			}
		}

		buffer += "\tFreighters, Cargo, Transports:\r\n";
		// freighters and transports (cargo)
		for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
			if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
				shipp = &Ships[objp->instance];

				if (Ship_info[shipp->ship_info_index].species == species) {
					//if (shipp->wingnum == -1)
					//if (shipp->cargo1 > 0)
                    if (Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Freighter] || Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Transport]) {
						temp.Format("\t\tName: %s\r\n", shipp->ship_name);
						buffer += temp;
						dump_loadout(shipp, loadout);
						buffer += loadout;
					}
				}
			}
		}

		buffer += "\tEscape pod, Sentry gun:\r\n";
		for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
			if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
				shipp = &Ships[objp->instance];

				if (Ship_info[shipp->ship_info_index].species == species) {
					//if (shipp->wingnum == -1)
					//if (shipp->cargo1 > 0)
                    if (Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Escapepod] || Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Sentrygun]) {
						temp.Format("\t\tName: %s\r\n", shipp->ship_name);
						buffer += temp;
						dump_loadout(shipp, loadout);
						buffer += loadout;
					}
				}
			}
		}


		// cruiser
		buffer += "\tCruiser:\r\n";
		for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
			if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
				shipp = &Ships[objp->instance];

				if (Ship_info[shipp->ship_info_index].species == species) {
					//if (shipp->wingnum == -1)
					//if (shipp->cargo1 > 0)
                    if (Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Cruiser]) {
						temp.Format("\t\tName: %s\r\n", shipp->ship_name);
						buffer += temp;
						dump_loadout(shipp, loadout);
						buffer += loadout;
					}
				}
			}
		}

		// dry dock, cap, super cap
		buffer += "\tCapital, Supercap:\r\n";
		for ( objp = GET_FIRST(&obj_used_list); objp != END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
			if (objp->type == OBJ_START || objp->type == OBJ_SHIP) {
				shipp = &Ships[objp->instance];

				if (Ship_info[shipp->ship_info_index].species == species) {
					//if (shipp->wingnum == -1)
					//if (shipp->cargo1 > 0)
                    if (Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Capital] || Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Supercap]) {
						temp.Format("\t\tName: %s\r\n", shipp->ship_name);
						buffer += temp;
						dump_loadout(shipp, loadout);
						buffer += loadout;
					}
				}
			}
		}

		buffer += "\r\n";
	}
	// go through all wings

	// go through all ships not in wings and FLYABLE

	// print primary, secondary, and BIG turrets
}
