/*
 * xml2cEvent.h: Converting xml-files from the web to cEvents
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id$
 */

#include <string>
#include <stdio.h>
#include <iostream>
#include <zlib.h>
#include <vdr/epg.h>
#include <vdr/channels.h> //EW
#include "xml2cEvent.h"
//#include "dbgtools.h"

using namespace std;

string HTMLExps[15][2] = {{"&amp;","&"},{"<b>",""},{"</b>",""},{"<br/>","\n"},{"&auml;","ä"},{"&ouml;","ö"},{"&uuml;","ü"},{"&szlig;","ß"},{"&apos;","'"},{"&quot;","\""},{"&#196;","Ä"},{"&#214;","Ö"},{"&#220;","Ü"},{"&#233;","é"},{"&#186;","°"}};


string ReplaceHTMLExps(string str){
  for(int i = 0; i < 15; i++){
    int j = 0;
    while((j < (int)str.length())&&(j>-1)){
      j = str.find(HTMLExps[i][0]);
      if (j > -1){
        str.erase(j, HTMLExps[i][0].length());
        str.insert(j, HTMLExps[i][1]);
      }
    }
  }
  return str;
};

int cEvents::FromXMLFile(const char *cfile){
  int result = 1;
  gzFile xmlfile = gzopen(cfile, "rb");
  if(xmlfile == NULL)
    result = 0;
  else{
    char buffer[2000];
    while(gzgets(xmlfile, buffer, 2000)){
      string bufstr = buffer;
      int pos = bufstr.find("<programme ");
      if(pos >= 0){
        NumberOfEvents++;
        Events.push_back(cEv());
        string tmpstr = bufstr;
        tmpstr.erase(0, tmpstr.find("startutc=\"") + 10);
        tmpstr.erase(tmpstr.find("\""), tmpstr.length() - 1);
        Events[NumberOfEvents-1].StartTime = atoi(tmpstr.c_str());
        tmpstr = bufstr;
        tmpstr.erase(0, tmpstr.find("duration=\"") + 10);
        tmpstr.erase(tmpstr.find("\""), tmpstr.length() - 1);
        Events[NumberOfEvents-1].Duration = atoi(tmpstr.c_str());
        tmpstr = bufstr;
        tmpstr.erase(0, tmpstr.find("eventid=\"") + 9);
        tmpstr.erase(tmpstr.find("\""), tmpstr.length() - 1);
        Events[NumberOfEvents-1].EventID = atoi(tmpstr.c_str());
        pos = bufstr.find("</programme>");
        string desc = "";
        while(pos == -1){
          gzgets(xmlfile, buffer, 2000);
          bufstr = buffer;
          pos = bufstr.find("<title>");
          if(pos >= 0){
            bufstr.erase(0, bufstr.find("<title>") + 7);
            bufstr.erase(bufstr.find("</title>"), bufstr.length() - 1);
            bufstr = ReplaceHTMLExps(bufstr);
            Events[NumberOfEvents-1].Title = (char *)malloc(bufstr.length()*(sizeof(char)+1));
            strncpy(Events[NumberOfEvents-1].Title, bufstr.c_str(), bufstr.length()+1);
          }
          pos = bufstr.find("<sub-title>");
          if(pos >= 0){
            bufstr.erase(0, bufstr.find("<sub-title>") + 11);
            bufstr.erase(bufstr.find("</sub-title>"), bufstr.length() - 1);
            bufstr = ReplaceHTMLExps(bufstr);
            Events[NumberOfEvents-1].ShortText =(char *)malloc(bufstr.length()*(sizeof(char)+1));
            strncpy(Events[NumberOfEvents-1].ShortText, bufstr.c_str(), bufstr.length()+1);
          }
          pos = bufstr.find("<desc>");
          if(pos >= 0){
            bufstr.erase(0, bufstr.find("<desc>") + 6);
            desc += bufstr;
            int end = bufstr.find("</desc>");
            while(end < 0){
              gzgets(xmlfile, buffer, 2000);
              bufstr = buffer;
              int rpos = desc.rfind("\n");
              if(rpos >= 0)
                desc.erase(rpos, desc.length() - 1);
              desc += "\n";
              desc += bufstr;
              end = bufstr.find("</desc>");
            }
            desc.erase(desc.find("</desc>"), desc.length() - 1);
            desc = ReplaceHTMLExps(desc);
            if(desc.length() > 0){
              Events[NumberOfEvents-1].Description = (char *)malloc(desc.length()*(sizeof(char)+1));
              strncpy(Events[NumberOfEvents-1].Description, desc.c_str(), desc.length()+1);
            }
          }
          pos = bufstr.find("<vps>");
          if(pos >= 0){
            bufstr.erase(0, bufstr.find("<vps>") + 5);
            bufstr.erase(bufstr.find("</vps>"), bufstr.length() - 1);
            if (bufstr != "")
              Events[NumberOfEvents-1].VPS = atoi(bufstr.c_str());
          }
          pos = bufstr.find("</programme>");
        }
      }
    }
    gzclose(xmlfile);
  }
  return result;
};

