/*******************************************************************************/

#include "Thps1HedWadEditor.h"

/*******************************************************************************/

////Header Include Start
#include "Images/Self_Thps1HedWadEditor_XPM.xpm"
////Header Include End

/*******************************************************************************/

////Event Table Start
BEGIN_EVENT_TABLE(Thps1HedWadEditor,wxFrame)
	////Manual Code Start
	////Manual Code End
	
	EVT_CLOSE(Thps1HedWadEditor::OnClose)
	EVT_BUTTON(ID_BTNEXPORTALL,Thps1HedWadEditor::BTNExportAllClick)
	EVT_BUTTON(ID_BTNSAVE,Thps1HedWadEditor::BTNSaveClick)
	EVT_BUTTON(ID_BTNOPEN,Thps1HedWadEditor::BTNOpenClick)
	EVT_BUTTON(ID_BTNEXPORT,Thps1HedWadEditor::BTNExportClick)
	EVT_BUTTON(ID_BTNIMPORT,Thps1HedWadEditor::BTNImportClick)
	EVT_BUTTON(ID_BTNDELETE,Thps1HedWadEditor::BTNDeleteClick)
	EVT_BUTTON(ID_BTNADD,Thps1HedWadEditor::BTNAddClick)
	EVT_LISTBOX(ID_LSTFILES,Thps1HedWadEditor::LSTFilesDoubleClicked)
	EVT_LISTBOX_DCLICK(ID_LSTFILES,Thps1HedWadEditor::LSTFilesDoubleClicked)
END_EVENT_TABLE()
////Event Table End

/*******************************************************************************/

Thps1HedWadEditor::Thps1HedWadEditor(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style)
: wxFrame(parent, id, title, position, size, style)
{
	CreateGUIControls();
	HTMLBmp -> SetBorders(0);
	ClearBMP();
    for(unsigned short x = 0; x < 4096; x++)
	{
        FileAr[x].rawdata = NULL;
        FileEx[x].rawdata = NULL;
    }
	FileSize = 0;
	Print("Program Initialized...");
}

/*******************************************************************************/

Thps1HedWadEditor::~Thps1HedWadEditor()
{
    for(unsigned short x = 0; x < 4096; x++)
	{
        delete[] FileAr[x].rawdata;
    }
}

/*******************************************************************************/

void Thps1HedWadEditor::CreateGUIControls()
{
	////GUI Items Creation Start

	DLGMsg =  new wxMessageDialog(this, wxT("Name Must Have 1 to 31 Characters!"), wxT("Message box"), wxICON_EXCLAMATION);

	DLGOpenWad =  new wxFileDialog(this, wxT("Choose a WAD file"), wxT(""), wxT(""), wxT("*.WAD"), wxOPEN | wxFILE_MUST_EXIST);

	DLGSaveWad =  new wxFileDialog(this, wxT("Choose a WAD file"), wxT(""), wxT(""), wxT("*.WAD"), wxSAVE);

	DLGSaveHed =  new wxFileDialog(this, wxT("Choose a HED file"), wxT(""), wxT(""), wxT("*.HED"), wxSAVE);

	DLGOpenHed =  new wxFileDialog(this, wxT("Choose a HED file"), wxT(""), wxT(""), wxT("*.HED"), wxOPEN | wxFILE_MUST_EXIST);

	DLGName =  new wxTextEntryDialog( this,wxT(""), wxT("Enter Internal Name Mi 1 to 31 Characters"), wxT("") ,wxOK | wxCENTRE);

	DLGExportAll =  new wxDirDialog(this, wxT("Choose a directory"), wxT(""), wxDD_NEW_DIR_BUTTON);

	DLGImport =  new wxFileDialog(this, wxT("Choose a file"), wxT(""), wxT(""), wxT("*.*"), wxOPEN | wxFILE_MUST_EXIST);

	DLGExport =  new wxFileDialog(this, wxT("Choose a file"), wxT(""), wxT(""), wxT("*.*"), wxSAVE);

	BTNExportAll = new wxButton(this, ID_BTNEXPORTALL, wxT("Export All"), wxPoint(122, 552), wxSize(117, 19), 0, wxDefaultValidator, wxT("BTNExportAll"));
	BTNExportAll->Enable(false);

	HTMLBmp = new wxHtmlWindow(this, ID_HTMLBMP, wxPoint(241, 0), wxSize(550, 450));

	BTNSave = new wxButton(this, ID_BTNSAVE, wxT("Save Hed/Wad"), wxPoint(120, 0), wxSize(120, 50), 0, wxDefaultValidator, wxT("BTNSave"));
	BTNSave->Enable(false);

	BTNOpen = new wxButton(this, ID_BTNOPEN, wxT("Open Hed/Wad"), wxPoint(0, 0), wxSize(120, 50), 0, wxDefaultValidator, wxT("BTNOpen"));

	BTNExport = new wxButton(this, ID_BTNEXPORT, wxT("Export File"), wxPoint(123, 526), wxSize(116, 26), 0, wxDefaultValidator, wxT("BTNExport"));
	BTNExport->Enable(false);

	BTNImport = new wxButton(this, ID_BTNIMPORT, wxT("Replace File"), wxPoint(0, 526), wxSize(121, 44), 0, wxDefaultValidator, wxT("BTNImport"));
	BTNImport->Enable(false);

	BTNDelete = new wxButton(this, ID_BTNDELETE, wxT("Delete File"), wxPoint(124, 490), wxSize(114, 34), 0, wxDefaultValidator, wxT("BTNDelete"));
	BTNDelete->Enable(false);

	BTNAdd = new wxButton(this, ID_BTNADD, wxT("Add New File"), wxPoint(0, 490), wxSize(122, 34), 0, wxDefaultValidator, wxT("BTNAdd"));
	BTNAdd->Enable(false);

	EDTConsole = new wxTextCtrl(this, ID_EDTCONSOLE, wxT(""), wxPoint(239, 451), wxSize(552, 120), wxTE_READONLY | wxTE_MULTILINE, wxDefaultValidator, wxT("EDTConsole"));
	EDTConsole->SetForegroundColour(wxColour(wxT("SKY BLUE")));
	EDTConsole->SetBackgroundColour(wxColour(wxT("BLACK")));

	wxArrayString arrayStringFor_LSTFiles;
	LSTFiles = new wxListBox(this, ID_LSTFILES, wxPoint(0, 50), wxSize(240, 440), arrayStringFor_LSTFiles, wxLB_SINGLE);

	SetTitle(wxT("Kamiloxnumetal's Thps1 Hed Wad Editor"));
	SetIcon(Self_Thps1HedWadEditor_XPM);
	SetSize(8,8,800,600);
	Center();
	
	////GUI Items Creation End
}

