/* GStreamer
 * Copyright (C) 2011 Axis Communications <dev-gstreamer@axis.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

/**
 * SECTION:element-curlsftpsink
 * @title: curlsftpsink
 * @short_description: sink that uploads data to a server using libcurl
 * @see_also:
 *
 * This is a network sink that uses libcurl as a client to upload data to
 * a SFTP (SSH File Transfer Protocol) server.
 *
 * ## Example launch line
 *
 * Upload a file to /home/john/sftp_tests/
 *
 * |[
 * gst-launch-1.0 filesrc location=/home/jdoe/some.file ! curlsftpsink  \
 *     file-name=some.file.backup  \
 *     user=john location=sftp://192.168.0.1/~/sftp_tests/  \
 *     ssh-auth-type=1 ssh-key-passphrase=blabla  \
 *     ssh-pub-keyfile=/home/jdoe/.ssh/id_rsa.pub  \
 *     ssh-priv-keyfile=/home/jdoe/.ssh/id_rsa  \
 *     create-dirs=TRUE
 * ]|
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "gstcurlsshsink.h"
#include "gstcurlsftpsink.h"

#include <curl/curl.h>
#include <string.h>
#include <stdio.h>

#ifdef G_OS_WIN32
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#endif
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

/* Default values */
#define GST_CAT_DEFAULT    gst_curl_sftp_sink_debug


/* Plugin specific settings */

GST_DEBUG_CATEGORY_STATIC (gst_curl_sftp_sink_debug);

enum
{
  PROP_0,
  PROP_CREATE_DIRS
};

/* private functions */
static void gst_curl_sftp_sink_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_curl_sftp_sink_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);
static void gst_curl_sftp_sink_finalize (GObject * gobject);

static gboolean set_sftp_options_unlocked (GstCurlBaseSink * curlbasesink);
static gboolean set_sftp_dynamic_options_unlocked (GstCurlBaseSink *
    curlbasesink);


#define gst_curl_sftp_sink_parent_class parent_class
G_DEFINE_TYPE (GstCurlSftpSink, gst_curl_sftp_sink, GST_TYPE_CURL_SSH_SINK);

static void
gst_curl_sftp_sink_class_init (GstCurlSftpSinkClass * klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  GstCurlBaseSinkClass *gstcurlbasesink_class = (GstCurlBaseSinkClass *) klass;
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);

  GST_DEBUG_CATEGORY_INIT (gst_curl_sftp_sink_debug, "curlsftpsink", 0,
      "curl sftp sink element");

  GST_DEBUG_OBJECT (klass, "class_init");

  gst_element_class_set_static_metadata (element_class,
      "Curl sftp sink",
      "Sink/Network",
      "Upload data over the SFTP protocol using libcurl",
      "Sorin L. <sorin@axis.com>");

  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_curl_sftp_sink_finalize);

  gobject_class->set_property = gst_curl_sftp_sink_set_property;
  gobject_class->get_property = gst_curl_sftp_sink_get_property;

  gstcurlbasesink_class->set_protocol_dynamic_options_unlocked =
      set_sftp_dynamic_options_unlocked;
  gstcurlbasesink_class->set_options_unlocked = set_sftp_options_unlocked;

  g_object_class_install_property (gobject_class, PROP_CREATE_DIRS,
      g_param_spec_boolean ("create-dirs", "Create missing directories",
          "Attempt to create missing directories",
          FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}

static void
gst_curl_sftp_sink_init (GstCurlSftpSink * sink)
{
}

static void
gst_curl_sftp_sink_finalize (GObject * gobject)
{
  GST_DEBUG ("finalizing curlsftpsink");
  G_OBJECT_CLASS (parent_class)->finalize (gobject);
}

static gboolean
set_sftp_dynamic_options_unlocked (GstCurlBaseSink * basesink)
{
  gchar *tmp = g_strdup_printf ("%s%s", basesink->url, basesink->file_name);
  CURLcode curl_err = CURLE_OK;

  curl_err = curl_easy_setopt (basesink->curl, CURLOPT_URL, tmp);
  g_free (tmp);
  if (curl_err != CURLE_OK) {
    basesink->error = g_strdup_printf ("failed to set URL: %s",
        curl_easy_strerror (curl_err));
    return FALSE;
  }

  return TRUE;
}

static gboolean
set_sftp_options_unlocked (GstCurlBaseSink * basesink)
{
  GstCurlSftpSink *sink = GST_CURL_SFTP_SINK (basesink);
  GstCurlSshSinkClass *parent_class;
  CURLcode curl_err = CURLE_OK;

  if ((curl_err =
          curl_easy_setopt (basesink->curl, CURLOPT_UPLOAD, 1L)) != CURLE_OK) {
    basesink->error = g_strdup_printf ("failed to prepare for upload: %s",
        curl_easy_strerror (curl_err));
    return FALSE;
  }

  if (sink->create_dirs) {
    if ((curl_err = curl_easy_setopt (basesink->curl,
                CURLOPT_FTP_CREATE_MISSING_DIRS, 1L)) != CURLE_OK) {
      basesink->error =
          g_strdup_printf ("failed to set create missing dirs: %s",
          curl_easy_strerror (curl_err));
      return FALSE;
    }
  }

  parent_class = GST_CURL_SSH_SINK_GET_CLASS (sink);

  /* chain to parent as well */
  return parent_class->set_options_unlocked (basesink);
}

static void
gst_curl_sftp_sink_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstCurlSftpSink *sink;
  GstState cur_state;

  g_return_if_fail (GST_IS_CURL_SFTP_SINK (object));
  sink = GST_CURL_SFTP_SINK (object);

  gst_element_get_state (GST_ELEMENT (sink), &cur_state, NULL, 0);
  if (cur_state != GST_STATE_PLAYING && cur_state != GST_STATE_PAUSED) {
    GST_OBJECT_LOCK (sink);

    switch (prop_id) {
      case PROP_CREATE_DIRS:
        sink->create_dirs = g_value_get_boolean (value);
        GST_DEBUG_OBJECT (sink, "create-dirs set to %d", sink->create_dirs);
        break;

      default:
        GST_DEBUG_OBJECT (sink, "invalid property id %d", prop_id);
        break;
    }

    GST_OBJECT_UNLOCK (sink);
  }
}

static void
gst_curl_sftp_sink_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstCurlSftpSink *sink;

  g_return_if_fail (GST_IS_CURL_SFTP_SINK (object));
  sink = GST_CURL_SFTP_SINK (object);

  switch (prop_id) {
    case PROP_CREATE_DIRS:
      g_value_set_boolean (value, sink->create_dirs);
      break;

    default:
      GST_DEBUG_OBJECT (sink, "invalid property id");
      break;
  }
}
