// ---------------------------------------------------------------------------
// 
//   Lily Engine alpha
// 
//   Copyright (c) 2010 Clifford Jolly
//     http://cliffjolly.com
//     cliff@cliffjolly.com
// 
// ---------------------------------------------------------------------------
// 
//   This program 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 of the License, or
//   (at your option) any later version.
//  
//   This program is distributed in the hope that it will be useful, but
//   WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//   General Public License for more details.
// 
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software
//   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
//   USA
// -------------------------- END HEADER -------------------------------------

#include <iostream>
using namespace std;

#include "console/console.h"
using namespace Console;

#include "game/gamemain.h"
#include <SDL.h>

#ifdef MACOSX
#include <mach-o/dyld.h>
#endif

#include "filesystem/filesystem.h"

// Set up console buffers with different colors and stuff.
void setupConsole(void) {
	outSetAttribs("error",    "31;1");
	outSetAttribs("warning",  "33;1");
	outSetAttribs("test",     "32;1");
	outSetAttribs("system",   "34;1");
	outSetAttribs("lua",      "36;1");
	outSetAttribs("world",    "36;1");
	outSetAttribs("graphics", "35;1");

	outSetPrefix("system",   "System:   ");
	outSetPrefix("error",    "Error:    ");
	outSetPrefix("warning",  "Warning:  ");
	outSetPrefix("test",     "Test:     ");
	outSetPrefix("lua",      "Lua:      ");
	outSetPrefix("world",    "World:    ");
	outSetPrefix("graphics", "Graphics: ");

	outSetSynced("error", true);
	outSetSynced("warning", true);
	outSetSynced("lua", true);

	// Turn off all the extra-verbose stuff.
	outSetEnabled("graphics", false);
}

// Testing function to show our directory hierarchy, including stuff in
// archives and what exists where.
void dumpDir(const std::string &dirName, int indentLevel, bool extractArchived = false) {
	
	vector<string> names;
	
	FileSystem::getAllFiles(dirName, names);

	for(unsigned int i = 0; i < names.size(); i++) {
		
		string fullPath = dirName + "/" + names[i];
		
		unsigned int flags = FileSystem::getFileFlags(fullPath);
		
		if(!extractArchived) {
			
			// Not extracting. Just dump information.
			
			if(flags & FileSystem::FILEFLAG_ARCHIVED) {
				cout << "A";
			} else {
				cout << "-";
			}
			
			if(flags & FileSystem::FILEFLAG_NONARCHIVED) {
				cout << "U";
			} else {
				cout << "-";
			}

			for(int j = 0; j < indentLevel + 1; j++) {
				cout << "  ";
			}
			
			cout << names[i] << endl;
		}
		
		if(FileSystem::isDir(fullPath)) {
		
			dumpDir(fullPath, indentLevel + 1, extractArchived);
		
		} else {
			
			if((flags & FileSystem::FILEFLAG_ARCHIVED) && !(flags & FileSystem::FILEFLAG_NONARCHIVED) && extractArchived) {
				
				// Normal file (not a directory), only exists in the
				// archive, and we were given the flag to extract.
				
				cout << "Extracting: " << fullPath << endl;
				
				int length;
				char *data = FileSystem::loadFile(fullPath, &length);
				FileSystem::saveFile(fullPath, data, length, true);
				delete[] data;
			}
		}
		
	}
	
}

void setupArchives(void) {
	
	// Debugging - Show the hierarchy of stuff.
	//dumpDir(".", 0);

    // Find all the .poop files in the working directory and add them.
    vector<string> wdFiles;
    vector<string> poopFiles;

    FileSystem::getNondirectories(".", wdFiles);
    FileSystem::filterFileListByType("poop", wdFiles, poopFiles);

    for(unsigned int i = 0; i < poopFiles.size(); i++) {
        FileSystem::addArchiveForSearch(poopFiles[i]);
    }

}

#ifdef WIN32
// TODO: Change this to a WinMain() at some point.
// (During development, having the console up is pretty nice, so we'll leave it for now.)
int main(int argc, char *argv[]) {
#else
int main(int argc, char *argv[]) {
#endif

#ifdef MACOSX
	
	// For Macs - Move to the binary's directory, becuase I don't even 
	// know where the working directory would be when you double-click
	// the .app bundle.
	char execPath[1024];
	unsigned int bufSize = 1023;
	int pos = 0;
	_NSGetExecutablePath(execPath, &bufSize);
	pos = (int)(strlen(execPath)) - 1;

	// Find the last forward slash.
	while(execPath[pos] != '/' && pos >= 0) {
		pos--;
	}
	
	// Cut it off
	if(pos >= 0) {
		execPath[pos] = 0;
	}

	// Go here.
	chdir(execPath);
	
	// Then take us back out of the Contents/MacOS directory.
	chdir("../..");
	
#endif

	setupConsole();
	setupArchives();
	
	for(int i = 1; i < argc; i++) {
		if(strcmp("--flushpoop", argv[i]) == 0) {
			dumpDir(".", 0, true);
		}
	}
	
	gameMain(argc, argv);

	return 0;
}