/*******************************************************************************/

void Thps1HedWadEditor::OnClose(wxCloseEvent& event)
{
	Destroy();
}

/*******************************************************************************/

void Thps1HedWadEditor::BTNOpenClick(wxCommandEvent& event)
{
	if(DLGOpenHed -> ShowModal() == wxID_OK)
	{
        Print("\nReading Header File *.HED");
        FHandler.Open(DLGOpenHed -> GetPath(),wxFile::read);
        bool strflag = true;
        unsigned short strsize = 0;
        unsigned char buf0;
        unsigned char buf1;
        unsigned char buf2;
        unsigned char buf3;
        while(true)
        {
            if(strflag)
            {
                FHandler.Read(&buf0,1);
                if(buf0 == 0xff)
                    break;
                FHandler.Read(&buf1,1);
                FHandler.Read(&buf2,1);
                FHandler.Read(&buf3,1);
                strsize+=4;
                if(!buf0 || !buf1 || !buf2 || !buf3)
                {
                    FileSize++;
                    FHandler.Seek(FHandler.Tell() - strsize);
                    FHandler.Read(&(FileAr[FileSize-1].name[0]),strsize);
                    LSTFiles -> Append(FileAr[FileSize-1].name);
                    strsize = 0;
                    strflag = false;
                }
            }
            else
            {
                FHandler.Read(&(FileAr[FileSize-1].offset),4);
                FHandler.Read(&(FileAr[FileSize-1].size),4);
                strflag = true;
            }
        }
        Print("\nHeader Readed, Found ");
        Print(FileSize);
        Print(" Files...");
        FHandler.Close();
        if(DLGOpenWad -> ShowModal() == wxID_OK)
        {
            Print("\nReading Data File *.WAD");
            FHandler.Open(DLGOpenWad -> GetPath(),wxFile::read);
            for(unsigned short x = 0; x < FileSize; x++)
            {
                FileAr[x].rawdata = new unsigned char[FileAr[x].size];
                FHandler.Seek(FileAr[x].offset);
                FHandler.Read(FileAr[x].rawdata,FileAr[x].size);
            }
            FHandler.Close();
            Print("\nData File Readed");
            BTNOpen->Enable(false);
            BTNSave->Enable();
	        BTNExport->Enable();
	        BTNImport->Enable();
	        BTNDelete->Enable();
	        BTNAdd->Enable();
	        BTNExportAll->Enable();
	        LSTFiles -> SetSelection(0);
        }
        else
        {
            FileSize = 0;
            LSTFiles -> Clear();
        }
    }
}

