/*  VirtualCue XMMS
 *  Copyright (C) 2005 Barraud Manuel
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public Licensse as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CueParser.h"


 char *LABEL_PERFORMER="PERFORMER";
 char *LABEL_TITLE="TITLE";
 char *LABEL_FILE="FILE";
 char *LABEL_INDEX="INDEX";
 static int CurrentLine=0;
 int CueParserErrno=0;
 

int EvalLengthLine(FILE *fichier)
{
 long pointerdata;
 int byte;
 int length=0;
 
 //on recupere la position interne du fichier   
 pointerdata=ftell(fichier);
 
 //on parcours le fichier jusqu'a la fin de celui ci
 while((byte=fgetc(fichier))!=EOF)
 {
 
  // si on rencontre un \r on regarde la valeur d'apres
  if(((char)byte)=='\n')
  {


 
 
   fseek(fichier,pointerdata,SEEK_SET);                              
   return length;//on a la ligne mais on ne compte pas le \r\n              
  }
  length++;
                                          
 }
   fseek(fichier,pointerdata,SEEK_SET);                              
   return length;
    
}



char *ExtractLine(FILE *fichier)
{
int length=0;
char *bufferline=NULL;
//on recupere la taille de la prochaine line
 length=EvalLengthLine(fichier);
 
 if(length==0)
 return NULL;
 
 bufferline=(char *)malloc(sizeof(char)*(length+1));// juste un peu plus grand que le chaine elle même pour penser a l'ajout du \0 en fin de chaine
 // si l'allocation s'est bien passé
 if(bufferline)
 {
     memset(bufferline,0,(length+1)*sizeof(char));
     fread(bufferline,length,sizeof(char),fichier);// on receupere la ligne
     fseek(fichier,1,SEEK_CUR);//on saute le \r\n
     
 }
     
     return bufferline;
     
}









char *SkipBackSpaceAndTab(char *chaine)
{
while(*chaine!='\0')
{
if(*chaine!=' '&&*chaine!='\t')
return chaine;

chaine++;      
}

return chaine;
}







int CalcNbTrackAvailable(char *filename)
{
 FILE *fichier;
  char *buffer;
  char *track;
  int nbtrack=0,ntrack;

  
fichier=fopen(filename,"rb");
  if(fichier)
  {

       while((buffer=ExtractLine(fichier)))
      {
      
      track=strstr(buffer,"TRACK");
   
      
      if(track)
      {
      sscanf(track,"TRACK %d AUDIO",&ntrack);
      if(ntrack>nbtrack)
      nbtrack=ntrack;   
       
      }
      free(buffer);                                    
      }        
 
      
     fclose(fichier);       
  }
  else
  {
      printf("Impossible d'ouvrir le fichier\n");
	  return -1;
  }

return nbtrack;
}




void GetString(char *str,char *buffer,int lengthstring)
{

int pos=0;
int count=0;
char *string;

if(lengthstring<1)
return;

if(lengthstring==1)//si la taille n'est que de 1 alors chaine vide on quitte
{
	*buffer='\0';
	return;
}

string=SkipBackSpaceAndTab(str);
	
while(*string!='\0'&&count<(lengthstring-1))
{

        if(*string=='"')
        pos++;
        else
        {
             if(pos==1)
             {
             *buffer=*string;
              count++;
			  buffer++;
             }
     
         
         }

	
         
         if(pos==2)
		 {
	     *buffer='\0';
         return;
		 }
	
         
         string++;
          
}

if(pos==1)
*(buffer-1)='\0';
printf("Guillemet manquant Ligne %d:%s\n",CurrentLine,str); 
}


#define CHK_PERFORMER 1
#define CHK_TITLE 2
#define CHK_FILE 4
#define CHK_INDEX 8



void GetInformationByLine(InfoCue *Icue,char *filename)
{
  FILE *fichier;
  char *buffer,*sline;
  char *performer,*title,*index,*file;
  int ntrack=-1;
  int minute,seconde,centiemeseconde;
  int chkerror=0;
	
  CueParserErrno=0;
	
  fichier=fopen(filename,"rb");
 
  if(fichier)
  {
	CurrentLine=0;
       while((buffer=ExtractLine(fichier)))
      {
        
          sline=strstr(buffer,"TRACK");
          if(sline)
          {
			  
			  if(ntrack==-1)//on verifiais precedemment les entetes donc en entete il ya le performer, le titre et le fichier 
			  {
				  
				if(chkerror!=(CHK_PERFORMER|CHK_TITLE|CHK_FILE))
				{
					//malformation de l'entetes
					printf("Warning Bad Header:");
					
					if(!(chkerror&CHK_PERFORMER))
					printf("Performer ");
					
					if(!(chkerror&CHK_TITLE))
					printf("Title ");
					
					if(!(chkerror&CHK_FILE))
					{
						//erreur grave nuis au fonctionnement
					CueParserErrno=1;	
					printf("File ");
					}
					printf("Missed\n");
					
					
				}					
				  
			  }
			  else
			  {
				  //on es en plein sur les tracks donc on a besoin d'un performer d'un titre et d'un index
				    if(chkerror!=(CHK_PERFORMER|CHK_TITLE|CHK_INDEX))
					{
					
						printf("***Missed Information for track %d:",ntrack);
						
						if(!(chkerror&CHK_PERFORMER))
						printf("Performer (Optional) ");
						
						if(!(chkerror&CHK_TITLE))
						printf("Title (Optionnal) ");
						
						if(!(chkerror&CHK_INDEX))
						{
							//erreur grave
							CueParserErrno=1;
							
						printf("Index (Must Required)");
						}
						printf("\n");
						
					
						
						
					}
				  
				  
			  }
			  
          chkerror=0;//nouveau checking d'erreur
          sscanf(sline,"TRACK %d AUDIO",&ntrack);
 	  
          }
          
      
          sline=strstr(buffer,LABEL_PERFORMER);
          if(sline)
          {
       
          chkerror|=CHK_PERFORMER;
			  
          performer=strstr(sline,LABEL_PERFORMER);
          if(ntrack<1)
          GetString(performer+strlen(LABEL_PERFORMER),Icue->Performer,SIZE_IT_PERFORMER);
      	  else
          GetString(performer+strlen(LABEL_PERFORMER),Icue->tracks[ntrack-1].Performer,SIZE_IT_PERFORMER);


          }
          
          sline=strstr(buffer,LABEL_TITLE);
          if(sline)
          {
          chkerror|=CHK_TITLE;
          title=strstr(sline,LABEL_TITLE);
	      if(ntrack<1)
          GetString(title+strlen(LABEL_TITLE),Icue->Title,SIZE_IT_TITLE);
 	      else
	      GetString(title+strlen(LABEL_TITLE),Icue->tracks[ntrack-1].Title,SIZE_IT_TITLE);

             
          }
          
          
          sline=strstr(buffer,LABEL_FILE);
          if(sline)
          {
         
          chkerror|=CHK_FILE;     
          file=strstr(sline,LABEL_FILE);
          GetString(file+strlen(LABEL_FILE),Icue->File,SIZE_IT_FILE);
   
          }
          
         

	  sline=strstr(buffer,LABEL_INDEX);

	  if(sline)
	  {
		  chkerror|=CHK_INDEX;
	      index=strstr(sline,LABEL_INDEX);
          sscanf(index,"INDEX 01 %d:%d:%d",&minute,&seconde,&centiemeseconde);
          
          Icue->tracks[ntrack-1].time_millieme=(centiemeseconde*10+seconde*1000+minute*60*1000);

	  }
		       
      CurrentLine++;
      free(buffer);                                    
      }        
 
      
     fclose(fichier);       
  }
  else
  {
      printf("Impossible d'ouvrir le fichier\n");
  }                 
                      
}

InfoCue *GetInfoCue(char *filename)
{
        
        int nbtrack=CalcNbTrackAvailable(filename);
		
		if(nbtrack<0)
		return NULL;
	
        InfoCue *Icue=(InfoCue *)malloc(sizeof(InfoCue)+sizeof(InfoTrack)*(nbtrack-1));
        if(Icue)
		{
		memset(Icue,0,sizeof(InfoCue)+sizeof(InfoTrack)*(nbtrack-1));
        Icue->nbtrack=nbtrack;
		GetInformationByLine(Icue,filename);
			if(CueParserErrno)//une erreur de syntaxe serieuse a été rencontrée
			{
				
				free(Icue);
				return NULL;
			}
			
        }
        else
		printf("Erreur d'allocation Memoire pour un InfoCue\n");
        
        
     return Icue;   
}


long GetTimeByNum(InfoCue *Icue,int num,int totaltime)
{

	long t_value;
	
	if(num==(Icue->nbtrack-1))
	t_value=(totaltime-Icue->tracks[num].time_millieme);
	else
	t_value=(Icue->tracks[num+1].time_millieme-Icue->tracks[num].time_millieme);

return t_value;


}
