/*
 * yac-menurecordings.c: A plugin for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id$
 */

#include <vdr/recording.h>
#include <vdr/plugin.h>
#include "yac-recordings.h"

#define INDEXFILESUFFIX   "/index.vdr"
#define SCRIPT_FILE "yac_start.sh"

char yacProjName[MAX_NAME_LEN];
bool yacMergeRecs;
// --- cYacRecItem ----------------------------------------------------

cYacRecItem::cYacRecItem(const cRecording *Recording)
{
   cString text;
   const cComponents *Components;
   cRec = (cRecording *)Recording;
   if( (name = strrchr(cRec->Name(), '~')) != NULL )
      name++;
   else
      name = (char *)cRec->Name();

   recFullLength = 0;
   recLength = GetLength();
   cutLength = GetCutLength();
   numATracks = 0;
   recSize = DirSizeMB( cRec->FileName() );
   videoInfo = NULL;
   bConverted = CheckConverted( cRec->FileName() );
   Components = cRec->Info()->Components();
   if( Components ) {
      for( int i = 0; i < Components->NumComponents(); i++ ) {
         const tComponent *p = Components->Component(i);
	 if( p->stream == 1 && (p->description != NULL) && !videoInfo )
            videoInfo = strdup(p->description);

         if( p->stream == 2 && p->type != 5 ) {
            audioTracks[numATracks].state = numATracks ? at_ignore : at_master;
            asprintf( &(audioTracks[numATracks].desc), "%s-%s", (p->description) ? p->description : "?",
                      (p->language) ? p->language : "?" );
            numATracks++;
         }
      }
      for( int i = 0; i < Components->NumComponents(); i++ ) {
         const tComponent *p = Components->Component(i);
         if( p->stream == 2 && p->type == 5 ) {
            audioTracks[numATracks].state = numATracks ? at_ignore : at_master;
            asprintf( &(audioTracks[numATracks].desc), "%s-%s", (p->description) ? p->description : "?",
                      (p->language) ? p->language : "?" );
            numATracks++;
         }
      }
   }
   titleBuffer[0] = '\0';
}


cYacRecItem::~cYacRecItem()
{
   while( numATracks > 0 ) {
      numATracks--;
      free( audioTracks[numATracks].desc );
   }
   if( videoInfo )
      free(videoInfo);
}


int cYacRecItem::GetLength(void) {
   int len = 0;
   char *filename;
   asprintf( &filename, "%s%s", cRec->FileName(), INDEXFILESUFFIX);
   if( access(filename, R_OK) == 0 ) {
      struct stat buf;
      if( stat(filename, &buf) == 0 ) {
         struct tIndex {
            int offset; uchar type; uchar number; short reserved;
         };
         int delta = buf.st_size % sizeof(tIndex);
         if( delta ) {
            delta = sizeof(tIndex) - delta;
            esyslog("ERROR: invalid file size (%ld) in '%s'", buf.st_size, filename);
         }
         recFullLength = (buf.st_size + delta) / sizeof(tIndex);
         len = recFullLength / SecondsToFrames(60);
      }
   }
   return len;
}

const char *cYacRecItem::Title(void) {
   int i;
   char audioInfo[32];
   char *tmp;

   tmp = audioInfo;
   for( i = 0; i < numATracks; i++ ) {
      if( i > 0 ) {
         *tmp = ',';
         tmp++;
      }
      strcpy( tmp, itoa(i+1) );
      tmp++;
      if( i > 9 )
         tmp++;
      if( audioTracks[i].state == at_use )
         *tmp = '+';
      else if( audioTracks[i].state == at_ignore )
         *tmp = '-';
      else if( audioTracks[i].state == at_master )
         *tmp = '*';

      tmp++;
   }
   *tmp = '\0';

   snprintf( titleBuffer, sizeof(titleBuffer), "%-16s / %d%s'\t%s", 
                                               audioInfo, 
                                               recLength, 
                                               cutLength >= 0 ? strdup(cString::sprintf("/%d", recLength - cutLength)) : "",
                                               name );
   return titleBuffer;
}

audioTrackState cYacRecItem::TrackState(int idx)
{
   if( idx >= 0 && idx < numATracks ) {
      return audioTracks[idx].state;
   }
   return at_ignore;
}

const char * cYacRecItem::TrackInfo(int idx)
{
   if( idx >= 0 && idx < numATracks ) {
      return audioTracks[idx].desc;
   }
   return "";
}

void cYacRecItem::SelectTrack(int idx, audioTrackState select)
{
   if( idx >= 0 && idx < numATracks )
      audioTracks[idx].state = select;
}

int cYacRecItem::GetCutLength(void)
{
   cMarks marks;
   int oldMark = -1;
   int cutLen = 0;
   if( !marks.Load(cRec->FileName()) || !marks.Count() || strstr( cRec->FileName(), "/%" )  )
      return -1;

   for( cMark *mark = marks.First(); mark != 0; mark = marks.Next(mark) ) {
      int pos = mark->position;
      if( oldMark >= 0 ) {
         cutLen += pos - oldMark;
         oldMark = -1;
      }
      else
         oldMark = pos;
   }
   if( oldMark > 0 && recFullLength > oldMark )
      cutLen += recFullLength - oldMark;

   return ( recFullLength - cutLen ) / SecondsToFrames(60);
}


