/*****************************************************************
 * gmerlin - a general purpose multimedia framework and applications
 *
 * Copyright (c) 2001 - 2012 Members of the Gmerlin project
 * gmerlin-general@lists.sourceforge.net
 * http://gmerlin.sourceforge.net
 *
 * This program 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 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, see <http://www.gnu.org/licenses/>.
 * *****************************************************************/

#include <string.h>
#include <gavl/metatags.h>
// #include <gmerlin/bgplug.h>
// #include <gmerlin/http.h>

#include "server.h"

void icy_update_metadata(icy_t * m, const gavl_dictionary_t * met)
  {
  int len;
  const char * artist;
  const char * title;
  const char * label;
  const char * station;
  char * tmp_string;
  char * stream_title;

  artist  = gavl_dictionary_get_string(met, GAVL_META_ARTIST);
  title   = gavl_dictionary_get_string(met, GAVL_META_TITLE);
  label   = gavl_dictionary_get_string(met, GAVL_META_LABEL);
  station = gavl_dictionary_get_string(met, GAVL_META_STATION);

  //  fprintf(stderr, "Update metadata:\n");
  //  gavl_dictionary_dump(met, 0);
  
  if(artist && title)
    stream_title = bg_sprintf("%s - %s", artist, title);
  else if(label)
    stream_title = gavl_strdup(label);
  else if(title)
    stream_title = gavl_strdup(title);
  else if(station)
    stream_title = gavl_strdup(station);
  else
    stream_title = gavl_strdup("Stream title");

  /* Convert charset */
  tmp_string = bg_convert_string(m->cnv, stream_title, -1, NULL);
  free(stream_title);
  stream_title = tmp_string;

  /* Escape */
  //  stream_title = gavl_escape_string(stream_title, ";'");

  /* Create buffer */
  len = 14 + // <len>StreamTitle='
    strlen(stream_title) +
    3;       // ';\0

  len = ((len + 15) / 16) * 16;

  m->buffer_len = len+1;

  if(m->buffer_alloc < m->buffer_len)
    {
    m->buffer_alloc = m->buffer_len + 32;
    m->buffer = realloc(m->buffer, m->buffer_alloc);
    }

  memset(m->buffer, 0, m->buffer_len);
  snprintf(m->buffer, m->buffer_len, "%cStreamTitle='%s';", len/16, stream_title);

//  gavl_hexdump((uint8_t*)m->buffer, m->buffer_len, 16);

  free(stream_title);
  }

void icy_init(icy_t * m,
              const gavf_program_header_t * ph,
              const gavl_dictionary_t * req,
              const gavl_dictionary_t * inline_metadata,
              gavl_dictionary_t * res)
  {
  const char * val;
  int send_metadata = 0;
  const gavl_compression_info_t * ci;
  
  m->cnv = bg_charset_converter_create("UTF-8", "ISO_8859-1");
  
  gavl_dictionary_get_int(req, "Icy-MetaData", &send_metadata);

  //  if(!send_metadata)
  //    return;
  
  //  bg_http_response_set_protocol(res, "ICY");
  
  /* Set ICY-specific header fields */
#if 0
  gavl_dictionary_set_string(res, "icy-notice1",
                    "<BR>This stream requires <a href=\"http://www.winamp.com/\">Winamp</a><BR>");
  gavl_dictionary_set_string(res, "icy-notice2",
                    "SHOUTcast Distributed Network Audio Server/Linux v1.9.5<BR>");
#endif
  if((val = gavl_dictionary_get_string(&ph->m, GAVL_META_STATION)))
    gavl_dictionary_set_string_nocopy(res, "icy-name",
                            bg_convert_string(m->cnv, val, -1, NULL));

  if((val = gavl_dictionary_get_string(&ph->m, GAVL_META_GENRE)))
    gavl_dictionary_set_string_nocopy(res, "icy-genre",
                            bg_convert_string(m->cnv, val, -1, NULL));

  if((val = gavl_dictionary_get_string(&ph->m, GAVL_META_RELURL)))
    gavl_dictionary_set_string(res, "icy-url", val);

  ci = &ph->streams[0].ci;

  gavl_dictionary_set_string(res, "Content-Type", NULL);
  
  if(ci->id == GAVL_CODEC_ID_MP3)
    gavl_dictionary_set_string(res, "content-type", "audio/mpeg");
  else if(ci->id == GAVL_CODEC_ID_AAC)
    {
    if(ci->flags & GAVL_COMPRESSION_SBR)
      gavl_dictionary_set_string(res, "content-type", "audio/aacp");
    else
      gavl_dictionary_set_string(res, "content-type", "audio/aac");
    }
  
  gavl_dictionary_set_string(res, "icy-pub", "1");
  
  if(ph->streams[0].ci.bitrate > 0)
    gavl_dictionary_set_int(res, "icy-br", ph->streams[0].ci.bitrate / 1000);

  if((val = gavl_dictionary_get_string(&ph->m, GAVL_META_COMMENT)))
    gavl_dictionary_set_string(res, "icy-description",
                      bg_convert_string(m->cnv, val, -1, NULL));

  if(inline_metadata && (send_metadata > 0))
    {
    m->metaint = 16000;
    gavl_dictionary_set_int(res, "icy-metaint", m->metaint);
    icy_update_metadata(m, inline_metadata);
    }
  else
    {
    bg_charset_converter_destroy(m->cnv);
    m->cnv = NULL;
    }
  }

int icy_write(icy_t * m,
              const uint8_t * data, int len,
              gavf_io_t * io)
  {
  int bytes_written;
  int bytes;
  
  if(!m->metaint)
    return (gavf_io_write_data(io, data, len) == len);

  // fprintf(stderr, "icy_write\n");
  
  bytes_written = 0;
  while(bytes_written < len)
    {
    bytes = len - bytes_written;
    
    if(m->byte_counter + bytes > m->metaint)
      {
      /* Write data */
      bytes = m->metaint - m->byte_counter;
      }

    if(bytes &&
       (gavf_io_write_data(io, data + bytes_written, bytes) < bytes))
      return 0;
    
    m->byte_counter += bytes;
    bytes_written += bytes;
    
    if(m->byte_counter == m->metaint)
      {
      /* Write metadata */
      if(gavf_io_write_data(io, (uint8_t*)m->buffer, m->buffer_len) < m->buffer_len)
        return 0;
      /* Reset */
      m->byte_counter = 0;
      m->buffer[0] = 0;
      m->buffer_len = 1;
      }
    }
  return len;
  }

void icy_free(icy_t * m)
  {
  if(m->buffer)
    free(m->buffer);
  if(m->cnv)
    bg_charset_converter_destroy(m->cnv);
  }
