/*
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1
 * 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 Lesser General Public License for more details.
 */

#include "./cshtype.h"

#include <string.h>

#include "../shtype/shtype-from-gst-caps.hpp"
#include "../shtype/shtype.hpp"
#include "./cshtype_internal.hpp"

namespace sh4lt {
CShType::CShType(const char* media, const char* label, const char* group_label)
    : shtype_(media, label, group_label) {}

CShType::CShType(ShType shtype) : shtype_(shtype) {}

}  // namespace sh4lt

Sh4ltShType sh4lt_make_shtype(const char* media, const char* label, const char* group_label) {
  sh4lt::CShType* res = new sh4lt::CShType(media, label, group_label);
  if (res->shtype_) return static_cast<void*>(res);
  delete res;
  return nullptr;
}

void sh4lt_delete_shtype(Sh4ltShType shtype) { delete static_cast<sh4lt::CShType*>(shtype); }

char* sh4lt_get_path(const char* label, const char* group) {
  const auto path = sh4lt::ShType::get_path(label, group).string();
  char* res = static_cast<char*>(malloc((path.size() + 1) * sizeof(char)));
  strcpy(res, path.c_str());
  return res;
}

char* sh4lt_get_log_for_path_issue() {
  const auto msg = sh4lt::ShType::get_log_for_path_issue();
  char* res = static_cast<char*>(malloc((msg.size() + 1) * sizeof(char)));
  strcpy(res, msg.c_str());
  return res;
}

char* sh4lt_shtype_media(const Sh4ltShType shtype) {
  auto tmp = static_cast<sh4lt::CShType*>(shtype)->shtype_.media();
  char* res = static_cast<char*>(malloc((tmp.size() + 1) * sizeof(char)));
  strcpy(res, tmp.c_str());
  return res;
}

char* sh4lt_shtype_label(const Sh4ltShType shtype) {
  auto tmp = static_cast<sh4lt::CShType*>(shtype)->shtype_.label();
  char* res = static_cast<char*>(malloc((tmp.size() + 1) * sizeof(char)));
  strcpy(res, tmp.c_str());
  return res;
}

char* sh4lt_shtype_group(const Sh4ltShType shtype) {
  auto tmp = static_cast<sh4lt::CShType*>(shtype)->shtype_.group();
  char* res = static_cast<char*>(malloc((tmp.size() + 1) * sizeof(char)));
  strcpy(res, tmp.c_str());
  return res;
}

char* sh4lt_shtype_description(const Sh4ltShType shtype) {
  auto tmp = static_cast<sh4lt::CShType*>(shtype)->shtype_.description();
  char* res = static_cast<char*>(malloc((tmp.size() + 1) * sizeof(char)));
  strcpy(res, tmp.c_str());
  return res;
}

char* sh4lt_shtype_default_group() {
  auto tmp = sh4lt::ShType::default_group();
  char* res = static_cast<char*>(malloc((tmp.size() + 1) * sizeof(char)));
  strcpy(res, tmp.c_str());
  return res;
}

void sh4lt_shtype_set_description(const Sh4ltShType shtype, const char* description) {
  static_cast<sh4lt::CShType*>(shtype)->shtype_.set_description(description ? description
                                                                            : std::string());
}

void sh4lt_shtype_set_str_prop(const Sh4ltShType shtype, const char* key, const char* value) {
  static_cast<sh4lt::CShType*>(shtype)->shtype_.set_prop(key, value);
}

void sh4lt_shtype_set_int_prop(const Sh4ltShType shtype, const char* key, int64_t value) {
  static_cast<sh4lt::CShType*>(shtype)->shtype_.set_prop(key, value);
}

void sh4lt_shtype_set_float_prop(const Sh4ltShType shtype, const char* key, double value) {
  static_cast<sh4lt::CShType*>(shtype)->shtype_.set_prop(key, value);
}

void sh4lt_shtype_set_bool_prop(const Sh4ltShType shtype, const char* key, int value) {
  static_cast<sh4lt::CShType*>(shtype)->shtype_.set_prop(key, static_cast<bool>(value));
}

