/*	Renegade Scripts.dll
	Shader Database Editor Main Code
	Copyright 2007 Jonathan Wilson

	This file is part of the Renegade scripts.dll
	The Renegade scripts.dll is free software; you can redistribute it and/or modify it under
	the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2, or (at your option) any later
	version. See the file COPYING for more details.
	In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence.
	Only the source code to the module(s) containing the licenced code has to be released.
*/
#include <stdio.h>
#include "resource1.h"
#include "scripts.h"
#include "shadereng.h"
#include <commdlg.h>
#include "editorshader.h"
#include "editorshadermgr.h"
#include "shader_scene.h"
#include "scene_shader_editor.h"


HINSTANCE hInst;
bool save = false;
bool savepost = false;
const char *Get_Renegade_Data_Folder()
{
	HKEY key;
	LONG error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Westwood\\Renegade",0,KEY_ALL_ACCESS,&key);
	unsigned long size = 4;
	unsigned long type;
	error = RegQueryValueEx(key,"InstallPath",0,&type,NULL,&size);
	if (error == ERROR_FILE_NOT_FOUND)
	{
		return "c:\\";
	}
	char *c = new char[size+1];
	error = RegQueryValueEx(key,"InstallPath",0,&type,(BYTE *)c,&size);
	char *c2 = strrchr(c,'\\');
	c2[1] = 'd';
	c2[2] = 'a';
	c2[3] = 't';
	c2[4] = 'a';
	c2[5] = 0;
	return c;
}


