/*
 * Copyright (c) 2003, 2004 Jean-Yves Lefort
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include <stdio.h>
#include <errno.h>
#include <glib.h>
#include <glib/gi18n.h>
#include "sg-util.h"

/*** function declarations ***************************************************/

static gboolean st_m3u_write (GSList *uri_list,
			      GIOChannel *channel,
			      GError **err);

/*** API implementation ******************************************************/

/**
 * st_m3u_mktemp:
 * @prefix: the prefix to use for the temporary filename. Should be in
 * the form "streamtuner.handler.XXXXXX", where handler is the name of
 * the handler.
 * @uri_list: a list of URIs to write.
 * @err: a location to store errors, or %NULL.
 *
 * Creates a temporary M3U playlist. @uri_list must be a list of
 * strings which will be written to the playlist.
 *
 * Return value: the full pathname of the temporary file, or %NULL on
 * failure (in such case, @err will be set).  The pathname should be
 * freed when it is no longer needed.
 **/
char *
st_m3u_mktemp (const char *prefix, GSList *uri_list, GError **err)
{
  GError *tmp_err = NULL;
  GIOChannel *channel = NULL;
  char *filename = NULL;
  char *m3uname = NULL;
  int fd;
  gboolean status;

  g_return_val_if_fail(prefix != NULL, NULL);
  
  fd = g_file_open_tmp(prefix, &filename, &tmp_err);
  if (fd == -1)
    {
      g_set_error(err, 0, 0, _("unable to create a temporary file: %s"),
		  tmp_err->message);
      g_error_free(tmp_err);
      return NULL;
    }

  channel = g_io_channel_unix_new(fd);
  
  if (g_io_channel_set_encoding(channel, NULL, &tmp_err) != G_IO_STATUS_NORMAL)
    {
      g_set_error(err, 0, 0, _("unable to unset the encoding of the temporary file: %s"),
		  tmp_err->message);
      g_error_free(tmp_err);
      goto end;
    }

  if (! st_m3u_write(uri_list, channel, &tmp_err))
    {
      g_set_error(err, 0, 0, _("unable to write the playlist to a temporary file: %s"),
		  tmp_err->message);
      g_error_free(tmp_err);
      goto end;
    }

  status = g_io_channel_shutdown(channel, TRUE, &tmp_err) == G_IO_STATUS_NORMAL;
  g_io_channel_unref(channel);
  channel = NULL;

  if (! status)
    {
      g_set_error(err, 0, 0, _("unable to close the temporary file: %s"),
		  tmp_err->message);
      g_error_free(tmp_err);
      goto end;
    }

  m3uname = g_strconcat(filename, ".m3u", NULL);
  if (rename(filename, m3uname) < 0)
    {
      g_set_error(err, 0, 0, _("unable to rename the temporary file: %s"),
		  g_strerror(errno));
      g_free(m3uname);
      m3uname = NULL;
      goto end;
    }

 end:
  if (channel)
    {
      g_io_channel_shutdown(channel, TRUE, NULL);	/* ignore errors */
      g_io_channel_unref(channel);
    }
  g_free(filename);
  
  return m3uname;
}

/*** private implementation **************************************************/

static gboolean
st_m3u_write (GSList *uri_list, GIOChannel *channel, GError **err)
{
  GSList *l;

  g_return_val_if_fail(channel != NULL, FALSE);

  if (g_io_channel_write_chars(channel, "#M3U\n", -1, NULL, err) != G_IO_STATUS_NORMAL)
    return FALSE;

  SG_LIST_FOREACH(l, uri_list)
    {
      gboolean status;
      char *line;

      line = g_strdup_printf("%s\n", (const char *) l->data);
      status = g_io_channel_write_chars(channel, line, -1, NULL, err);
      g_free(line);

      if (! status)
	return FALSE;
    }

  return TRUE;
}