void sh4lt_shtype_set_custom_type(const Sh4ltShType shtype,
                                  const char* key,
                                  const char* custom_type) {
  static_cast<sh4lt::CShType*>(shtype)->shtype_.set_custom_type(key, custom_type);
}

char* sh4lt_shtype_get_str_prop(const Sh4ltShType shtype, const char* key) {
  auto tmp = static_cast<sh4lt::CShType*>(shtype)->shtype_.get_prop(key).as<std::string>();
  if (tmp.empty()) return nullptr;
  char* res = static_cast<char*>(malloc((tmp.size() + 1) * sizeof(char)));
  strcpy(res, tmp.c_str());
  return res;
}

int64_t sh4lt_shtype_get_int_prop(const Sh4ltShType shtype, const char* key) {
  return static_cast<sh4lt::CShType*>(shtype)->shtype_.get_prop(key).as<int64_t>();
}

double sh4lt_shtype_get_float_prop(const Sh4ltShType shtype, const char* key) {
  return static_cast<sh4lt::CShType*>(shtype)->shtype_.get_prop(key).as<double>();
}

int sh4lt_shtype_get_bool_prop(const Sh4ltShType shtype, const char* key) {
  return static_cast<sh4lt::CShType*>(shtype)->shtype_.get_prop(key).as<bool>();
}

char* sh4lt_shtype_get_custom_type(const Sh4ltShType shtype, const char* key) {
  auto tmp = static_cast<sh4lt::CShType*>(shtype)->shtype_.get_custom_type(key);
  if (tmp.empty()) return nullptr;
  char* res = static_cast<char*>(malloc((tmp.size() + 1) * sizeof(char)));
  strcpy(res, tmp.c_str());
  return res;
}

void sh4lt_shtype_get_properties(const Sh4ltShType shtype, char* properties[], size_t* size) {
  const auto tmp = static_cast<sh4lt::CShType*>(shtype)->shtype_.get_properties();
  size_t i = 0;
  *size = tmp.size();
  for (const auto& it : tmp) {
    char* res = static_cast<char*>(malloc((it.first.size() + 1) * sizeof(char)));
    strcpy(res, it.first.c_str());
    properties[i] = res;
    ++i;
  }
}

void sh4lt_shtype_get_custom_types(const Sh4ltShType shtype, char* types[], size_t* size) {
  const auto tmp = static_cast<sh4lt::CShType*>(shtype)->shtype_.get_custom_types();
  size_t i = 0;
  *size = tmp.size();
  for (const auto& it : tmp) {
    char* res = static_cast<char*>(malloc((it.first.size() + 1) * sizeof(char)));
    strcpy(res, it.first.c_str());
    types[i] = res;
    ++i;
  }
}

Sh4ltShType sh4lt_shtype_from_gst_caps(const char* gst_caps,
                                       const char* label,
                                       const char* group_label) {
  sh4lt::CShType* res =
      new sh4lt::CShType(sh4lt::shtype::shtype_from_gst_caps(gst_caps, label, group_label, ""));
  if (res->shtype_) return static_cast<void*>(res);
  delete res;
  return nullptr;
}

char* sh4lt_shtype_to_gst_caps(const Sh4ltShType shtype) {
  auto tmp = sh4lt::shtype::shtype_to_gst_caps(static_cast<sh4lt::CShType*>(shtype)->shtype_);
  if (tmp.empty()) return nullptr;
  char* res = static_cast<char*>(malloc((tmp.size() + 1) * sizeof(char)));
  strcpy(res, tmp.c_str());
  return res;
}

char* sh4lt_shtype_serialize(const Sh4ltShType shtype) {
  auto tmp = sh4lt::ShType::serialize(static_cast<sh4lt::CShType*>(shtype)->shtype_);
  if (tmp.empty()) return nullptr;
  char* res = static_cast<char*>(malloc((tmp.size() + 1) * sizeof(char)));
  strcpy(res, tmp.c_str());
  return res;
}

Sh4ltShType sh4lt_shtype_deserialize(const char* serialized) {
  sh4lt::CShType* res = new sh4lt::CShType(sh4lt::ShType::deserialize(serialized));
  if (res->shtype_) return static_cast<void*>(res);
  delete res;
  return nullptr;
}
