/*
 * See the files COPYING and README for copyright information and how to reach 
 * the author.
 *
 *  $Id: common.c,v 1.11 2006/04/24 19:43:37 lordjaxom Exp $
 */

#include "common.h"
#include "setup.h"
#include "boost/bind.hpp"
#include "proctools/format.h"
#include "proctools/logger.h"//XXX
#include <sstream>
#include <string>
#include <iterator>
#include <algorithm>
#include <iomanip>
#include <ctime>
#include <vdr/recording.h>
#include <sys/types.h>
#include <glob.h>

namespace vdr_burn
{

	using namespace std;
	using boost::bind;
	using proctools::format;
	using proctools::logger;//XXX

	namespace disk_type
	{
		const char* strings[count] = 
			{ "DVD with menus", "DVD without menus", "Archive disk" };
	}

	namespace disk_size
	{
		const char* strings[count] = 
			{ "Single Layer", "Double Layer", "CD-R", "Custom" };
	}

	namespace demux_type
	{
		const char* strings[count] = 
			{ "VDRSync", "ProjectX" };
	}

	string track_info::get_type_description(void) const
	{
		string result = "Unknown";
		switch (type) {
			case video:      result = tr("Video track"); break;
			case mpeg_audio: result = format(tr("Audio track ({0})")) 
									  % "MPEG1 layer 2"; break;
			case ac3_audio:  result = format(tr("Audio track ({0})")) 
									  % "AC3"; break;
			default:         break;
		}
		return result;
	}

const char *StoreModes[sm_Count]    = { "Create ISO only", "Write to Disc", 
										"Create ISO and write" };
const char *ChaptersModes[cm_Count] = { "No chapters", "Use editing marks", 
										"Every 5 minutes", "Every 10 minutes", 
										"Every 15 minutes", "Every 30 minutes", 
										"Every hour" };

const char *TitleChars = "abcdefghijklmnopqrstuvwxyz"
						 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
						 "0123456789"
						 "äöüÄÖÜß:- ";

int ScanPageCount(const std::string& Path) 
{
	cString path = AddDirectory(Path.c_str(), "menu-bg-*.png");
	glob_t globbuf;
	int res;

	if ((res = glob(path, 0, NULL, &globbuf)) != 0) {
		const char *error = "Unknown error";

		switch (res) {
			case GLOB_NOSPACE: error = "Out of memory"; break;
			case GLOB_ABORTED: error = "I/O error"; break;
			case GLOB_NOMATCH: error = "File not found"; break;
		}

		esyslog("ERROR[burn]: Error while scanning %s: %s", *path, error);
		return -1;
	}

	res = globbuf.gl_pathc;
	globfree(&globbuf);
	return res;
}

std::string progress_bar(double current, double total, int length) 
{
	if (length < 2)
		return "";

	if (current > total)
		current = total;

	int l = static_cast<int>(current * (length - 2) / total);
	ostringstream builder;

	builder << '[';
	fill_n(ostream_iterator<char>(builder), l, '|');
	fill_n(ostream_iterator<char>(builder), length - 2 - l, ' ');
	builder << ']';
	return builder.str();
}

string escape_iso_to_utf8(const string& Text) 
{
	stringstream result;
	for (const uchar *in = reinterpret_cast<const uchar*>(Text.c_str()); 
		 *in; ++in) {
		if (BurnSetup.UseIso2UTF && *in >= 0x80)
			result << static_cast<char>( ((*in >> 6) & 0x1F) | 0xC0 )
				   << static_cast<char>( (*in & 0x3F) | 0x80 );
		else if (*in == '-') {
			if (BurnSetup.UseIso2UTF)
				result << static_cast<char>( 0xe2 )
					   << static_cast<char>( 0x80 )
					   << static_cast<char>( 0x93 );
			else
				result << '_';//XXX
		}
		else if (*in == 0x09)
			result << ' ';
		else
			result << static_cast<char>(*in);
	}
	return result.str();
}

void trim_left(char *Text, const char *Chars)
{
	char *tmp = Text, *ptr;
	do {
		ptr = tmp;
		while (strchr(Chars, *ptr) != NULL)
			++ptr;
		memmove(tmp, ptr, strlen(ptr) + 1);
		if ((tmp = strchr(tmp, '~')) != NULL)
			++tmp;
	} while (tmp != NULL);
}

string get_recording_datetime(const cRecording* recording_, char delimiter)
{
	string title = recording_->Title('\t', false, -1);

	string::iterator it = title.begin();
	for (int i = 0; i < 2 && it != title.end(); ++i)
		it = find(it + 1, title.end(), '\t');

	title.erase(it, title.end());
	if (title[title.length() - 1] == ' ')
		title.erase(title.length() - 1);
	if (delimiter != '\t')
		replace(title.begin(), title.end(), '\t', delimiter);
	return title;
}

string get_recording_title(const cRecording* recording_, int level)
{
	stringstream result;
	string name( recording_->Name() );
	
	if (level == recording_->HierarchyLevels()) {
		string::size_type pos;
		if ((pos = name.find('~')) != string::npos)
			name.erase(0, pos + 1);

		result << get_recording_datetime(recording_)
			   << (recording_->IsNew() ? '*' : ' ') << '\t'
			   << name;
		return result.str();
	}

	string::size_type lastOffset = 0;
	string::size_type offset;
	while ((offset = name.find('~', lastOffset)) != string::npos) {
		if (level-- == 0)
			break;
		lastOffset = offset + 1;
	}
	result << "\t\t" << name.substr(lastOffset, offset - lastOffset);
	return result.str();
}

/*string strip_recording_title(const cRecording* recording_, char separator,
							 bool newIndicator, int level)
{
	string title = recording_->Title('\t', newIndicator, level);
	string::size_type pos;

	if ((pos = title.rfind('\t')) != string::npos) {
		title[pos] = separator;
		if (level == -1) { // TODO too much internal knowledge
			string::size_type tabpos;
			while ((tabpos = title.find('\t')) < pos)
				title.replace(tabpos, 1, " ");
		}
	}
	return title;
}*/

string escape_shellcmd(const string& command)
{
	string result(command);
	replace(result.begin(), result.end(), '/', '_');
	return result;
}

bool elapsed_since(time_t& timestamp, time_t difference)
{
	time_t now = time(NULL);
	if (timestamp + difference <= now) {
		timestamp = now;
		return true;
	}
	return false;
}

string int_to_string(int value, int base, bool prefix)
{
	stringstream conv;
	if (prefix) {
		switch (base) {
		case 2: conv << "0b"; break;
		case 8: conv << "0"; break;
		case 16: conv << "0x"; break;
		}
	}
	conv << setbase(base) << value;

	string result;
	conv >> result;
	return result;
}

}
