/*
 * mainmenu.c: The actual menu implementations
 *
 * See the main source file 'vdr.c' for copyright information and
 * how to reach the author.
 *
 * $Id:
 */

#include "umsmenus.h"
#include <typeinfo>
#include <vdr/interface.h>
#include <vdr/menu.h>

//=== cUMSMainMenuItem ================================================================

class cUMSMainMenuItem : public cOsdItem {
public:
	char boxname[200];
	bool bCallHist;
	int vmails;
	int faxes;
        cUMSMainMenuItem(char *cheading,bool bCallHistory,int icount, int itype);
	virtual void Set(void);
};

cUMSMainMenuItem::cUMSMainMenuItem(char *username,bool bCallHistory,int nrVoiceMails, int nrFaxes)
{
	strcpy(boxname,username);
	vmails=nrVoiceMails;
	faxes=nrFaxes;
	bCallHist=bCallHistory;
	Set();
}

void cUMSMainMenuItem::Set(void)
{
  	char *buffer = NULL;
	if (bCallHist)
  	    asprintf(&buffer, "%s (*/%d/%d)",boxname,vmails,faxes);
	else
  	    asprintf(&buffer, "%s (-/%d/%d)",boxname,vmails,faxes);
 	SetText(buffer, false);
}

//=== cUMSMainMenu ================================================================

cUMSMainMenu::cUMSMainMenu(char *boxBasePath)
:cOsdMenu(tr("UMS Boxen"),20)
{
    basePath=boxBasePath;
    RebuildMenu();
    Display();
}

int CheckFileName(const struct dirent *entry)
{
    if (strstr(entry->d_name,".au")!=NULL)
	return true;
    else
	return false;	
}

int cUMSMainMenu::GetNrVoiceMails(char *user)
{
    char path[500];
    strcpy(path,basePath);
    strcat(path,"/");
    strcat(path,user);
    strcat(path,"/received");
    struct dirent **namelist;
    int n;
    n=scandir(path,&namelist,CheckFileName,alphasort);
    free(namelist);
    return n;
}

bool cUMSMainMenu::CheckCallHistory(char *user)
{
	char *historyfile=NULL;
	asprintf(&historyfile,"%s/%s/callhistory.new",basePath,user);
	return (access(historyfile,R_OK)==0);
}

void cUMSMainMenu::RebuildMenu(void)
{
  	Clear();
  	DIR *d=opendir(basePath);
  	struct dirent *de=readdir(d);
  	while (de!=NULL)
  	{
		if ((strcmp(".",de->d_name)!=0) && (strcmp("..",de->d_name)!=0) && (strcmp(".keep",de->d_name)!=0))
		    Add(new cUMSMainMenuItem(de->d_name,CheckCallHistory(de->d_name),GetNrVoiceMails(de->d_name),0));
  		de=readdir(d);
  	}
  	closedir(d);
}

eOSState cUMSMainMenu::OpenSelectedBox(void)
{
    cUMSMainMenuItem *ci=(cUMSMainMenuItem*)Get(Current());
    char h[200];
    strcpy(h,"UMS Box fuer ");
    strcat(h,ci->boxname);
    AddSubMenu(new cBoxMenu(this,h,basePath,ci->boxname));
    return osContinue;
}

eOSState cUMSMainMenu::ProcessKey(eKeys Key)
{
  eOSState state = cOsdMenu::ProcessKey(Key);

  switch (state) {
    default:
         if (state == osUnknown) {
            switch (Key) {
              case kOk:     return OpenSelectedBox();
              default: break;
              }
            }
    }
  return state;
}

//==== cBoxMenuItem ===============================================================

class cBoxMenuItem : public cOsdItem {
public:
	char heading[100];
	int count;
	int type;
        cBoxMenuItem(char *cheading,int icount, int itype);
	virtual void Set(void);
};

cBoxMenuItem::cBoxMenuItem(char *cheading,int icount, int itype)
{
	strcpy(heading,cheading);
	count=icount;
	type=itype;
	Set();
}

void cBoxMenuItem::Set(void)
{
  	char *buffer = NULL;
	if (type!=et_calllist)
  	    asprintf(&buffer, "%s (%d)",heading,count);
	else
	    asprintf(&buffer, "%s",heading);	    
  	SetText(buffer, false);
}


