/* id3read.c
   interface for the id3tag library
   Copyright (C) 2001 Linus Walleij

This file is part of the GNOMAD package.

GNOMAD is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

You should have received a copy of the GNU General Public License
along with GNOMAD; see the file COPYING.  If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. 

*/

#define ID3V2_MAX_STRING_LEN 4096
#include <id3tag.h>
#include <libmtp.h>
#include <stdlib.h>		/* atol() */
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <glib.h>
#include <glib/gstdio.h>

/* Converts a figure representing a number of seconds to
 *  * a string in mm:ss notation */
gchar *
seconds_to_mmss (uint32_t seconds)
{
  gchar tmp2[10];
  gchar tmp[10];
  uint32_t secfrac = seconds % 60;
  uint32_t minfrac = seconds / 60;

  if (seconds == 0)
    return g_strdup ("0:00");

  snprintf (tmp2, 10, "0%u", secfrac);
  while (strlen (tmp2) > 2)
    {
      tmp2[0] = tmp2[1];
      tmp2[1] = tmp2[2];
      tmp2[2] = '\0';
    }
  snprintf (tmp, 10, "%u:%s", minfrac, tmp2);
  return g_strdup (tmp);
}

/* Converts a string in mm:ss notation to a figure
 *  * representing seconds */
guint
mmss_to_seconds (gchar * mmss)
{
  gchar **tmp;
  guint seconds = 0;

  if (!mmss)
    return seconds;

  tmp = g_strsplit (mmss, ":", 0);
  if (tmp[1] != NULL)
    {
      seconds = 60 * strtoul (tmp[0], NULL, 10);
      seconds += strtoul (tmp[1], NULL, 10);
    }
  if (tmp != NULL)
    g_strfreev (tmp);
  return seconds;
}

/* Eventually make charset selectable */

static id3_utf8_t *
charset_to_utf8 (const id3_latin1_t * str)
{
  id3_utf8_t *tmp;

  tmp =
    (id3_utf8_t *) g_convert ((gchar *) str, -1, "UTF-8", "ISO-8859-1",
			      NULL, NULL, NULL);
  return (id3_utf8_t *) tmp;
}

/*****************************************************************************
 * ID3TAG interface
 * Many parts of this code copied in from gtkpod or plagiated, I confess.
 * Acknowledgements to Jorg Schuler for that...
 *****************************************************************************/

/*
 * Returns a text frame, or NULL
 */

static gchar *
getFrameText (struct id3_tag *tag, char *frame_name)
{
  const id3_ucs4_t *string;
  struct id3_frame *frame;
  union id3_field *field;
  gchar *utf8 = NULL;
  enum id3_field_textencoding encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;

  frame = id3_tag_findframe (tag, frame_name, 0);
  if (!frame)
    return NULL;

  /* Find the encoding used for the field */
  field = id3_frame_field (frame, 0);
  //printf ("field: %p\n", field);
  if (field && (id3_field_type (field) == ID3_FIELD_TYPE_TEXTENCODING))
    {
      encoding = field->number.value;
      //printf ("encoding: %d\n", encoding);
    }

  if (strcmp (frame_name, ID3_FRAME_COMMENT) == 0)
    field = id3_frame_field (frame, 3);
  else
    field = id3_frame_field (frame, 1);

  //printf ("field: %p\n", field);

  if (!field)
    return NULL;

  if (strcmp (frame_name, ID3_FRAME_COMMENT) == 0)
    string = id3_field_getfullstring (field);
  else
    string = id3_field_getstrings (field, 0);

  // g_debug("string: %s\n", string);

  if (!string)
    return NULL;

  if (strcmp (frame_name, ID3_FRAME_GENRE) == 0)
    string = id3_genre_name (string);

  if (encoding == ID3_FIELD_TEXTENCODING_ISO_8859_1)
    {
      /* ISO_8859_1 is just a "marker" -- most people just drop
         whatever coding system they are using into it, so we use
         charset_to_utf8() to convert to utf8 */
      id3_latin1_t *raw = id3_ucs4_latin1duplicate (string);
      utf8 = (gchar *) charset_to_utf8 (raw);
      g_free (raw);
    }
  else
    {
      /* Standard unicode is being used -- we won't have to worry
         about charsets then. */
      // g_debug("This frame is a Unicode frame!\n");
      utf8 = (gchar *) id3_ucs4_utf8duplicate (string);
    }
  // g_debug("Found tag: %s, value: %s\n", frame_name, utf8);
  return utf8;
}

