/*Arculator 2.1 by Sarah Walker
  New hard disc dialogue*/
#include <stdint.h>
#include <wx/wxprec.h>

#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif

#include <wx/xrc/xmlres.h>
#include "wx-hd_new.h"

static int MAX_CYLINDERS = 1024;
static int MAX_HEADS = 16;
static int MIN_SECTORS = 1;
static int MAX_SECTORS = 63;
static int SECTOR_SIZE = 512;
#define MAX_SIZE ((MAX_CYLINDERS * MAX_HEADS * MAX_SECTORS) / (1024 * 1024 / SECTOR_SIZE))

class HDNewDialog: public wxDialog
{
public:
	HDNewDialog(wxWindow *parent);

	int new_sectors;
	int new_heads;
	int new_cylinders;
	char new_fn[256];

private:
	void OnOK(wxCommandEvent &event);
	void OnCancel(wxCommandEvent &event);

	void OnFile(wxCommandEvent &event);
	void OnCHS(wxCommandEvent &event);
	void OnSize(wxCommandEvent &event);
};

HDNewDialog::HDNewDialog(wxWindow *parent)
{
	wxXmlResource::Get()->LoadDialog(this, parent, "HdNewDlg");

	Bind(wxEVT_BUTTON, &HDNewDialog::OnOK, this, wxID_OK);
	Bind(wxEVT_BUTTON, &HDNewDialog::OnCancel, this, wxID_CANCEL);
	Bind(wxEVT_BUTTON, &HDNewDialog::OnFile, this, XRCID("IDC_CFILE"));
	Bind(wxEVT_TEXT, &HDNewDialog::OnCHS, this, XRCID("IDC_EDIT_SECTORS"));
	Bind(wxEVT_TEXT, &HDNewDialog::OnCHS, this, XRCID("IDC_EDIT_HEADS"));
	Bind(wxEVT_TEXT, &HDNewDialog::OnCHS, this, XRCID("IDC_EDIT_CYLINDERS"));
	Bind(wxEVT_TEXT, &HDNewDialog::OnSize, this, XRCID("IDC_EDIT_SIZE"));

	if (SECTOR_SIZE == 512)
	{
		((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_SECTORS")))->SetValue("63");
		((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_HEADS")))->SetValue("16");
		((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_CYLINDERS")))->SetValue("100");
	}
	else
	{
		((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_SECTORS")))->SetValue("32");
		((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_HEADS")))->SetValue("8");
		((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_CYLINDERS")))->SetValue("615");
	}
	((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_SIZE")))->SetValue("40");
}

void HDNewDialog::OnOK(wxCommandEvent &event)
{
	wxString temp_s;

	temp_s = ((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_CYLINDERS")))->GetValue();
	new_cylinders = atoi(temp_s);
	temp_s = ((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_HEADS")))->GetValue();
	new_heads = atoi(temp_s);
	temp_s = ((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_SECTORS")))->GetValue();
	new_sectors = atoi(temp_s);
	temp_s = ((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_FN")))->GetValue();
	strncpy(new_fn, temp_s, sizeof(new_fn)-1);
	new_fn[sizeof(new_fn)-1] = 0;

	int total_sectors = new_cylinders * new_heads * new_sectors;
	FILE *f = fopen(new_fn, "wb");
	if (f)
	{
		uint8_t sector_buf[512];

		memset(sector_buf, 0, 512);

		for (int c = 0; c < total_sectors; c++)
			fwrite(sector_buf, SECTOR_SIZE, 1, f);

		fclose(f);
		EndModal(1);
	}
	else
	{
		wxMessageBox("Could not create file", "Arculator", wxOK | wxCENTRE | wxSTAY_ON_TOP | wxICON_ERROR, this);
	}
}
void HDNewDialog::OnCancel(wxCommandEvent &event)
{
	EndModal(0);
}

static bool in_callback = false;

void HDNewDialog::OnFile(wxCommandEvent &event)
{
	wxString fn = wxFileSelector("New disc image", "", "", "",
				     "HDF Disc Image|*.hdf|All Files|*.*", wxFD_SAVE | wxFD_OVERWRITE_PROMPT, this);

	if (!fn.empty())
	{
		((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_FN")))->SetValue(fn);
	}
}

void HDNewDialog::OnCHS(wxCommandEvent &event)
{
	wxString temp_s;
	char size_s[80];
	int cylinders, heads, sectors;
	int size;

	if (in_callback)
		return;
	in_callback = true;

	temp_s = ((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_CYLINDERS")))->GetValue();
	cylinders = atoi(temp_s);
	if (cylinders > MAX_CYLINDERS)
	{
		cylinders = MAX_CYLINDERS;
		snprintf(size_s, sizeof(size_s), "%i", cylinders);
		((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_CYLINDERS")))->SetValue(size_s);
	}

	temp_s = ((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_HEADS")))->GetValue();
	heads = atoi(temp_s);
	if (heads > MAX_HEADS)
	{
		heads = MAX_HEADS;
		snprintf(size_s, sizeof(size_s), "%i", heads);
		((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_HEADS")))->SetValue(size_s);
	}

	temp_s = ((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_SECTORS")))->GetValue();
	sectors = atoi(temp_s);
	if (sectors > MAX_SECTORS)
	{
		sectors = MAX_SECTORS;
		snprintf(size_s, sizeof(size_s), "%i", sectors);
		((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_SECTORS")))->SetValue(size_s);

	}
	else if (sectors < MIN_SECTORS)
	{
		sectors = MIN_SECTORS;
		snprintf(size_s, sizeof(size_s), "%i", sectors);
		((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_SECTORS")))->SetValue(size_s);

	}

	size = (cylinders * heads * sectors) / (1024 * 1024 / SECTOR_SIZE);
	snprintf(size_s, sizeof(size_s), "%i", size);
	((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_SIZE")))->SetValue(size_s);

	in_callback = false;
}

void HDNewDialog::OnSize(wxCommandEvent &event)
{
	wxString temp_s;
	char size_s[80];
	int cylinders, heads, sectors;
	int size;

	if (in_callback)
		return;
	in_callback = true;

	temp_s = ((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_SIZE")))->GetValue();
	size = atoi(temp_s);
	if (size > MAX_SIZE)
	{
		size = MAX_SIZE;
		snprintf(size_s, sizeof(size_s), "%i", size);
		((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_SIZE")))->SetValue(size_s);
	}

	heads = MAX_HEADS;
	sectors = MAX_SECTORS;
	cylinders = (size * (1024 * 1024 / SECTOR_SIZE)) / (MAX_HEADS * MAX_SECTORS);

	snprintf(size_s, sizeof(size_s), "%i", cylinders);
	((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_CYLINDERS")))->SetValue(size_s);
	snprintf(size_s, sizeof(size_s), "%i", heads);
	((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_HEADS")))->SetValue(size_s);
	snprintf(size_s, sizeof(size_s), "%i", sectors);
	((wxTextCtrl *)this->FindWindow(XRCID("IDC_EDIT_SECTORS")))->SetValue(size_s);

	in_callback = false;
}

int ShowNewHD(wxWindow *parent, int *new_sectors, int *new_heads, int *new_cylinders, char *new_fn, int new_fn_size, bool is_st506)
{
	if (is_st506)
	{
		MAX_CYLINDERS = 1024;
		MAX_HEADS = 8;
		MIN_SECTORS = 32;
		MAX_SECTORS = 32;
		SECTOR_SIZE = 256;
	}
	else
	{
		MAX_CYLINDERS = 1024;
		MAX_HEADS = 16;
		MIN_SECTORS = 1;
		MAX_SECTORS = 63;
		SECTOR_SIZE = 512;
	}

	HDNewDialog dlg(parent);

	dlg.Fit();
	if (dlg.ShowModal())
	{
		*new_sectors = dlg.new_sectors;
		*new_heads = dlg.new_heads;
		*new_cylinders = dlg.new_cylinders;
		strncpy(new_fn, dlg.new_fn, new_fn_size);

		return 1;
	}
	else
		return 0;
}