BOOL CALLBACK MainDlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
	OPENFILENAME ofn;
	char sfile[MAX_PATH] = "";
	unsigned int x;
	int sel;
	char c[100];
	switch(Message)
	{
	case WM_INITDIALOG:
		save = false;
		savepost = false;
		SendMessage(hwnd,WM_SETICON,ICON_SMALL,(LPARAM)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_APP),IMAGE_ICON,32,32,LR_DEFAULTCOLOR));
		SendMessage(hwnd,WM_SETICON,ICON_BIG,(LPARAM)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_APP),IMAGE_ICON,32,32,LR_DEFAULTCOLOR));
		if (!TheEditorShaderManager)
		{
			TheEditorShaderManager = new EditorShaderManagerClass();
		}
		x = TheEditorShaderManager->EditorShaderFactories->Count();
		for (unsigned int i = 0;i < x;i++)
		{
			SendDlgItemMessage(hwnd,IDC_SHADERTYPES,LB_ADDSTRING,0,(LPARAM)(*TheEditorShaderManager->EditorShaderFactories)[i]->Name);
		}
		if (!SceneShaderController)
		{
			SceneShaderController = new SceneShaderControllerClass();	
		}
		for (int i = 0; i < SceneShaderRegistrar->FactoryCount; i++)
		{
			SceneShaderFactory *factory = SceneShaderRegistrar->GetFactoryByIndex(i);
			if (factory->Editable == true)
			{
				LRESULT res = SendDlgItemMessage(hwnd,IDC_PPSHADERTYPES,LB_ADDSTRING,0,(LPARAM)factory->Editor_Name);
				if ((res != LB_ERR) && (res != LB_ERRSPACE)) 
				{
					SendDlgItemMessage(hwnd,IDC_PPSHADERTYPES,LB_SETITEMDATA,(WPARAM)res,(LPARAM)i);
				}
			}
		}
		break;
	case WM_CLOSE:
		if ((save == true) || (savepost == true))
		{
			if (MessageBox(hwnd,"Unsaved changes, continue?","Unsaved changes",MB_YESNO) == IDNO)
			{
				break;
			}
		}
		EndDialog(hwnd, 0);
		break;
	case WM_COMMAND:
		switch(LOWORD(wParam))
		{
		case ID_FILE_EXIT:
			if ((save == true) || (savepost == true))
			{
				if (MessageBox(hwnd,"Unsaved changes, continue?","Unsaved changes",MB_YESNO) == IDNO)
				{
					break;
				}
			}
			EndDialog(hwnd, 0);
			break;
		case ID_FILE_NEWSDB:
			if (save == true)
			{
				if (MessageBox(hwnd,"Unsaved changes, continue?","Unsaved changes",MB_YESNO) == IDNO)
				{
					break;
				}
			}
			TheEditorShaderManager->Unload_Database();
			SendDlgItemMessage(hwnd,IDC_SHADERS,LB_RESETCONTENT,0,0);
			save = false;
			break;
		case ID_FILE_NEWPOST:
			if (savepost == true)
			{
				if (MessageBox(hwnd,"Unsaved changes, continue?","Unsaved changes",MB_YESNO) == IDNO)
				{
					break;
				}
			}
			SceneShaderController->UnloadDatabase();
			SendDlgItemMessage(hwnd,IDC_PPSHADERS,LB_RESETCONTENT,0,0);
			savepost = false;
			break;
		case ID_FILE_SAVESDB:
			ZeroMemory(&ofn, sizeof(ofn));
			ofn.lStructSize = sizeof(ofn);
			ofn.hwndOwner = hwnd;
			ofn.lpstrFilter = "Shader Databases (*.sdb)\0*.sdb\0";
			ofn.lpstrFile = sfile;
			ofn.lpstrTitle = "Save Shader Database";
			ofn.lpstrDefExt = ".sdb";
			ofn.nMaxFile = MAX_PATH;
			//ofn.lpstrInitialDir = Get_Renegade_Data_Folder();
			ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
			if (GetSaveFileName(&ofn))
			{
				FileClass *f = Get_Data_File(sfile);
				if (f)
				{
					f->Open(2);
					TheEditorShaderManager->Save_Database(f);
					Close_Data_File(f);
					save = false;
				}
			}
			break;
		case ID_FILE_SAVEPOST:
			ZeroMemory(&ofn, sizeof(ofn));
			ofn.lStructSize = sizeof(ofn);
			ofn.hwndOwner = hwnd;
			ofn.lpstrFilter = "Scene Shader Databases (*.sdb)\0*.sdb\0";
			ofn.lpstrFile = sfile;
			ofn.lpstrTitle = "Save Scene Shader Database";
			ofn.lpstrDefExt = ".sdb";
			ofn.nMaxFile = MAX_PATH;
			//ofn.lpstrInitialDir = Get_Renegade_Data_Folder();
			ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
			if (GetSaveFileName(&ofn))
			{
				FileClass *f = Get_Data_File(sfile);
				if (f)
				{
					f->Open(2);
					SceneShaderController->SaveDatabase(f);
					Close_Data_File(f);
					savepost = false;
				}
			}
			break;
		case ID_FILE_OPENSDB:
			ZeroMemory(&ofn, sizeof(ofn));
			ofn.lStructSize = sizeof(ofn);
			ofn.hwndOwner = hwnd;
			ofn.lpstrFilter = "Shader Databases (*.sdb)\0*.sdb\0All Files (*.*)\0*.*\0";
			ofn.lpstrFile = sfile;
			ofn.lpstrTitle = "Open Shader Database";
			ofn.nMaxFile = MAX_PATH;
			ofn.lpstrDefExt = ".sdb";
			//ofn.lpstrInitialDir = Get_Renegade_Data_Folder();
			ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_DONTADDTORECENT | OFN_NOCHANGEDIR;
			if (GetOpenFileName(&ofn))
			{
				TheEditorShaderManager->Unload_Database();
				SendDlgItemMessage(hwnd,IDC_SHADERS,LB_RESETCONTENT,0,0);
				FileClass *f = Get_Data_File(sfile);
				if (f)
				{
					f->Open(1);
					TheEditorShaderManager->Load_Database(f);
					Close_Data_File(f);
					save = false;
					if (!TheEditorShaderManager->EditorShaders)
					{
						break;
					}
					x = TheEditorShaderManager->EditorShaders->Count();
					for (unsigned int i = 0;i < x;i++)
					{
						SendDlgItemMessage(hwnd,IDC_SHADERS,LB_ADDSTRING,0,(LPARAM)(*TheEditorShaderManager->EditorShaders)[i]->Get_Name());
					}
				}
			}
			break;
		case ID_FILE_OPENPOST:
			ZeroMemory(&ofn, sizeof(ofn));
			ofn.lStructSize = sizeof(ofn);
			ofn.hwndOwner = hwnd;
			ofn.lpstrFilter = "Scene Shader Databases (*.sdb)\0*.sdb\0All Files (*.*)\0*.*\0";
			ofn.lpstrFile = sfile;
			ofn.lpstrTitle = "Open Scene Shader Database";
			ofn.nMaxFile = MAX_PATH;
			ofn.lpstrDefExt = ".sdb";
			//ofn.lpstrInitialDir = Get_Renegade_Data_Folder();
			ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_DONTADDTORECENT | OFN_NOCHANGEDIR;
			if (GetOpenFileName(&ofn))
			{
				SceneShaderController->UnloadDatabase();
				SendDlgItemMessage(hwnd,IDC_PPSHADERS,LB_RESETCONTENT,0,0);
				FileClass *f = Get_Data_File(sfile);
				if (f)
				{
					f->Open(1);
					SceneShaderController->LoadDatabase(f);
					for (unsigned int i = 0; i < SceneShaderController->GetShaderCount(); i++)
					{
						SendDlgItemMessage(hwnd,IDC_PPSHADERS,LB_ADDSTRING,0,(LPARAM)SceneShaderController->GetShaderByIndex(i)->Name);
					}
					Close_Data_File(f);
					savepost = false;
				}
			}
			break;
		case IDC_NEWSHADER:
			sel = SendDlgItemMessage(hwnd,IDC_SHADERTYPES,LB_GETCURSEL,0,0);
			if (sel != -1)
			{
				GetDlgItemText(hwnd,IDC_SHADERNAME,c,100);
				if (c[0])
				{
					EditorShaderClass *e = (*TheEditorShaderManager->EditorShaderFactories)[sel]->New(c);
					if (!TheEditorShaderManager->EditorShaders)
					{
						TheEditorShaderManager->EditorShaders = new SimpleDynVecClass<EditorShaderClass *>(0);
					}
					TheEditorShaderManager->EditorShaders->Add(e);
					SendDlgItemMessage(hwnd,IDC_SHADERS,LB_ADDSTRING,0,(LPARAM)e->Get_Name());
					e->Edit(hwnd);
				}
			}
			break;
		case IDC_NEWPPSHADER:

			sel = SendDlgItemMessage(hwnd,IDC_PPSHADERTYPES,LB_GETCURSEL,0,0);
			if (sel != -1)
			{
				GetDlgItemText(hwnd,IDC_PPSHADERNAME,c,100);
				if (c[0])
				{
					LRESULT registrarNum = SendDlgItemMessage(hwnd,IDC_PPSHADERTYPES,LB_GETITEMDATA,(WPARAM)sel,0);
					SceneShaderClass* shader = SceneShaderRegistrar->GetFactoryByIndex(registrarNum)->CreateNew();
					shader->PrivateData = shader->GetEditor();
					shader->Name = newstr(c);
					SceneShaderController->AddShader(shader);
					SendDlgItemMessage(hwnd,IDC_PPSHADERS,LB_ADDSTRING,0,(LPARAM)shader->Name);
					((SceneShaderEditorClass*)shader->PrivateData)->Edit(hwnd);
				}
			}
			break;
		case IDC_EDITSHADER:
			sel = SendDlgItemMessage(hwnd,IDC_SHADERS,LB_GETCURSEL,0,0);
			if (sel != -1)
			{
				(*TheEditorShaderManager->EditorShaders)[sel]->Edit(hwnd);
			}
			break;
		case IDC_EDITPPSHADER:
			sel = SendDlgItemMessage(hwnd,IDC_PPSHADERS,LB_GETCURSEL,0,0);
			if (sel != -1)
			{
				SceneShaderClass* shader = SceneShaderController->GetShaderByIndex(sel);
				if (shader)
				{
					if (!shader->PrivateData)
					{
						shader->PrivateData = shader->GetEditor();
					}
					SceneShaderEditorClass* editor = (SceneShaderEditorClass*) shader->PrivateData;
					if (editor) 
					{
						editor->Edit(hwnd);
					}
				}
			}
			break;
		case IDC_DELSHADER:
			sel = SendDlgItemMessage(hwnd,IDC_SHADERS,LB_GETCURSEL,0,0);
			if (sel != -1)
			{
				SendDlgItemMessage(hwnd,IDC_SHADERS,LB_DELETESTRING,sel,0);
				delete (*TheEditorShaderManager->EditorShaders)[sel];
				TheEditorShaderManager->EditorShaders->Delete(sel);
			}
			break;
		case IDC_DELPPSHADER:
			sel = SendDlgItemMessage(hwnd,IDC_PPSHADERS,LB_GETCURSEL,0,0);
			if (sel != -1)
			{
				SendDlgItemMessage(hwnd,IDC_PPSHADERS,LB_DELETESTRING,sel,0);
				SceneShaderController->DeleteShaderByIndex(sel);
			}
			break;
		}
		break;
	default:
		return FALSE;
	}
	return TRUE;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,int nCmdShow)
{
	hInst = hInstance;
	DialogBox(hInst, MAKEINTRESOURCE(IDD_MAIN), NULL,(DLGPROC)MainDlgProc);
	delete SceneShaderController;
	delete SceneShaderRegistrar;
	delete TheEditorShaderManager;
}
