//
// Created by Иван_Архипов on 30.10.2017.
//
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <windows.h>
#include <ctime>

#include "LotroDatPatcher.h"
using namespace LOTRO_DAT;


int main() {
    const clock_t begin_time = clock();

	// Change these 2 variables to your path and name of .dat file
    std::string path = "E:\\SteamLibrary\\steamapps\\common\\Lord of the Rings Online\\";
    std::string filename = "client_highres.dat";

    bool exportTextsToFiles = false; // Not implemented yet - do not turn to true;
    bool exportImagesToFiles = true;
    bool exportFontsToFiles = false; // Not implemented yet - do not turn to true;
    bool exportSoundsToFiles = false;
    bool exportTexturesToFiles = true;
    bool exportUnknownToFiles = false; // Not implemented yet - do not turn to true;

    bool exportTextsToDb = false; // Not implemented yet - do not turn to true;
    bool exportImagesToDb = false;
    bool exportFontsToDb = false; // Not implemented yet - do not turn to true;
    bool exportSoundsToDb = false;
    bool exportTexturesToDb = false;
    bool exportUnknownToDb = false; // Not implemented yet - do not turn to true;

	// There is no need to touch something else

	std::string output_dir = std::string("Data (") + filename + std::string(")\\");
    //freopen((output_dir + std::string("errors.log")).c_str(), "w", stderr);

	std::string txt_dir = "txt\\";
	std::string jpg_dir = "jpg\\";
	std::string dds_dir = "dds\\";
	std::string wav_dir = "wav\\";
	std::string ogg_dir = "ogg\\";
	std::string font_dir = "font\\";
	std::string unk_dir = "unk\\";

	int txt_all = 0, txt_suc = 0;
	int jpg_all = 0, jpg_suc = 0;
	int dds_all = 0, dds_suc = 0;
	int wav_all = 0, wav_suc = 0;
	int ogg_all = 0, ogg_suc = 0;
	int font_all = 0, font_suc = 0;
	int unk_all = 0, unk_suc = 0;

	CreateDirectory(output_dir.c_str(), nullptr);
	CreateDirectory((output_dir + txt_dir).c_str(), nullptr);
	CreateDirectory((output_dir + jpg_dir).c_str(), nullptr);
	CreateDirectory((output_dir + dds_dir).c_str(), nullptr);
	CreateDirectory((output_dir + wav_dir).c_str(), nullptr);
	CreateDirectory((output_dir + ogg_dir).c_str(), nullptr);
	CreateDirectory((output_dir + font_dir).c_str(), nullptr);
	CreateDirectory((output_dir + unk_dir).c_str(), nullptr);

    Database *images = nullptr;
    Database *sounds = nullptr;
    Database *texts = nullptr;
    Database *fonts = nullptr;
    Database *textures = nullptr;
    Database *unknown = nullptr;

    if (exportImagesToDb) images = new Database(output_dir + std::string("Images.db"));
    if (exportSoundsToDb) sounds = new Database(output_dir + std::string("Sounds.db"));
    if (exportTextsToDb) texts = new Database(output_dir + std::string("Texts.db"));
    if (exportFontsToDb) fonts = new Database(output_dir + std::string("Fonts.db"));
    if (exportTexturesToDb) textures = new Database(output_dir + std::string("Textures.db"));
    if (exportUnknownToDb) unknown = new Database(output_dir + std::string("Unknown.db"));

	std::cout << "Starting search...\n";
	DatFile a(path + filename);
    std::cout << "Total files found: " << a.dictionary().size() << std::endl;

	std::cout << "Writing unordered dictionary:\n";
	FILE *f;
	fopen_s(&f, (output_dir + "dict.txt").c_str(), "w");
	fprintf(f, "file_id offset size size2 extension\n");
	for (auto i : a.dictionary()) {
		std::string extension = "unk";
		EXTENSION ext = i.second->ext();
		if (ext == TXT) extension = "txt";
		if (ext == JPG) extension = "jpg";
		if (ext == DDS) extension = "dds";
		if (ext == WAV) extension = "wav";
		if (ext == OGG) extension = "ogg";
		if (ext == FONT) extension = "font";
		fprintf(f, "%lld %lld %lld %lld %s\n", i.second->file_id(), i.second->file_offset()
                , i.second->file_size(), i.second->block_size(), extension.c_str());
	}
	fclose(f);
	
	std::cout << "Beginning unpacking...\n";

	long long all = a.dictionary().size();
	long long counter = 0;
    
	for (auto i : a.dictionary())
    {
		EXTENSION ext = i.second->ext();
        if (ext == TXT) {
        	txt_all++;
            if (exportTextsToDb) txt_suc += i.second->ExportFile((output_dir + txt_dir + std::to_string(i.second->file_id())).c_str(), texts);
            if (exportTextsToFiles) txt_suc += i.second->ExportFile((output_dir + txt_dir + std::to_string(i.second->file_id())).c_str());
        }

        if (ext == JPG) {
            jpg_all++;
            if (exportImagesToDb) jpg_suc += i.second->ExportFile((output_dir + jpg_dir + std::to_string(i.second->file_id())).c_str(), images);
            if (exportImagesToFiles) jpg_suc += i.second->ExportFile((output_dir + jpg_dir + std::to_string(i.second->file_id())).c_str());
        }

        if (ext == DDS) {
            dds_all++;
            if (exportTexturesToDb) dds_suc += i.second->ExportFile((output_dir + dds_dir + std::to_string(i.second->file_id())).c_str(), textures);
            if (exportTexturesToFiles) dds_suc += i.second->ExportFile((output_dir + dds_dir + std::to_string(i.second->file_id())).c_str());
        }

        if (ext == WAV) {
            wav_all++;
            if (exportSoundsToDb) wav_suc += i.second->ExportFile((output_dir + wav_dir + std::to_string(i.second->file_id())).c_str(), sounds);
            if (exportSoundsToFiles) wav_suc += i.second->ExportFile((output_dir + wav_dir + std::to_string(i.second->file_id())).c_str());
        }

        if (ext == OGG) {
            ogg_all++;
            if (exportSoundsToDb) ogg_suc += i.second->ExportFile((output_dir + ogg_dir + std::to_string(i.second->file_id())).c_str(), sounds);
            if (exportSoundsToFiles) ogg_suc += i.second->ExportFile((output_dir + ogg_dir + std::to_string(i.second->file_id())).c_str());
        }

        if (ext == FONT) {
            font_all++;
            if (exportFontsToDb) font_suc += i.second->ExportFile((output_dir + font_dir + std::to_string(i.second->file_id())).c_str(), fonts);
            if (exportFontsToFiles) font_suc += i.second->ExportFile((output_dir + font_dir + std::to_string(i.second->file_id())).c_str());
        }

        if (ext == UNKNOWN)
        {
            unk_all++;
            if (exportUnknownToDb) unk_suc += i.second->ExportFile((output_dir + unk_dir + std::to_string(i.second->file_id())).c_str(), unknown);
            if (exportUnknownToFiles) unk_suc += i.second->ExportFile((output_dir + unk_dir + std::to_string(i.second->file_id())).c_str());
        }

		counter++;
		if ((counter - 1) * 100ll / all != counter * 100ll / all) {
			fprintf(stdout, "Done: %lld%%\n", counter * 100ll / all);
		}
    }

	delete images;
    delete sounds;
    delete texts;
    delete fonts;
    delete textures;
    delete unknown;

	std::cout << "Total found:" << std::endl;
	std::cout << "Txt: " << txt_all << std::endl
		<< "JPG: " << jpg_all << std::endl
		<< "DDS: " << dds_all << std::endl
		<< "WAV: " << wav_all << std::endl
		<< "OGG: " << ogg_all << std::endl
		<< "Fonts " << font_all << std::endl
		<< "Unknown: " << unk_all << std::endl;

	std::cout << "Total exported (counted both to files and databases):" << std::endl;
	std::cout << "Txt: " << txt_suc << std::endl
		<< "JPG: " << jpg_suc << std::endl
		<< "DDS: " << dds_suc << std::endl
		<< "WAV: " << wav_suc << std::endl
		<< "OGG: " << ogg_suc << std::endl
		<< "Fonts " << font_suc << std::endl
		<< "Unknown: " << unk_suc << std::endl;

	fprintf(stdout, "Spent %f seconds on running unpacker! Thank you for your patience!\n", float(clock() - begin_time) / CLOCKS_PER_SEC);
	system("pause");
	return 0;
}