//=== cBoxMenu ================================================================

cBoxMenu::cBoxMenu(cUMSMainMenu *Parent,char *heading,char *boxpath,char *boxname)
:cOsdMenu(tr(heading))
{
    parent=Parent;
    strcpy(basePath,boxpath);
    strcpy(user,boxname);
    RebuildMenu();
    Display();
}

int cBoxMenu::GetNrVoiceMails()
{
    char path[500];
    strcpy(path,basePath);
    strcat(path,"/");
    strcat(path,user);
    strcat(path,"/received");
    struct dirent **namelist;
    int n;
    n=scandir(path,&namelist,CheckFileName,alphasort);
    free(namelist);
    return n;
}

void cBoxMenu::RebuildMenu(void)
{
  	Clear();
	Add(new cBoxMenuItem("Anrufe",GetNrVoiceMails(),et_voicemail));
	Add(new cBoxMenuItem("Faxe",0,et_fax));
	char *historyfile=NULL;
	asprintf(&historyfile,"%s/%s/callhistory",basePath,user);
	if (access(historyfile,R_OK)==0)	
	{
	    char *header=NULL;
	    char *historynew=NULL;
	    asprintf(&historynew,"%s/%s/callhistory.new",basePath,user);
	    if (access(historynew,R_OK)==0)
		asprintf(&header,"Anrufliste (*)");
	    else	
		asprintf(&header,"Anrufliste (-)");
	    Add(new cBoxMenuItem(header,0,et_calllist));	    
	}	    
}

eOSState cBoxMenu::OpenFolder(void)
{
    cBoxMenuItem *bi=(cBoxMenuItem*)Get(Current());
    switch (bi->type)
    {
	case et_voicemail: 	AddSubMenu(new cVoiceMailMenu(this,basePath,user));
				break;
	case et_calllist: 	AddSubMenu(new cCallHistoryMenu(this,basePath,user));
				break;
    }
    return osContinue;	
}

eOSState cBoxMenu::ProcessKey(eKeys Key)
{
  eOSState state = cOsdMenu::ProcessKey(Key);
  switch (state) {
    case osBack: parent->RebuildMenu();
		 break;
    default:
         if (state == osUnknown) {
            switch (Key) {
              case kOk:     return OpenFolder();
	      
              default: break;
              }
            }
    }
  return state;
}

//==== cVoiceMailItem ===============================================================

class cVoiceMailItem : public cOsdItem {
public:
	char heading[MAX_CALLERID_LENGTH];
	char au_file[300];
        cVoiceMailItem(char *cheading,char *filename);
	virtual void Set(void);
};

cVoiceMailItem::cVoiceMailItem(char *cheading,char *filename)
{
	strcpy(heading,cheading);
	strcpy(au_file,filename);
	Set();
}

void cVoiceMailItem::Set(void)
{
  	char *buffer = NULL;
	asprintf(&buffer, "%s",heading);	    
  	SetText(buffer, false);
}


//==== cVoiceMailMenu ===============================================================

cVoiceMailMenu::cVoiceMailMenu(cBoxMenu *Parent,char *boxpath,char *boxname)
:cOsdMenu(tr("Voicemails"))
{
    parent=Parent;
    strcpy(basePath,boxpath);
    strcpy(user,boxname);
    bPlaying=false;
    Setup();
}

int FilterTextFiles(const struct dirent *entry)
{
    if (strstr(entry->d_name,".txt")!=NULL)
	return true;
    else
	return false;	
}

cVBOXSndPlayerControl* cVoiceMailMenu::GetVBOXSndPlayerControl()
{
    cControl *control=cControl::Control();
    if (control && typeid(*control)==typeid(cVBOXSndPlayerControl))
	return static_cast<cVBOXSndPlayerControl*>(control);
    return NULL;
}
    	
