#pragma once

// subtitleeditor -- a tool to create or edit subtitle
//
// https://kitone.github.io/subtitleeditor/
// https://github.com/kitone/subtitleeditor/
//
// Copyright @ 2005-2018, kitone
//
// 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 3 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/>.

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */

#include <gtkmm.h>
#include <iostream>
#include <sstream>
#include "debug.h"
#include "i18n.h"

// Check whether a gtkmm version equal to or greater than
// major.minor.micro is present.
#define GTKMM_CHECK_VERSION(major, minor, micro)                        \
  (GTKMM_MAJOR_VERSION > (major) ||                                     \
   (GTKMM_MAJOR_VERSION == (major) && GTKMM_MINOR_VERSION > (minor)) || \
   (GTKMM_MAJOR_VERSION == (major) && GTKMM_MINOR_VERSION == (minor) && \
    GTKMM_MICRO_VERSION >= (micro)))

// Return one of the values depending on whether
// environment variable SE_DEV is defined or not.
#define SE_DEV_VALUE(value, dev_value) \
  ((Glib::getenv("SE_DEV") != "1") ? (value) : (dev_value))

// the profile name for the config dir
// ~/config/subtitleeditor/{profile}
void set_profile_name(const Glib::ustring &profile);

// ~/.config/subtitleeditor/{profile}/{file}
// XDG Base Directory Specification
Glib::ustring get_config_dir(const Glib::ustring &file);

// convertir str en n'importe quel type
template <class T>
bool from_string(const std::string &src, T &dest) {
  std::istringstream s(src);

  bool state = s >> dest != 0;

  if (!state)
    se_dbg_msg(SE_DBG_UTILITY, "string:'%s'failed.", src.c_str());

#ifdef DEBUG
  g_return_val_if_fail(state, false);
#endif
  return state;
}

// convertir str en n'importe quel type
template <class T>
bool from_string(const Glib::ustring &src, T &dest) {
  std::istringstream s(src);

  bool state = static_cast<bool>(s >> dest) != 0;

  if (!state)
    se_dbg_msg(SE_DBG_UTILITY, "string:'%s'failed.", src.c_str());

#ifdef DEBUG
  g_return_val_if_fail(state, false);
#endif
  return state;
}

// convertir n'importe quoi en string
template <class T>
std::string to_string(const T &src) {
  std::ostringstream oss;
  oss << src;

  return oss.str();
}

Glib::ustring build_message(const gchar *str, ...);

void dialog_warning(const Glib::ustring &primary_text,
                    const Glib::ustring &secondary_text);

void dialog_error(const Glib::ustring &primary_text,
                  const Glib::ustring &secondary_text);

namespace utility {

template <class T>
inline void clamp(T &val, const T &min, const T &max) {
  val = CLAMP(val, min, max);
}

bool string_to_bool(const std::string &str);

int string_to_int(const std::string &str);

int string_to_long(const std::string &str);

double string_to_double(const std::string &str);

void split(const std::string &str, const char &c,
           std::vector<std::string> &array, int max = -1);

// Split with best utf8 support...
void usplit(const Glib::ustring &str,
            const Glib::ustring::value_type &delimiter,
            std::vector<Glib::ustring> &container);

// Search and replace function.
void replace(Glib::ustring &text, const Glib::ustring &pattern,
             const Glib::ustring &replace_by);

// Search and replace function.
void replace(std::string &text, const std::string &pattern,
             const std::string &replace_by);

// transforme test/file.srt en /home/toto/test/file.srt
Glib::ustring create_full_path(const Glib::ustring &path);

// Get the number of characters per second.
// msec = SubtitleTime::totalmsecs
double get_characters_per_second(const Glib::ustring &text, const long msecs);

// Count characters in a subtitle the way they need to be counted
// for subtitle timing.
unsigned int get_text_length_for_timing(const Glib::ustring &text);

// Calculate the minimum acceptable duration for a string of this length.
unsigned long get_min_duration_msecs(unsigned long textlen, double maxcps);
unsigned long get_min_duration_msecs(const Glib::ustring &text, double maxcps);

// get number of characters for each line in the text
std::vector<int> get_characters_per_line(const Glib::ustring &text);

// get a text stripped from tags
Glib::ustring get_stripped_text(const Glib::ustring &text);

void set_transient_parent(Gtk::Window &window);

Glib::ustring add_or_replace_extension(const Glib::ustring &filename,
                                       const Glib::ustring &extension);
}  // namespace utility