//EW
bool cEvents::feedEpg(/*int Source, int Transponder, unsigned short ServiceID, int days*/)
{
	if (DebugLevel >= 4)
		cout << "webepg: feedEpg()\n";
	
	cSchedulesLock SchedulesLock(true,1000);
	cSchedules *Schedules=(cSchedules *)cSchedules::Schedules(SchedulesLock);
	
	if (DebugLevel >= 4)
		cout << "webepg: Have Schedules\n";
	
	cChannel* channel = Channels.GetByServiceID(Channel.Source, Channel.Transponder, Channel.ServiceID);	
	if (!channel)
		return false;
	
	if (DebugLevel >= 4)
		cout << "webepg: Have channel\n";
		
	cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(channel->GetChannelID());
	if(!pSchedule)
		pSchedule = (cSchedule *)Schedules->GetSchedule(channel, true);
	if(!pSchedule)
		return false;
	
	if (DebugLevel >= 4)
		cout << "webepg: Have pSchedule\n";
	
	if (DebugLevel >= 4)
		cout << "webepg: New Events to feed " << GetNumberOfEvents() << "\n";
	
	if (DebugLevel >= 4)
		fprintf(stderr, "webepg: feed events ");
	
	for (int i = 0; i < GetNumberOfEvents(); i++)
	{		
		cEv *oldEvent = GetEvent(i);
		cEvent *newEvent = new cEvent(oldEvent->EventID);
		if (DebugLevel >= 4)
			fprintf(stderr, "%d, ", oldEvent->EventID);
		
		newEvent->SetTableID(0);
		//newEvent->SetVersion(0xFF);
		newEvent->SetStartTime(oldEvent->StartTime);
		newEvent->SetDuration(oldEvent->Duration);
		newEvent->SetTitle(oldEvent->Title);
		newEvent->SetShortText(oldEvent->ShortText);
		newEvent->SetDescription(oldEvent->Description);
		
		newEvent->FixEpgBugs();
		pSchedule->AddEvent(newEvent);
	}
	
	if (DebugLevel >= 4)
			fprintf(stderr, "\n");
	
	if (DebugLevel >= 4)
		cout << "webepg: pSchedule->Sort();" << "\n";
	pSchedule->Sort();
	
	if (DebugLevel >= 4)
		cout << "webepg: Schedules->SetModified(pSchedule);" << "\n";
	Schedules->SetModified(pSchedule);
	
	return true;
};

//EW
void cEvents::clearEpg(/*int Source, int Transponder, unsigned short ServiceID*/)
{
	if (DebugLevel >= 4)
		cout << "webepg: clearEpg()\n";
	
	cSchedulesLock SchedulesLock(true,1000);
	cSchedules *Schedules=(cSchedules *)cSchedules::Schedules(SchedulesLock);	
	if (DebugLevel >= 4)
		cout << "webepg: Have Schedules\n";
	
	cChannel* channel = Channels.GetByServiceID(Channel.Source, Channel.Transponder, Channel.ServiceID);	
	if (!channel)
		return;	
	if (DebugLevel >= 4)
		cout << "webepg: Have channel\n";
		
	cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(channel->GetChannelID());
	if(!pSchedule)
		pSchedule = (cSchedule *)Schedules->GetSchedule(channel, true);
	if(!pSchedule)
		return;	
	if (DebugLevel >= 4)
		cout << "webepg: Have pSchedule\n";
	
	const cList<cEvent>* events = pSchedule->Events();
	
	if (DebugLevel >= 4)
		fprintf(stderr, "webepg: delete event ");
	
	cEvent *Event;
	//int count = events->Count();
	for (Event = events->First(); Event; Event = events->Next(Event))
	{
		Event->SetStartTime(0);
		pSchedule->UnhashEvent(Event);
	}
  /*while ((Event = events->First()) != NULL && count >= 1)
  {
  	//if (!Event->HasTimer())
  	{
  		if (DebugLevel >= 4)
  			fprintf(stderr, "%d, ", Event->EventID());
  		pSchedule->DelEvent(Event);
  	}
  	count--;
  }*/

  pSchedule->Cleanup();
  	
  if (DebugLevel >= 4)
  			fprintf(stderr, "\n");
};
