// resource.cpp - Source to manage GUI resources

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/reboot.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>

#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>

extern "C" {
#include "../twcommon.h"
#include "../minuitwrp/minui.h"
}

#include "rapidxml.hpp"
#include "objects.hpp"

#define TMP_RESOURCE_NAME   "/tmp/extract.bin"

Resource::Resource(xml_node<>* node, ZipArchive* pZip)
{
	if (node && node->first_attribute("name"))
		mName = node->first_attribute("name")->value();
}

int Resource::ExtractResource(ZipArchive* pZip, std::string folderName, std::string fileName, std::string fileExtn, std::string destFile)
{
	if (!pZip)
		return -1;

	std::string src = folderName + "/" + fileName + fileExtn;

	const ZipEntry* binary = mzFindZipEntry(pZip, src.c_str());
	if (binary == NULL) {
		return -1;
	}

	unlink(destFile.c_str());
	int fd = creat(destFile.c_str(), 0666);
	if (fd < 0)
		return -1;

	int ret = 0;
	if (!mzExtractZipEntryToFile(pZip, binary, fd))
		ret = -1;

	close(fd);
	return ret;
}

FontResource::FontResource(xml_node<>* node, ZipArchive* pZip)
 : Resource(node, pZip)
{
	std::string file;
	xml_attribute<>* attr;

	mFont = NULL;
	if (!node)
		return;

	attr = node->first_attribute("filename");
	if (!attr)
		return;

	file = attr->value();

#ifndef TW_DISABLE_TTF
	if(file.size() >= 4 && file.compare(file.size()-4, 4, ".ttf") == 0)
	{
		m_type = TYPE_TTF;

		attr = node->first_attribute("size");
		if(!attr)
			return;

		int size = atoi(attr->value());
		int dpi = 300;

		attr = node->first_attribute("dpi");
		if(attr)
			dpi = atoi(attr->value());

		if (ExtractResource(pZip, "fonts", file, "", TMP_RESOURCE_NAME) == 0)
		{
			mFont = gr_ttf_loadFont(TMP_RESOURCE_NAME, size, dpi);
			unlink(TMP_RESOURCE_NAME);
		}
		else
		{
			file = std::string(TWRES "fonts/") + file;
			mFont = gr_ttf_loadFont(file.c_str(), size, dpi);
		}
	}
	else
#endif
	{
		m_type = TYPE_TWRP;

		if(file.size() >= 4 && file.compare(file.size()-4, 4, ".ttf") == 0)
		{
			attr = node->first_attribute("fallback");
			if (!attr)
				return;

			file = attr->value();
		}

		if (ExtractResource(pZip, "fonts", file, ".dat", TMP_RESOURCE_NAME) == 0)
		{
			mFont = gr_loadFont(TMP_RESOURCE_NAME);
			unlink(TMP_RESOURCE_NAME);
		}
		else
		{
			mFont = gr_loadFont(file.c_str());
		}
	}
}

FontResource::~FontResource()
{
	if(mFont)
	{
#ifndef TW_DISABLE_TTF
		if(m_type == TYPE_TTF)
			gr_ttf_freeFont(mFont);
		else
#endif
			gr_freeFont(mFont);
	}
}

ImageResource::ImageResource(xml_node<>* node, ZipArchive* pZip)
 : Resource(node, pZip)
{
	std::string file;

	mSurface = NULL;
	if (!node) {
		LOGERR("ImageResource node is NULL\n");
		return;
	}

	if (node->first_attribute("filename"))
		file = node->first_attribute("filename")->value();

	if (ExtractResource(pZip, "images", file, ".png", TMP_RESOURCE_NAME) == 0)
	{
		res_create_surface(TMP_RESOURCE_NAME, &mSurface);
		unlink(TMP_RESOURCE_NAME);
	}
	else if (ExtractResource(pZip, "images", file, "", TMP_RESOURCE_NAME) == 0)
	{
		// JPG includes the .jpg extension in the filename so extension should be blank
		res_create_surface(TMP_RESOURCE_NAME, &mSurface);
		unlink(TMP_RESOURCE_NAME);
	}
	else
		res_create_surface(file.c_str(), &mSurface);
}

ImageResource::~ImageResource()
{
	if (mSurface)
		res_free_surface(mSurface);
}

AnimationResource::AnimationResource(xml_node<>* node, ZipArchive* pZip)
 : Resource(node, pZip)
{
	std::string file;
	int fileNum = 1;

	if (!node)
		return;

	if (node->first_attribute("filename"))
		file = node->first_attribute("filename")->value();

	for (;;)
	{
		std::ostringstream fileName;
		fileName << file << std::setfill ('0') << std::setw (3) << fileNum;

		gr_surface surface;
		if (pZip)
		{
			if (ExtractResource(pZip, "images", fileName.str(), ".png", TMP_RESOURCE_NAME) != 0)
				break;

			if (res_create_surface(TMP_RESOURCE_NAME, &surface))
				break;

			unlink(TMP_RESOURCE_NAME);
		}
		else
		{
			if (res_create_surface(fileName.str().c_str(), &surface))
				break;
		}
		mSurfaces.push_back(surface);
		fileNum++;
	}
}

AnimationResource::~AnimationResource()
{
	std::vector<gr_surface>::iterator it;

	for (it = mSurfaces.begin(); it != mSurfaces.end(); ++it)
		res_free_surface(*it);

	mSurfaces.clear();
}

Resource* ResourceManager::FindResource(std::string name)
{
	std::vector<Resource*>::iterator iter;

	for (iter = mResources.begin(); iter != mResources.end(); iter++)
	{
		if (name == (*iter)->GetName())
			return (*iter);
	}
	return NULL;
}

ResourceManager::ResourceManager(xml_node<>* resList, ZipArchive* pZip)
{
	LoadResources(resList, pZip);
}

void ResourceManager::LoadResources(xml_node<>* resList, ZipArchive* pZip)
{
	xml_node<>* child;

	if (!resList)
		return;
	child = resList->first_node("resource");
	while (child != NULL)
	{
		xml_attribute<>* attr = child->first_attribute("type");
		if (!attr)
			break;

		Resource* res = NULL;
		std::string type = attr->value();
		if (type == "font")
		{
			res = new FontResource(child, pZip);
		}
		else if (type == "image")
		{
			res = new ImageResource(child, pZip);
		}
		else if (type == "animation")
		{
			res = new AnimationResource(child, pZip);
		}
		else
		{
			LOGERR("Resource type (%s) not supported.\n", type.c_str());
		}

		if (res == NULL || res->GetResource() == NULL)
		{
			std::string res_name;
			if (child->first_attribute("name"))
				res_name = child->first_attribute("name")->value();
			if (res_name.empty() && child->first_attribute("filename"))
				res_name = child->first_attribute("filename")->value();

			if (!res_name.empty()) {
				LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str());
			} else
				LOGERR("Resource type (%s) failed to load\n", type.c_str());

			delete res;
		}
		else
		{
			mResources.push_back(res);
		}

		child = child->next_sibling("resource");
	}
}

ResourceManager::~ResourceManager()
{
	std::vector<Resource*>::iterator iter;

	for (iter = mResources.begin(); iter != mResources.end(); iter++)
		delete *iter;

	mResources.clear();
}
