#include <SDL2/SDL.h>
#include "video.h"
#include "wx-sdl2.h"
#include "wx-sdl2-video.h"
#include "ibm.h"
#include "device.h"
#include "x86_ops.h"
#include "mem.h"
#include "codegen.h"
#include "cpu.h"
#include "model.h"
#include "fdd.h"
#include "hdd.h"
#include "ide.h"
#include "cdrom-image.h"
#include "scsi_zip.h"
#include "codegen_allocator.h"
#include "wx-common.h"

drive_info_t drive_info[10];

int status_is_open = 0;

extern int sreadlnum, swritelnum, segareads, segawrites, scycles_lost;
extern int render_fps, fps;

extern uint64_t main_time;
extern uint64_t render_time;
static uint64_t status_time;

drive_info_t *get_machine_info(char *s, int *num_drive_info) {
	int drive, i;
	int pos = 0;
	sprintf(s,
		"Model: %s\n"
		"CPU: %s",
		model_getname(),
		models[model]->cpu[cpu_manufacturer].cpus[cpu].name);
	if (emulation_state == EMULATION_RUNNING)
		sprintf(s + strlen(s), "\nEmulation speed: %d%%", fps);
	else if (emulation_state == EMULATION_PAUSED)
		strcat(s, "\nEmulation is paused.");
	else
		strcat(s, "\nEmulation is not running.");

	for (i = 0; i < 2; ++i) {
		drive = 'A' + i;
		if (fdd_get_type(i) > 0) {
			strcpy(drive_info[pos].fn, discfns[i]);
			drive_info[pos].enabled = strlen(drive_info[pos].fn) > 0;
			drive_info[pos].drive = i;
			drive_info[pos].drive_letter = drive;
			drive_info[pos].type = DRIVE_TYPE_FDD;
			drive_info[pos].readflash = readflash_get(READFLASH_FDC, i);
			readflash_clear(READFLASH_FDC, i);
			pos++;
		}
	}
	int num_hdds = hdd_controller_current_is_mfm() ? 2 : (hdd_controller_current_is_scsi() ? 7 : 4);
	for (i = 0; i < num_hdds; ++i) {
		drive = 'C' + i;
		if (!hdd_controller_current_is_mfm() && i == cdrom_channel) {
			if (cdrom_drive < 0)
				continue;
			if (cdrom_drive == CDROM_IMAGE) {
				if (!strlen(image_path))
					continue;
				strcpy(drive_info[pos].fn, image_path);
			} else
				strcpy(drive_info[pos].fn, "");
			drive_info[pos].enabled = strlen(drive_info[pos].fn) > 0;
			drive_info[pos].drive = i;
			drive_info[pos].drive_letter = drive;
			drive_info[pos].type = DRIVE_TYPE_CDROM;
			drive_info[pos].readflash = readflash_get(READFLASH_HDC, i);
			readflash_clear(READFLASH_HDC, i);
			pos++;
		} else if (!hdd_controller_current_is_mfm() && i == zip_channel) {
			strcpy(drive_info[pos].fn, "");
			drive_info[pos].enabled = zip_loaded();
			drive_info[pos].drive = i;
			drive_info[pos].drive_letter = drive;
			drive_info[pos].type = DRIVE_TYPE_FDD;
			drive_info[pos].readflash = readflash_get(READFLASH_HDC, i);
			readflash_clear(READFLASH_HDC, i);
			pos++;
		} else if (strlen(ide_fn[i]) > 0) {
			strcpy(drive_info[pos].fn, ide_fn[i]);
			drive_info[pos].enabled = 1;
			drive_info[pos].drive = i;
			drive_info[pos].drive_letter = drive;
			drive_info[pos].type = DRIVE_TYPE_HDD;
			drive_info[pos].readflash = readflash_get(READFLASH_HDC, i);
			readflash_clear(READFLASH_HDC, i);
			pos++;
		}
	}
	*num_drive_info = pos;
	return drive_info;
}

int get_status(char *machine, char *device) {
//        if (!status_is_open) {
//                return 0;
//        }
//        char device_s[4096];
	uint64_t new_time = timer_read();
	uint64_t status_diff = new_time - status_time;
	status_time = new_time;
	sprintf(machine,
		"CPU speed : %f MIPS\n"
		"FPU speed : %f MFLOPS\n\n"

		/*                        "Cache misses (read) : %i/sec\n"
			"Cache misses (write) : %i/sec\n\n"*/

		"Video throughput (read) : %i bytes/sec\n"
		"Video throughput (write) : %i bytes/sec\n\n"
		"Effective clockspeed : %iHz\n\n"
		"Timer 0 frequency : %fHz\n\n"
		"CPU time : %f%% (%f%%)\n"
		"Render time : %f%% (%f%%)\n"
		"Renderer: %s\n"
		"Render FPS: %d\n"
		"\n"

		"New blocks : %i\nOld blocks : %i\nRecompiled speed : %f MIPS\nAverage size : %f\n"
		"Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i\nReal speed : %f MIPS\nMem blocks used : %i (%g MB)"
		//                        "\nFully recompiled ins %% : %f%%"
		, mips,
		flops,
		/*#ifndef DYNAREC
			sreadlnum,
			swritelnum,
		#endif*/
		segareads,
		segawrites,
		cpu_get_speed() - scycles_lost,
		pit_timer0_freq(),
		((double)main_time * 100.0) / status_diff,
		((double)main_time * 100.0) / timer_freq,
		((double)render_time * 100.0) / status_diff,
		((double)render_time * 100.0) / timer_freq,
		current_render_driver_name,
		render_fps, cpu_new_blocks_latched, cpu_recomp_blocks_latched, (double)cpu_recomp_ins_latched / 1000000.0, (double)cpu_recomp_ins_latched / cpu_recomp_blocks_latched,
		cpu_recomp_flushes_latched, cpu_recomp_evicted_latched,
		cpu_recomp_reuse_latched, cpu_recomp_removed_latched,

		((double)cpu_recomp_ins_latched / 1000000.0) / ((double)main_time / timer_freq),
		codegen_allocator_usage,
		(double)(codegen_allocator_usage * MEM_BLOCK_SIZE) / (1024.0 * 1024.0)
		//                        ((double)cpu_recomp_full_ins_latched / (double)cpu_recomp_ins_latched) * 100.0
		//                        cpu_reps_latched, cpu_notreps_latched
	);
	main_time = 0;
	render_time = 0;
	/*#ifndef DYNAREC
	device_add_status_info(device_s, 4096);
	#endif*/

//        device_s[0] = 0;
	device[0] = 0;
	device_add_status_info(device, 4096);

	return 1;
}