void cVoiceMailMenu::AddVoiceMailItem(char *path,char *fn)
{
    char callerid[MAX_CALLERID_LENGTH];
    char dt[100];
    char *buffer;
    asprintf(&buffer,"%s/%s",path,fn);    
    FILE *f=fopen(buffer,"r");
    char c='\0';
    while (c!=EOF)
    {
	int i=0;
	char tempLine[MAX_CALLERID_LENGTH];
	memset(tempLine,0,MAX_CALLERID_LENGTH);
	while ((c=getc(f)) != '\n' && c!=EOF)
		    tempLine[i++]=c;
	if (strstr(tempLine,"vdr-call_from=")!=NULL)		    
	    strcpy(callerid,strstr(tempLine," "));
	if (strstr(tempLine,"vdr-time=")!=NULL)
	    strcpy(dt,strstr(tempLine," "));
    }
    fclose(f);
    char *header=NULL;
    asprintf(&header,"%s -%s ",dt,callerid);
    char au_file[200];
    int i=0;
    while (buffer[i]!='.')
	au_file[i++]=buffer[i];
    au_file[i++]='\0';	
    strcat(au_file,".au");	
    Add(new cVoiceMailItem(header,au_file));
}

void cVoiceMailMenu::Setup(void)
{
  	Clear();
	char path[500];
	strcpy(path,basePath);
	strcat(path,"/");
	strcat(path,user);
	strcat(path,"/received");
	struct dirent **namelist;
	int n;
	n=scandir(path,&namelist,FilterTextFiles,alphasort);
	if (n<0)
	    isyslog("KWASI invalid path. path=%s",path);	    
	else
	{
	    while (n--)
	    {
		AddVoiceMailItem(path,namelist[n]->d_name);
		free(namelist[n]);
	    }    
	    free(namelist);
	}    
  	Display();
	SetHelp("Wiedergeben","Details","Loeschen");
}

eOSState cVoiceMailMenu::LaunchPlayer(void)
{
    cVoiceMailItem *vi=(cVoiceMailItem*)Get(Current());
    if (vi==NULL)
	return osContinue;
    cVBOXSndPlayerControl *control=GetVBOXSndPlayerControl();
    if (control)
    {
	control->Stop();
	return osContinue;	
    }
    isyslog("Playing file %s",vi->au_file);
    cControl::Launch(new cVBOXSndPlayerControl(vi->au_file));
    Display();
    return osContinue;
}

eOSState cVoiceMailMenu::StopPlayer(void)
{
    cVoiceMailItem *vi=(cVoiceMailItem*)Get(Current());
    if (vi==NULL)
	return osContinue;
    cVBOXSndPlayerControl *control=GetVBOXSndPlayerControl();
    if (control)
	control->Stop();
    Display();	
    return osContinue;
}

eOSState cVoiceMailMenu::ShowDetails()
{
    cVoiceMailItem *vi=(cVoiceMailItem*)Get(Current());
    if (vi==NULL)
	return osContinue;
    AddSubMenu(new cMenuText("Details",vi->heading));
    return osContinue;
}    

eOSState cVoiceMailMenu::DeleteVoiceMail()
{
    if (!Interface->Confirm(tr("Nachricht wirklich loeschen?")))
	return osContinue;
    cVoiceMailItem *vi=(cVoiceMailItem*)Get(Current());
    if (vi==NULL)
	return osContinue;
    char *buffer;
    char basefile[200];
    for (int i=0;i<200;i++)
	basefile[i]=0;
    asprintf(&buffer,"%s",vi->au_file);
    int i=0;
    while (buffer[i]!='.')
	basefile[i++]=buffer[i];    
    char *cmd;
    asprintf(&cmd,"rm %s.*",basefile);
    system(cmd);
    isyslog("KWASI DEBUG: %s ",cmd);
    cList<cOsdItem>::Del(vi);        
    Display();
    return osContinue;
}

eOSState cVoiceMailMenu::ProcessKey(eKeys Key)
{
  eOSState state = cOsdMenu::ProcessKey(Key);

  switch (state) {
    case osBack: parent->RebuildMenu();
		 StopPlayer();
		 break;
    default:
         if (state == osUnknown) {
            switch (Key) {
	      case kYellow: return DeleteVoiceMail();
	      case kGreen:  return ShowDetails();
	      case kRed:    
              case kOk:     if (bPlaying)
	    		    {
				StopPlayer();
				bPlaying=false;
				SetHelp("Wiedergeben","Details","Loeschen");
			    }
			    else
			    {
				LaunchPlayer();
				bPlaying=true;
				SetHelp("Stoppen");
			    }
			    return osContinue;
				
              default: break;
              }
            }
    }
  return state;
}