/*****************************************************************************
 * FUNCTIONS FOR GETTING ID3v2 FIELDS
 *****************************************************************************/

gchar *
getArtist (struct id3_tag * tag)
{
  gchar *artname = NULL;

  artname = getFrameText (tag, "TPE1");
  if (artname == NULL)
    artname = getFrameText (tag, "TPE2");
  if (artname == NULL)
    artname = getFrameText (tag, "TPE3");
  if (artname == NULL)
    artname = getFrameText (tag, "TPE4");
  if (artname == NULL)
    artname = getFrameText (tag, "TCOM");
  return artname;
}

gchar *
getTitle (struct id3_tag * tag)
{
  return getFrameText (tag, "TIT2");
}

gchar *
getAlbum (struct id3_tag * tag)
{
  return getFrameText (tag, "TALB");
}

gchar *
getYear (struct id3_tag * tag)
{
  gchar *year = NULL;

  year = getFrameText (tag, "TYER");
  if (year == NULL)
    {
      year = getFrameText (tag, "TDRC");
    }
  if (year == NULL)
    {
      year = g_strdup ("None");
    }
  return year;
}

gchar *
getGenre (struct id3_tag * tag)
{
  return getFrameText (tag, "TCON");
}

int
getSonglen (struct id3_tag *tag)
{
  gchar *timetext;
  long milliseconds;
  int seconds;

  timetext = getFrameText (tag, "TLEN");
  if (timetext == NULL)
    return -1;

  // g_debug("Found time tag TLEN: %s ms ... ", timetext);
  milliseconds = atol (timetext);
  g_free (timetext);

  if (milliseconds > 0)
    {
      seconds = (int) milliseconds / 1000;
      // g_debug("%d milliseconds is %d seconds.\n", milliseconds, seconds);
      return seconds;
    }

  g_debug ("ID3v2 TLEN tag time was 0\n");

  return -1;
}

gchar *
getTracknum (struct id3_tag * tag)
{
  gchar trackno[40];
  gchar *trackstr = getFrameText (tag, "TRCK");
  gchar *posstr = getFrameText (tag, "TPOS");
  gint i;

  if (trackstr == NULL)
    {
      return NULL;
    }
  trackno[0] = '\0';
  // Take care of any a/b formats
  for (i = 0; i < strlen (trackstr); i++)
    {
      if (trackstr[i] == '/')
	{
	  // Terminate it at switch character
	  trackstr[i] = '\0';
	  break;
	}
    }
  // "Part of set" variable
  if (posstr != NULL)
    {
      // Same a/b format problem again
      for (i = 0; i < strlen (posstr); i++)
	{
	  if (posstr[i] == '/')
	    {
	      // Terminate it at switch character
	      posstr[i] = '\0';
	      break;
	    }
	}
      strncpy (trackno, posstr, sizeof (trackno));
      if (strlen (trackstr) == 1)
	{
	  strcat (trackno, "0");
	}
      strncat (trackno, trackstr, sizeof (trackno) - strlen (trackno) - 1);
      g_free (trackstr);
      g_free (posstr);
    }
  else
    {
      strncpy (trackno, trackstr, sizeof (trackno));
      g_free (trackstr);
    }
  // Terminate and return
  trackno[sizeof (trackno) - 1] = '\0';
  return g_strdup (trackno);
}

gchar *
getOrigFilename (struct id3_tag * tag)
{
  return getFrameText (tag, "TOFN");
}