/*******************************************************************************/

void Thps1HedWadEditor::BTNSaveClick(wxCommandEvent& event)
{
    wxFile FHandlerAux;
    unsigned int offsetc = 0;
    unsigned short aux;
    unsigned short auxb;
    unsigned char auxc = 0;
	if(DLGSaveHed -> ShowModal() == wxID_OK)
    {
        if(FHandler.Open(DLGSaveHed -> GetPath(),wxFile::write))
        {
            if(DLGSaveWad -> ShowModal() == wxID_OK)
            {
                if(FHandlerAux.Open(DLGSaveWad -> GetPath(), wxFile::write))
                {
                    Print("\nCalculating Files Offsets");
                    for(unsigned short x = 0; x < FileSize; x++)
                    {
                        FileAr[x].offset = offsetc;
                        offsetc += FileAr[x].size;
                    }
                    Print("\nWriting *.HED");
                    for(unsigned short x = 0; x < FileSize; x++)
                    {
                        aux = strlen(FileAr[x].name);
                        aux++;
                        while(aux % 4 != 0)
                            aux++;
                        auxb = aux - strlen(FileAr[x].name);
                        for(unsigned char y = 0; y < strlen(FileAr[x].name); y++)
                            FHandler.Write(&(FileAr[x].name[y]),1);
                        for(unsigned char y = 0; y < auxb; y++)
                            FHandler.Write(&auxc,1);
                        FHandler.Write(&(FileAr[x].offset),4);
                        FHandler.Write(&(FileAr[x].size),4);
                    }
                    auxc = 0xff;
                    FHandler.Write(&auxc,1);
                    Print("\nWriting *.WAD");
                    for(unsigned short x = 0; x < FileSize; x++)
                    {
                        FHandlerAux.Write(FileAr[x].rawdata,FileAr[x].size);
                    }
                    FHandler.Close();
                    FHandlerAux.Close();
                    Print("\nHED/WAD Saved!");
                }
                else
                {
                    FHandler.Close();
                    Print("\nCan't Open WAD Destination File...");
                }
            }
            else
            {
                FHandler.Close();
            }
        }
        else
        {
            Print("\nCan't Open HED Destination File...");
        }
    }
}

/*******************************************************************************/

void Thps1HedWadEditor::BTNAddClick(wxCommandEvent& event)
{
	if(FileSize < 4096)
	{
        if(DLGImport -> ShowModal() == wxID_OK)
        {
            DLGName -> SetValue(DLGImport -> GetFilename());
            forcesize: DLGName -> ShowModal();
            if(DLGName -> GetValue().Length() <= 0 || DLGName -> GetValue().Length() >= 32)
            {
                DLGMsg -> ShowModal();
                goto forcesize;
            }
            FHandler.Open(DLGImport -> GetPath(),wxFile::read);
            FileAr[FileSize].size = FHandler.Length();
            FileAr[FileSize].rawdata = new unsigned char[FileAr[FileSize].size];
            strcpy(FileAr[FileSize].name,(const char *) DLGName -> GetValue());
            FHandler.Read(FileAr[FileSize].rawdata,FileAr[FileSize].size);
            FHandler.Close();
            LSTFiles -> Append(FileAr[FileSize++].name);
            Print("\nFile Added!");
            BTNSave->Enable();
	        BTNExport->Enable();
	        BTNImport->Enable();
	        BTNDelete->Enable();
	        BTNExportAll->Enable();
        }
    }
	else
    {
        Print("\nSorry This Program Only Allows 4096 Files, Contact yhwh.aggro@gmail.com For A Fix");
    }
}

/*******************************************************************************/

void Thps1HedWadEditor::BTNDeleteClick(wxCommandEvent& event)
{
    unsigned short delindex = LSTFiles -> GetSelection();
	if(FileSize == 1)
	{
        BTNSave->Enable(false);
	    BTNExport->Enable(false);
	    BTNImport->Enable(false);
	    BTNDelete->Enable(false);
	    BTNExportAll->Enable(false);
    }
    LSTFiles -> Clear();
    for(unsigned short x = 0; x < FileSize; x++)
    {
        strcpy(FileEx[x].name,FileAr[x].name);
        FileEx[x].size = FileAr[x].size;
        FileEx[x].rawdata = FileAr[x].rawdata;
        FileAr[x].rawdata = NULL;
    }
    for(unsigned short y = 0,x = 0; x < FileSize; x++)
    {
        if(x == delindex)
        {
            delete[] FileEx[x].rawdata;
            FileEx[x].rawdata = NULL;
        }
        else
        {
            strcpy(FileAr[y].name,FileEx[x].name);
            FileAr[y].size = FileEx[x].size;
            FileAr[y].rawdata = FileEx[x].rawdata;
            FileEx[x].rawdata = NULL;
            LSTFiles -> Append(FileAr[y].name);
            y++;
        }
    }
    LSTFiles -> SetSelection(0);
    FileSize--;
    Print("\nFile Deleted!");
}