//==== cCallHistoryItem ===============================================================

class cCallHistoryItem : public cOsdItem {
public:
	char heading[MAX_CALLERID_LENGTH];
        cCallHistoryItem(char *cheading);
	virtual void Set(void);
};

cCallHistoryItem::cCallHistoryItem(char *cheading)
{
	strcpy(heading,cheading);
	SetSelectable(true);
	Set();
}

void cCallHistoryItem::Set(void)
{
  	char *buffer = NULL;
	asprintf(&buffer, "%s",heading);	    
  	SetText(buffer, false);
}


//=== cCallHistoryMenu ==========================================================

cCallHistoryMenu::cCallHistoryMenu(cBoxMenu *Parent,char *boxpath,char *boxname)
:cOsdMenu(tr("Anrufliste"))
{
    parent=Parent;
    strcpy(basePath,boxpath);
    strcpy(user,boxname);
    Setup();
}

void cCallHistoryMenu::AddHistoryItems()
{
    char *historyfile=NULL;
    asprintf(&historyfile,"%s/%s/callhistory",basePath,user);
    if (access(historyfile,R_OK)!=0)
	return;
    char *tmpfile=NULL;
    asprintf(&tmpfile,"%s/%s/ch.tmp",basePath,user);
    char *cmd=NULL;
    asprintf(&cmd,"tac %s > %s",historyfile,tmpfile);    	
    system(cmd);
    FILE *f=fopen(tmpfile,"r");
    char c='\0';
    while (c!=EOF)
    {
	int i=0;
	char tempLine[500];
	memset(tempLine,0,500);
	while ((c=getc(f)) != '\n' && c!=EOF)
		    tempLine[i++]=c;
	Add(new cCallHistoryItem(tempLine));		    
    }
    fclose(f);
    unlink(tmpfile);
}

void cCallHistoryMenu::Setup(void)
{
  	Clear();
	AddHistoryItems();
  	Display();
	char *historyfile=NULL;
	asprintf(&historyfile,"%s/%s/callhistory.new",basePath,user);
	if (access(historyfile,R_OK))
	    SetHelp("Details","Loeschen","","ungelesen");
	else
	    SetHelp("Details","Loeschen","gelesen");
}

eOSState cCallHistoryMenu::DeleteHistory()
{
    if (!Interface->Confirm(tr("Komplette Anrufliste loeschen?")))
	return osContinue;
    char *historyfile=NULL;
    asprintf(&historyfile,"%s/%s/callhistory",basePath,user);
    unlink(historyfile);
    asprintf(&historyfile,"%s/%s/callhistory.new",basePath,user);
    unlink(historyfile);
    Clear();
    Display();
    return osBack;
}        
    	
eOSState cCallHistoryMenu::SetReadState(bool bRead)
{
    char *historyfile=NULL;
    asprintf(&historyfile,"%s/%s/callhistory.new",basePath,user);
    if (bRead)
    {
	unlink(historyfile);
	Skins.Message(mtInfo,"Status gelesen gesetzt");
	SetHelp("Details","Loeschen","","ungelesen");
    }
    else
    {
	FILE *f=fopen(historyfile,"w");
	fclose(f);
	Skins.Message(mtInfo,"Status NICHT gelesen gesetzt");
        SetHelp("Details","Loeschen","gelesen");
    }	
    return osUser1;		
}

eOSState cCallHistoryMenu::ShowDetails(void)
{
    cCallHistoryItem *ci=(cCallHistoryItem*)Get(Current());
    if (ci==NULL)
	return osContinue;
    AddSubMenu(new cMenuText("Details",ci->heading));	
    Display();
    return osContinue;
}


eOSState cCallHistoryMenu::ProcessKey(eKeys Key)
{
  eOSState state = cOsdMenu::ProcessKey(Key);

  switch (state) {
    case osBack: parent->RebuildMenu();
		 break;
    default:
         if (state == osUnknown) {
            switch (Key) {
	      case kBlue:     return SetReadState(false);
	      case kYellow:   return SetReadState(true);	
	      case kGreen:    return DeleteHistory();
	      case kRed:	      
              case kOk:     return ShowDetails();
              default: break;
              }
            }
    }
  return state;
}
