<%pre>

#include <setup.h>
#include <tasks.h>
#include <tools.h>
#include <users.h>
#include <recman.h>
#include <tntconfig.h>

#ifdef HAVE_LIBPCRECPP
#include <pcrecpp.h>
#endif

#include <vdr/videodir.h>

#define MB_PER_MINUTE 25.75 // this is just an estimate!
#include <string>
std::string argList;
std::string recoring_item;
size_t max_length_recoring_item = 0;

using namespace vdrlive;

</%pre>
<%args>
	std::string sort;
	std::string todel;
	std::string diskinfo;
	std::string filter;
	std::string deletions[];
        std::string flat;
</%args>
<%session scope="global">
	bool logged_in(false);
</%session>

<# scope="page" should be enough but does not work with tntnet 3.0 #>
<%request scope="global">
	std::string currentSort;
	std::string deleteResult;
	std::string currentFilter;
	std::string currentFlat;
</%request>

<%include>page_init.eh</%include>
<%cpp>
if (!logged_in && LiveSetup().UseAuth()) return reply.redirect("login.html");

// sort dpends on old sort, an sort parameter
currentSort = LiveSetup().GetLastSortingMode();
if (currentSort.empty() ) currentSort = "nameasc";
if (!sort.empty()) {
	if (sort == "date")
		currentSort = (currentSort == "dateasc") ? "datedesc" : "dateasc";
	else if (sort == "name")
		currentSort = (currentSort == "nameasc") ? "namedesc" : "nameasc";
	else if (sort == "errors")
                currentSort = (currentSort == "errorsasc") ? "errorsdesc" : "errorsasc";
	else if (sort == "duplicates")
		currentSort = sort;
	LiveSetup().SetLastSortingMode(currentSort);
}
// flat defaults from sort, but can we overwritten
if (currentSort == "errorsasc" || currentSort == "errorsdesc" || currentSort == "duplicates") currentFlat = "true";
  else currentFlat = "false";
if (! flat.empty() ) currentFlat = flat;

currentFilter = filter;

pageTitle = tr("Recordings");

deleteResult = "";
if (!todel.empty()) {
	if (!cUser::CurrentUserHasRightTo(UR_DELRECS))
		throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") );
	deletions.push_back(todel);
}
#if TNTVERSION >= 30000
typedef std::vector<std::string> deletions_type;
#endif
for (deletions_type::const_iterator it = deletions.begin(); it != deletions.end(); ++it) {
	if (cUser::CurrentUserHasRightTo(UR_DELRECS)) {
		RemoveRecordingTask task(*it);
		LiveTaskManager().Execute(task);
		if (!task.Result())
			deleteResult += std::string() + tr("ERROR:") + " " + task.Error() + "<br/>";
		else
			deleteResult += std::string() + tr("Deleted recording:") + " " + StringReplace(task.RecName(), "~", "/") + "<br/>";
	}
	else {
		throw HtmlError( tr("Sorry, no permission. Please contact your administrator!") );
	}
}
deletions.clear();