/*******************************************************************************/

void Thps1HedWadEditor::BTNImportClick(wxCommandEvent& event)
{
	if(DLGImport -> ShowModal() == wxID_OK)
	{
        FHandler.Open(DLGImport -> GetPath(),wxFile::read);
        FileAr[LSTFiles -> GetSelection()].size = FHandler.Length();
        delete[] FileAr[LSTFiles -> GetSelection()].rawdata;
        FileAr[LSTFiles -> GetSelection()].rawdata = NULL;
        FileAr[LSTFiles -> GetSelection()].rawdata = new unsigned char[FileAr[LSTFiles -> GetSelection()].size];
        FHandler.Read(FileAr[LSTFiles -> GetSelection()].rawdata,FileAr[LSTFiles -> GetSelection()].size);
        FHandler.Close();
        Print("\nFile Replaced!");
    }
}

/*******************************************************************************/

void Thps1HedWadEditor::BTNExportClick(wxCommandEvent& event)
{
    DLGExport -> SetFilename(FileAr[LSTFiles -> GetSelection()].name);
	if(DLGExport -> ShowModal() == wxID_OK)
	{
        if(FHandler.Open(DLGExport -> GetPath(),wxFile::write))
        {
            FHandler.Write(FileAr[LSTFiles -> GetSelection()].rawdata,FileAr[LSTFiles -> GetSelection()].size);
            FHandler.Close();
            Print("\nFile Exported!");
        }
        else
            Print("\nCan't Open Destination File...");
    }
}

/*******************************************************************************/

void Thps1HedWadEditor::LSTFilesDoubleClicked(wxCommandEvent& event)
{
	wxString auxwxstr = FileAr[LSTFiles -> GetSelection()].name;
	if(auxwxstr.SubString(auxwxstr.Length() - 3,auxwxstr.Length() - 1).MakeUpper() == "BMP")
	{
        FHandler.Open("Temp.bmp",wxFile::write);
        FHandler.Write(FileAr[LSTFiles -> GetSelection()].rawdata,FileAr[LSTFiles -> GetSelection()].size);
        ShowBMP("Temp.bmp");
        FHandler.Close();
    }
	else
	   ClearBMP();
}

/*******************************************************************************/

void Thps1HedWadEditor::Print(const char* str)
{
	EDTConsole -> AppendText(str);
}

/*******************************************************************************/


void Thps1HedWadEditor::Print(unsigned int num)
{
	char aux[14];
	itoa(num,aux,10);
	EDTConsole -> AppendText(aux);
}

/*******************************************************************************/

void Thps1HedWadEditor::ShowBMP(const char* str)
{
	HTMLBmp -> SetPage("<HTML><BODY BgColor=\"Grey\"><IMG SRC=\"");
	HTMLBmp -> AppendToPage(str);
	HTMLBmp -> AppendToPage("\"></IMG></BODY></HTML>");
}

/*******************************************************************************/

void Thps1HedWadEditor::ClearBMP()
{
	HTMLBmp -> SetPage("<HTML><BODY BgColor=\"Grey\"></BODY></HTML>");
}

/*******************************************************************************/

void Thps1HedWadEditor::BTNExportAllClick(wxCommandEvent& event)
{
	if(DLGExportAll -> ShowModal() == wxID_OK)
	{
        wxString auxwx = DLGExportAll -> GetPath();
        if(auxwx.Last() != '\\')
            auxwx += '\\';
        Print("\nExport All Files To: ");
        Print(auxwx);
        for(unsigned short x=0; x < FileSize; x++)
        {
           if(FHandler.Open(auxwx + FileAr[x].name,wxFile::write))
           {
                FHandler.Write(FileAr[x].rawdata,FileAr[x].size);
                FHandler.Close();
           }
           else
           {
                Print("\nCan't Open Destination File For: ");
                Print(FileAr[x].name);
           }   
        }
        Print("\nAll Files Exported...");
    }
}

/*******************************************************************************/