bool cYacRecItem::CheckConverted(const char *filename)
{
   struct stat statBuf;

   if (lstat(cString::sprintf( "%s/yacoto.log", filename ), &statBuf) == -1) 
      return false;

   return true;
}

// --- class cYacRecs ----------------------------------------------------

cYacRecs::cYacRecs(void) 
{
   yacSelState = 0;
   Clear();
}

void cYacRecs::Clear(void) 
{
   for( int i = 0; i < MAX_SEL && yacRecs[i] != NULL ; i++ ) {
      if( yacRecs[i] != NULL ) {
         delete yacRecs[i];
         yacRecs[i] = NULL;
      }
   }
   yacSelState++;
   numItems = 0;
   yacMergeRecs = false;
   yacProjName[0] = '\0';
}


bool cYacRecs::Selected(cRecording *rec)
{
   if( rec ) {
      for( int i = 0; i < MAX_SEL && yacRecs[i] != NULL; i++ ) {
         if( !strcmp(yacRecs[i]->CRec()->FileName(), rec->FileName()) )
            return true;
      }
   }
   return false;
}


bool cYacRecs::Start(void)
{
   char execCmd[8192];
   int baseLen = 0;

   strcpy(execCmd,AddDirectory( cPlugin::ConfigDirectory(), "yacoto/" ));
   strcat(execCmd,SCRIPT_FILE);
   baseLen = strlen(execCmd);
   if( yacMergeRecs == true || numItems == 1 ) {
      strcpy(execCmd + baseLen, " \"");
      strcat(execCmd, yacProjName);
      strcat(execCmd, "\"");
      baseLen = 0;
   }

   Skins.Message(mtInfo, tr("Starting convert"),1);
   for( int i = 0; i < MAX_SEL && yacRecs[i] != NULL; i++ ) {
      if( baseLen > 0 ) {
         strcpy(execCmd + baseLen, " \"");
         strcat(execCmd, yacRecs[i]->Name() );
         strcat(execCmd, "\"");
      }

      strcat( execCmd, " \"" );
      strcat( execCmd, yacRecs[i]->CRec()->FileName() );
      for( int j = 0; j < yacRecs[i]->NumATracks(); j++ ) {
         sprintf( execCmd + strlen(execCmd), "~%d", (int)yacRecs[i]->TrackState(j));
      }
      strcat( execCmd, "\"" );
      if( yacMergeRecs == false || yacRecs[i+1] == NULL ) {
         dsyslog( "Executing <%s>", execCmd );
         system( execCmd );
      }
      yacRecs[i]->SetConverted();
   }

   Clear();
   return true;
}


bool cYacRecs::Remove(cRecording *rec)
{
   int i,j;
   bool rc = false;
   for( i = 0; i < MAX_SEL && yacRecs[i] != NULL; i++ ) {
      dsyslog("Remove %d %s", i, rec->FileName());
      if( !strcmp(yacRecs[i]->CRec()->FileName(), rec->FileName()) ) {
         delete yacRecs[i];
         for( j = i + 1; j < MAX_SEL && yacRecs[j] != NULL; i++, j++ ) {
            yacRecs[i] = yacRecs[j];
         }
         yacRecs[i] = NULL;
         yacSelState++;
         numItems--;
         rc = true;
         break;
      }
   }
   return rc;
}

bool cYacRecs::Add(cRecording *rec)
{
   int i;
   bool rc = false;

   dsyslog( "Adding %s", rec->FileName() );
   for( i = 0; i < MAX_SEL && yacRecs[i] != NULL; i++ ) {
      if( !strcmp(yacRecs[i]->CRec()->FileName(), rec->FileName()) ) {
         return false;
      }
   }
   if( i < MAX_SEL ) {
      yacRecs[i] = new cYacRecItem(rec);
      if( numItems == 0 ) {
         strncpy(yacProjName, yacRecs[i]->Name(), sizeof(yacProjName));
      }
      yacSelState++;
      numItems++;
      rc = true;
   }
   return rc;
}


bool cYacRecs::Changed(int *state)
{
   bool result = ( *state != yacSelState );
   *state = yacSelState;

   return result;
}


bool cYacRecs::Move(cRecording *rec, moveMode mode)
{
   bool rc = false;
   int i,j;
   if( rec && rec->FileName() ) {
      for( i = 0; i < MAX_SEL && yacRecs[i] != NULL; i++ ) {
         if( !strcmp(yacRecs[i]->CRec()->FileName(), rec->FileName()) ) {
            int newPos = i;
            switch( mode ) {
               case move_up:
                  newPos = i - 1;
                  break;
               case move_down:
                  newPos = i + 1;
                  break;
               case move_top:
                  newPos = 0;
                  break;
               case move_bottom:
                  newPos = numItems - 1;
                  break;
               default:
                  break;
            }
            if( newPos >= 0 && newPos < numItems && newPos != i ) {
               cYacRecItem *actRec = yacRecs[i];
               if( newPos > i ) {
                  for( j=i; j < newPos; j++ ) {
                     yacRecs[j] = yacRecs[j+1];
                  }
               }
               else {
                  for( j=i; j > newPos; j-- ) {
                     yacRecs[j] = yacRecs[j-1];
                  }
               }
               yacRecs[newPos] = actRec;
               rc = true;
            }
            break;
         }
      }
   }
   return rc;
}


cYacRecs yacRecordings;