int FreeMB, UsedMB;
#if APIVERSNUM > 20101
int Percent = cVideoDirectory::VideoDiskSpace(&FreeMB, &UsedMB);
#else
int Percent = VideoDiskSpace(&FreeMB, &UsedMB);
#endif
int Minutes = int(double(FreeMB) / MB_PER_MINUTE);
int Hours = Minutes / 60;
Minutes %= 60;
diskinfo = cString::sprintf("%s %d%%  -  %2d:%02d %s", trVDR("Disk"), Percent, Hours, Minutes, trVDR("free"));
</%cpp>
<& pageelems.doc_type &>
<html>
	<head>
		<title>VDR-Live - <$ pageTitle $></title>
		<& pageelems.stylesheets &>
		<& pageelems.ajax_js &>
		<script type="text/javascript" src="treeview.js"></script>
		<script type="text/javascript"><!--
		function filterRecordings(filter)
		{
			window.location.href = "recordings.html?sort=<$ currentSort $>&filter=" + encodeURIComponent(filter.value);
		}
		function ExpandAll()
		{
			var openNodes = "";
			recordingNodes = window.document.getElementsBySelector("ul.recordingslist");
			for (idx = 0; idx < recordingNodes.length; idx++) {
				if (recordingNodes[idx].parentNode.className != 'recordings') {
					recordingNodes[idx].style.display = 'block';
					openNodes += recordingNodes[idx].id + ","; 
				}
			}
			expandNodes = window.document.getElementsBySelector("img.recording_expander");
			for (idx = 0; idx < expandNodes.length; idx++) {
				expandNodes[idx].src = "img/minus.png";
			}
			folderNodes = window.document.getElementsBySelector("img.recording_folder");
			for (idx = 0; idx < folderNodes.length; idx++) {
				folderNodes[idx].src = "img/folder_open.png";
			}
			createCookie( cookieNameRec, openNodes, 14 );
		}
		function CollapseAll()
		{
			recordingNodes = window.document.getElementsBySelector("ul.recordingslist");
			for (idx = 0; idx < recordingNodes.length; idx++) {
				if (recordingNodes[idx].parentNode.className != 'recordings') {
					recordingNodes[idx].style.display = 'none';
				}
			}
			expandNodes = window.document.getElementsBySelector("img.recording_expander");
			for (idx = 0; idx < expandNodes.length; idx++) {
				expandNodes[idx].src = "img/plus.png";
			}
			folderNodes = window.document.getElementsBySelector("img.recording_folder");
			for (idx = 0; idx < folderNodes.length; idx++) {
				folderNodes[idx].src = "img/folder_closed.png";
			}
			eraseCookie( cookieNameRec );
		}
		//--></script>
	</head>
	<body onload="adjustHeader()" onresize="adjustHeader()">
		<& pageelems.logo &>
<%cpp>
if (!deleteResult.empty()) {
</%cpp>
		<& menu active=("recordings") component=("recordings.delete_error") &>
<%cpp>
} else {
</%cpp>
		<& menu active=("recordings") component=("recordings.sort_options") &>
<%cpp>
}
</%cpp>
		<div class="inhalt">
			<div class="boxheader"><div><div><$ std::string(tr("List of recordings")) + " (" + diskinfo + ")" $></div></div></div>
