#include "rsi_flac/flac_tag.h"
#include "rsi_flac/flac_entry_point.h"

extern "C"
{
  #include <FLAC/all.h>
}

#include "WDL/win32_utf8.h"

RSI_FlacTag::RSI_FlacTag()
  : m_file(NULL)
  , m_metadata(false, WDL_StringKeyedArray<char *>::freecharptr)
{}

RSI_FlacTag::~RSI_FlacTag()
{
  if (m_file) delete m_file;
  m_metadata.DeleteAll();
}

bool RSI_FlacTag::Open(const char *filename)
{
  bool res = false;
  m_fn.Set(filename);

  int rmode, rbufsize, rnbufs;
  RSI_GetDiskReadMode(&rmode, &rbufsize, &rnbufs);
  m_file = new WDL_FileRead(filename, rmode, rbufsize, rnbufs);

  if (!m_file->IsOpen())
  {
    return false;
  }

#ifdef _WIN32
  flac_internal_set_utf8_filenames(true);
#endif

  FLAC__Metadata_Chain *chain = FLAC__metadata_chain_new();
  if (FLAC__metadata_chain_read(chain, m_fn.Get()))
  {
    FLAC__Metadata_Iterator *it = FLAC__metadata_iterator_new();
    FLAC__metadata_iterator_init(it, chain);

    WDL_FastString ss;
    while (FLAC__metadata_iterator_next(it))
    {
      FLAC__StreamMetadata *meta = FLAC__metadata_iterator_get_block(it);
      if (meta->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
      {
        for (int i = 0; i < (int)meta->data.vorbis_comment.num_comments; i++)
        {
          ss.SetRaw((const char *)meta->data.vorbis_comment.comments[i].entry,
            meta->data.vorbis_comment.comments[i].length);

          if (!strnicmp(ss.Get(), "TITLE=", 6))
          {
            ss.DeleteSub(0, 6);
            m_metadata.Insert("TITLE", strdup(ss.Get()));
          }
          else if (!strnicmp(ss.Get(), "ALBUM=", 6))
          {
            ss.DeleteSub(0, 6);
            m_metadata.Insert("ALBUM", strdup(ss.Get()));
          }
          else if (!strnicmp(ss.Get(), "TRACKNUMBER=", 12))
          {
            ss.DeleteSub(0, 12);
            m_metadata.Insert("TRACKNUMBER", strdup(ss.Get()));
          }
          else if (!strnicmp(ss.Get(), "ARTIST=", 7))
          {
            ss.DeleteSub(0, 7);
            m_metadata.Insert("ARTIST", strdup(ss.Get()));
          }
          else if (!strnicmp(ss.Get(), "DESCRIPTION=", 12))
          {
            ss.DeleteSub(0, 12);
            m_metadata.Insert("DESCRIPTION", strdup(ss.Get()));
          }
          else if (!strnicmp(ss.Get(), "GENRE=", 6))
          {
            ss.DeleteSub(0, 6);
            m_metadata.Insert("GENRE", strdup(ss.Get()));
          }
          else if (!strnicmp(ss.Get(), "DATE=", 5))
          {
            ss.DeleteSub(0, 5);
            m_metadata.Insert("DATE", strdup(ss.Get()));
          }
        }
      }
    }
    FLAC__metadata_iterator_delete(it); res = true;
  }

  FLAC__metadata_chain_delete(chain);

  return res;
}

const char *RSI_FlacTag::GetType() const
{
  return "FLAC";
}

const char *RSI_FlacTag::GetTitle() const
{
  if (strcmp(m_metadata.Get("TITLE", ""), ""))
  {
    return m_metadata.Get("TITLE", "");
  }
  return m_fn.get_filepart();
}

const char *RSI_FlacTag::GetArtist() const
{
  return m_metadata.Get("ARTIST", "");
}

const char *RSI_FlacTag::GetAlbum() const
{
  return m_metadata.Get("ALBUM", "");
}

const char *RSI_FlacTag::GetGenre() const
{
  return m_metadata.Get("GENRE", "");
}

const char *RSI_FlacTag::GetTrack() const
{
  return m_metadata.Get("TRACKNUMBER", "");
}

const char *RSI_FlacTag::GetYear() const
{
  return m_metadata.Get("DATE", "");
}

const char *RSI_FlacTag::GetComment() const
{
  return m_metadata.Get("DESCRIPTION", "");
}

WDL_INT64 RSI_FlacTag::GetFileSize() const
{
  return m_file->GetSize();
}

const char *RSI_FlacTag::GetFileName() const
{
  return m_fn.get_filepart();
}

const char *RSI_FlacTag::GetFilePath() const
{
  return m_fn.Get();
}

const char *RSI_FlacTag::GetFileExtension() const
{
  return m_fn.get_fileext();
}
