// ---------------------------------------------------------------------------
// 
//   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 "../hacks/toolhacks.h"

#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>
#include <vector>
using namespace std;

#include "filesystem.h"
#include "archive.h"
using namespace FileSystem;

void invalidParams(const std::string &myName) {
	cout << "Usages:" << endl;
	cout << "  " << myName << " create <archive> <file> <file> <file> ..." << endl;
	cout << "  " << myName << " extract <archive> <file>" << endl;
	cout << "  " << myName << " list <archive>" << endl;
	cout << endl;
	
	exit(1);
}

string indent(int x) {
	ostringstream str;
	for(int i = 0; i < x; i++) {
		str << "  ";
	}
	return str.str();
}

int errorCount = 0;

void addFile(Archive *archive, const std::string &name, int indentLevel = 0) {
	
	string indentStr = indent(indentLevel);
		
	if(isDir(name)) {
		
		cout << indentStr << "Reading directory " << name << endl;
		
		vector<string> names;
		getAllFiles(name, names);
		
		for(int i = 0; i < names.size(); i++) {
			addFile(archive, name + "/" + names[i], indentLevel + 1);
		}
		
	} else {
		
		cout << indentStr << "Adding file " << name << " ...";
		
		string result = "done";
		
		int fileLen;
		char *fileData = loadFile(name, &fileLen);
		
		if(!fileData) {
			result = "FAIL";
			errorCount++;
		} else {
			archive->addFile(name, fileData, fileLen);
			delete[] fileData;
		}
		
		int spaceAmount = 79 - indentLevel * 2 - (int)name.size() - (int)result.size();
		while(spaceAmount > 0) {
			cout << " ";
			spaceAmount--;
		}
		
		cout << result << endl;
	}
	
}

int main(int argc, char *argv[]) {
	
	if(argc < 3) {
		invalidParams(argv[0]);
	}
	
	string command = argv[1];
	
	if(command == "list") {
		Archive arch(argv[2], false);
		
		if(arch.getFailed()) {
			cerr << "Could not open " << arch.getMyFileName() << endl;
			exit(1);
		}
		
		vector<string> fileList;
		arch.getFileList(fileList);
		
		for(unsigned int i = 0; i < fileList.size(); i++) {
			cout << fileList[i] << endl;
		}
		
	} else if(command == "create") {
		
		if(argc < 4) {
			cerr << "Not enough parameters for create" << endl;
			exit(1);
		}
		
		Archive arch(argv[2], true);
		if(arch.getFailed()) {
			cerr << "Failed to create " << arch.getMyFileName() << endl;
			exit(1);			
		}
		
		cout << "Created " << arch.getMyFileName() << endl;
		
		vector<string> fileList;
		for(int i = 3; i < argc; i++) {
			string newFileName = argv[i];
			
			newFileName = fixFileName(newFileName);
			
			addFile(&arch, newFileName);
		}
		
		if(errorCount) {
			cout << errorCount << " errors" << endl;
			exit(1);
		}
		
	} else if(command == "extract") {
		
		cerr << endl
			<< "=======================================================" << endl
			<< "==================       FIXME      ===================" << endl
			<< "=======================================================" << endl
			<< "Not implemented yet. Seriously, these are just supposed" << endl
			<< "to be one-way things. You put the data in the archives," << endl
			<< "then have your game read them. At no point should you"   << endl
			<< "store data assets in one of these things and expect to"  << endl
			<< "be able to actually retrieve them outside of being"      << endl
			<< "loaded in the project they're meant for." << endl << endl;
		
		exit(1);
	}
	
	return 0;
}