<%cpp>
#if VDRVERSNUM >= 20301
			int rec_cnt;
			{
				LOCK_RECORDINGS_READ;
				rec_cnt = Recordings->Count();  // Access VDRs global cRecordings Recordings instance.
			}
			if (rec_cnt == 0) {
#else
			if (Recordings.Count() == 0) { // Access VDRs global cRecordings Recordings instance.
#endif
</%cpp>
			<$ tr("No recordings found") $>
<%cpp>
			} else {
</%cpp>
			<form method="post" name="recordings" action="recordings.ecpp">
			<div class="recordings">
			<ul class="recordingslist" style="display: block;">
<& recordings.recordings_item filter=(currentFilter) &>
			</ul>
			</div>
			<div class="withmargin">
				<button class="red" type="submit"><$ tr("Delete selected") $></button>
			</div>
			</form>
<%cpp>
			}
</%cpp>
		</div>
	</body>
</html>
<%include>page_exit.eh</%include>

<# ---------------------------------------------------------------------- #>

<%def recordings_item>
<%args>
	filter;
	path[];
	int level = 0;
	int counter = 0;
	std::string idHash = "";
</%args>
<%cpp>
recoring_item.reserve(6000);
// Max Buffer used: 5.636 bytes
RecordingsTreePtr recordingsTree(LiveRecordingsManager()->GetRecordingsTree());
std::list<RecordingsItemPtr> recItems;
std::list<RecordingsItemPtr>::iterator recIter;
if( currentFlat != "true" ) {
RecordingsMap::iterator iter;
RecordingsMap::iterator end = recordingsTree->end(path);

for (iter = recordingsTree->begin(path); iter != end; ++iter) {
	RecordingsItemPtr recItem = iter->second;
	if (recItem->IsDir()) {
		recItems.push_back(recItem);
	}
}
if (currentSort == "namedesc")
	recItems.sort(RecordingsItemPtrCompare::ByDescendingNameDescSort);
else if (currentSort == "nameasc")
	recItems.sort(RecordingsItemPtrCompare::ByAscendingNameDescSort);
for (recIter = recItems.begin(); recIter != recItems.end(); ++recIter) {
	RecordingsItemPtr recItem = *recIter;
	counter++;

	/* search trough directory for new recordings */
        bool newR = false;
	if ( LiveSetup().GetMarkNewRec() ) {
           std::vector<std::string> p(path); 
	   p.push_back(recItem->Name()); 
	   newR = checkNew(recordingsTree, p);; 
        }
</%cpp>
	<li class="recording">
	<& rec_item_dir name=(recItem->Name()) level=(recItem->Level() ) newR=(newR ? "_new" : "") &>
<%cpp>
#if TNT_QUERYPARAMS_NO_BOOL
		tnt::QueryParams recItemParams(qparam);
#else
		tnt::QueryParams recItemParams(qparam, false);
#endif
#if TNTVERSION >= 30000
                typedef std::vector<std::string> path_type;
#endif
		for (path_type::const_iterator i = path.begin(); i != path.end(); ++i) {
			recItemParams.add("path", *i);
		}
#if TNTVERSION >= 30000
		recItemParams.add("path[]", recItem->Name());
#else
		recItemParams.add("path", recItem->Name());
#endif
		recItemParams.add("level", lexical_cast<std::string, int>(level + 1));
		recItemParams.add("filter", filter);
		std::string combinedId = recItem->Name() + "_";
		combinedId += counter + "_" + level;
		idHash = MD5Hash(combinedId);
</%cpp>
		<ul id="fldr_<$ idHash $>" class="recordingslist" style="display: none;">
<%cpp>
		callComp("recordings.recordings_item", request, reply, recItemParams);
</%cpp>
		</ul>
	</li>
<%cpp>
}
recItems.clear();
for (iter = recordingsTree->begin(path); iter != end; ++iter) {
	RecordingsItemPtr recItem = iter->second;
	if (!recItem->IsDir()) {
		recItems.push_back(recItem);
	}
}
} else {
if (currentSort == "duplicates") {
  addAllDuplicateRecordings(recItems, recordingsTree);
} else {
  addAllRecordings(recItems, recordingsTree, path);
}
}
if (currentSort == "dateasc")
	recItems.sort(RecordingsItemPtrCompare::ByAscendingDate);
else if (currentSort == "datedesc")
	recItems.sort(RecordingsItemPtrCompare::ByDescendingDate);
else if (currentSort == "namedesc")
	recItems.sort(RecordingsItemPtrCompare::ByDescendingNameDescSort);
else if (currentSort == "nameasc")
	recItems.sort(RecordingsItemPtrCompare::ByAscendingNameDescSort);
else if (currentSort == "errorsasc" || currentSort == "errorsdesc")
	recItems.sort(RecordingsItemPtrCompare::ByDescendingRecordingErrors);

argList.clear();
argList.append("&sort=");
argList.append(currentSort);
argList.append("&filter=");
argList.append(currentFilter);
for (recIter = recItems.begin(); recIter != recItems.end(); ++recIter) {
		RecordingsItemPtr recItem = *recIter;
  recoring_item.clear();
  recItem->AppendasHtml(recoring_item, currentFlat == "true", argList);
  max_length_recoring_item = std::max(max_length_recoring_item, recoring_item.length() );
#ifdef HAVE_LIBPCRECPP
		pcrecpp::RE re(filter.c_str(), pcrecpp::UTF8().set_caseless(true));
		if (filter.empty() || re.PartialMatch(recItem->Name()) || re.PartialMatch(recItem->ShortText()?recItem->ShortText() : "" ) || re.PartialMatch(recItem->Description()?recItem->Description() : ""))
#endif
		{
</%cpp>
  <$$ recoring_item $>
  <# Buffer used: <$ recoring_item.length() $> bytes
  Max Buffer used: <$ max_length_recoring_item $> bytes #>
<%cpp>
		}
}
</%cpp>
</%def>

<# ---------------------------------------------------------------------- #>

<%def sort_options>
<%cpp> { </%cpp>
<a href="recordings.html?sort=name&filter=<? currentFilter != "" ? currentFilter ?>" /><$ tr("Sort by name") $></a>
<span class="sep">|</span>
<a href="recordings.html?sort=date&filter=<? currentFilter != "" ? currentFilter ?>" /><$ tr("Sort by date") $></a>
<span class="sep">|</span>
<a href="recordings.html?sort=duplicates&filter=<? currentFilter != "" ? currentFilter ?>" /><$ tr("Duplicates") $></a>
<%cpp>
#if VDRVERSNUM >= 20505
</%cpp>
<span class="sep">|</span>
<a href="recordings.html?sort=errors&filter=<? currentFilter != "" ? currentFilter ?>" /><$ tr("Errors") $></a>
<%cpp>
#endif
#ifdef HAVE_LIBPCRECPP
</%cpp>
<span class="sep">|</span>
<span class="label bold"><$ tr("Filter") $>:&nbsp;<input type="text" name="filter" value="<$ currentFilter $>" id="filter" onchange="filterRecordings(this)" />&nbsp;<& tooltip.help text=(tr("Look in recordings titles and subtitles for the given string and display only the matching ones. You may also use perl compatible regular expressions (PCRE).")) &></span>
<%cpp>
#endif
</%cpp>
<span class="sep">|</span>
<img onclick="ExpandAll()" src="<$ LiveSetup().GetThemedLink("img", "plus.png") $>" alt="" <& tooltip.hint text=(tr("Expand all folders")) &>/>
<img onclick="CollapseAll()" src="<$ LiveSetup().GetThemedLink("img", "minus.png") $>" alt="" <& tooltip.hint text=(tr("Collapse all folders")) &>/>
<br />
<%cpp> } </%cpp>
</%def>

<# ---------------------------------------------------------------------- #>

<%def del_rec>
<%args>
	std::string id;
</%args>
<%cpp> { </%cpp><a href="recordings.html?todel=<$ id $>" <& tooltip.hint text=(tr("Delete this recording from hard disc!")) &>><img src="<$ LiveSetup().GetThemedLink("img", "del.png") $>" alt="" /></a><%cpp> } </%cpp>
</%def>

<# ---------------------------------------------------------------------- #>

<%def edit_rec>
<%args>
	std::string id;
</%args>
<%cpp> { </%cpp><a href="edit_recording.html?recid=<$ id $>"><img src="<$ LiveSetup().GetThemedLink("img", "edit.png") $>" alt="" <& tooltip.hint text=(tr("Edit recording")) &> /></a><%cpp> } </%cpp>
</%def>

<# ---------------------------------------------------------------------- #>


<%def rec_tools>
<%args>
	std::string id;
	std::string title;
</%args>
<& pageelems.ajax_action_href action="play_recording" param=(id) tip=(tr("play this recording.")) image="play.png" alt="" &>
<& pageelems.m3u_playlist_recording recid=(id) &>
<& pageelems.imdb_info_href title=(title) &>
<& recordings.edit_rec id=(id) &>
<& recordings.del_rec id=(id) &>
</%def>

<# ---------------------------------------------------------------------- #>

<%def archived_disc>
<%args>
	std::string archived;
	std::string title;
</%args>
<img src="<$ LiveSetup().GetThemedLink("img", "on_dvd.png") $>" alt="on_dvd" <& tooltip.hint text=(archived) &> />
<& pageelems.imdb_info_href title=(title) &>
</%def>

<# ---------------------------------------------------------------------- #>

<%def rec_item_dir>
<%args>
  std::string name;
  int level;
  std::string newR;
</%args>
  <div class="recording_item" onclick="Toggle(this)">
    <div class="recording_imgs">
      <{ if(level > 1) { }><img src="img/transparent.png" width="<$16*(level-1) $>px" height="16px" /> <{ } }>
      <img class="recording_expander" src="<$ LiveSetup().GetThemedLinkPrefixImg()$>plus.png" /><img class="recording_folder" src="<$ LiveSetup().GetThemedLinkPrefixImg()$>folder_closed.png" /></div>
    <div class="recording_spec">
      <div class="recording_name<$ newR $>"><$ name $></div>
    </div>
    <div class="recording_actions">&nbsp;</div>
  </div>
</%def>

<# ---------------------------------------------------------------------- #>

<%def delete_error>
<& recordings.sort_options &>
<%cpp> { reply.out() << deleteResult; } </%cpp>
</%def>
