/*
 * playlist.c
 * 25/09/03
 */

#include "lib.h"
#include "main.h"
#include "msg.h"
#include "playlist.h"
#include "ro_file.h"
#include "ka_error.h"


int recursive = 0;
static int file_count;
static FILE * temp;


/*
 * playlist_update
 * ---------------
 */
void playlist_update(void)
{
  _kernel_swi_regs regs;
  int blk[10];
  char s[16];
  static int last_count = -1;

  // only update when necessary to stop flickering when adding directories
  if(file_count != last_count)
  {
    snprintf(s, sizeof(s), "%d", file_count);
    icon_text_change(win_data[WIN_PLAYLIST].win_handle, ICON_COUNT, s);

    if((file_count == 0 && last_count != 0) ||
       (file_count != 0 && last_count == 0))
    {
      blk[0] = win_data[WIN_PLAYLIST].win_handle;
      blk[3] = IFLAG_SELECTED | IFLAG_SHADED;
      regs.r[1] = (int)blk;
      blk[2] = (file_count) ? 0 : IFLAG_SHADED;
      blk[1] = ICON_SAVE_PL;
      _kernel_swi(Wimp_SetIconState, &regs, &regs);
      blk[1] = ICON_FILE_TEXT;
      _kernel_swi(Wimp_SetIconState, &regs, &regs);
      blk[1] = ICON_FILENAME;
      _kernel_swi(Wimp_SetIconState, &regs, &regs);
    }
  }
  last_count = file_count;
}

/*
 * playlist_open
 * -------------
 */
void playlist_open(void)
{
  _kernel_swi_regs regs;
  int blk[10];

  // start new playlist
  if(temp) fclose(temp);
  if((temp = fopen("<Kino$ScrapDir>.temp","w")) == NULL)
    report_error(1, "error103:%s", "<Kino$ScrapDir>.temp"); // (Cannot open file)
  else
  {
    fprintf(temp,"Playlist\n");

    file_count = 0;
    playlist_update();

    // open window
    blk[0] = win_data[WIN_PLAYLIST].win_handle;
    regs.r[1] = (int) blk;
    _kernel_swi(Wimp_GetWindowState, &regs, &regs);
    blk[7] = -1; // bring to front
    _kernel_swi(Wimp_OpenWindow, &regs, &regs);
  }
}

/*
 * playlist_close
 * --------------
 */
void playlist_close(void)
{
  if(temp)
  {
    fclose(temp);
    _kernel_oscli("delete <Kino$ScrapDir>.temp");
    temp = NULL;
  }
}

/*
 * playlist_add
 * ------------
 */
void playlist_add(const char* name)
{
  if(temp)
  {
    fprintf(temp,"%s\n", name);
    file_count++;
    playlist_update();
  }
}

/*
 * playlist_save
 * -------------
 */
void playlist_save(const char* name)
{
  static char s[MAXPATH];

  if(temp)
  {
    fclose(temp);
    temp = NULL;

    // move file
    snprintf(s, sizeof(s), "copy <Kino$ScrapDir>.temp %s ~c ~v f d", name);
    _kernel_oscli(s);
  }
  playlist_open(); // start new file
}

static int file_types[] =
{ FILETYPE_VOB
, FILETYPE_MPEG
, FILETYPE_AVI
, -1
};

int playlist_accept(int file_type)
{
  for (int* ptypes = file_types; *ptypes != -1; ptypes++)
  {
    if (*ptypes == file_type)
      return 1;
  }

  return 0;
}

/*
 * playlist_dir_add
 * ----------------
 * Add any MPEG files in the given directory to the playlist.
 * Searches recursively through sub directories if required.
 */
void playlist_dir_add(const char* name)
{
  char s[MAXPATH]; // limits maximum pathlength
  _kernel_swi_regs regs;
  struct
  {
    int i[5];
    char c[256];
  } b;

  regs.r[0] = 10;
  regs.r[1] = (int)name;
  regs.r[2] = (int)&b;
  regs.r[4] = 0;
  regs.r[5] = sizeof(b);
  regs.r[6] = 0;

  while(regs.r[4] != -1)
  {
    regs.r[3] = 1;
    _kernel_swi(OS_GBPB, &regs, &regs);
    if(regs.r[3] == 1)
    {
      snprintf(s, sizeof(s), "%s.%s", name, b.c); // add name to path
      if((b.i[4] == 1) // file
      && ((b.i[0] & 0xfff00000) == 0xfff00000)
      && playlist_accept((b.i[0] >> 8) & 0xfff))
        playlist_add(s);
      else if((b.i[4] == 2) && recursive) // directory
        playlist_dir_add(s);
    }
  }
}

/*
 * playlist_send
 * -------------
 * Starts an instance of the player with the supplied playlist.
 * Ignores files that can't be opened or text files that aren't
 * playlists.
 */
void playlist_send(int type, const char* name)
{
  static char s[MAXPATH];
  static const char* run_pl = "<KinoChoices$Dir>.RunPlayLst";
  _kernel_swi_regs regs;
  FILE *f;

  if(type == FILETYPE_TEXT) // check for a playlist
  {
    if((f = fopen(name, "r")) == NULL)
      return; // cannot open file, ignore

    fgets(s,16,f);
    fclose(f);
    if(strncmp("Playlist", s, 8) != 0)
      return; // file not a playlist, ignore
  }
  else if(type == 0x1000) // if a directory contains mpegs, pass to player as a playlist
  {
    int n = 0;
    struct
    {
      int i[5];
      char c[256];
    } b;

    regs.r[0] = 10;
    regs.r[1] = (int)name;
    regs.r[2] = (int)&b;
    regs.r[4] = 0;
    regs.r[5] = sizeof(b);
    regs.r[6] = 0;
    while(regs.r[4] != -1)
    {
      regs.r[3] = 1;
      _kernel_swi(OS_GBPB, &regs, &regs);
      if(regs.r[3] == 1)
        if((b.i[4] == 1) // file
        && ((b.i[0] & 0xfff00000) == 0xfff00000)
        && playlist_accept((b.i[0] >> 8) & 0xfff))
          n++;
    }
    if(n == 0)
      return;
  }
  else
    return;

  // create an Obey file to pass the playlist option to the player
  if((f = fopen(run_pl,"w")) == 0)
    report_error(1, "error103:%s", run_pl); // (Cannot write Obey file)
  else
  {
    fprintf(f,"| Generated file\n"
              "\n"
              "| Uncomment and edit to customize\n"
              "|Run Kino:Ensure\n"
              "|WimpSlot -min 256K -max 256K\n"
              "|Run Kino:Kino -fKinoChoices:Choices -p%s\n"
              "\n"
              "| Uncomment to use normal version\n"
              "Run Kino:RunKino -p%s\n", name, name);
    fclose(f);
    regs.r[0] = WRITE_CATINFO;
    regs.r[1] = (int)run_pl;
    regs.r[2] = FILETYPE_OBEY;
    _kernel_swi(OS_File, &regs, &regs); // set filetype to Obey
    snprintf(s, sizeof(s), "Filer_Run %s", run_pl);
    _kernel_oscli(s);
  }
}
