#ifndef UTF8STRING__H
#define UTF8STRING__H

#include <string>
#include <vector>
#include <array>
#include "fmt/core.h"

namespace util
{

class utf8char : public std::array<char, 4>
{
  public :

  utf8char();
  utf8char(const std::string & other);
  utf8char(const char * other);
  utf8char & operator=(char other);
  utf8char & operator=(const std::string & other);
  bool operator==(char other) const;
  bool operator==(const std::string & other) const;
  bool operator!=(char other) const;
};

class utf8string : public std::vector<utf8char>
{
  using std::vector<utf8char>::vector;
  public :

  utf8string & operator=(const std::string & other);
  utf8string & operator=(const char * const other);
  bool operator==(const std::string & other) const;
  void replace(utf8char from, utf8char to);
};

};

template <>
struct fmt::formatter<util::utf8char>
{
  constexpr auto parse(format_parse_context & ctx) { return ctx.begin(); }

  template <typename FormatContext>
  auto format(const util::utf8char & c, FormatContext & ctx)
  {
    std::string result = "";
    for (char cc : c)
      if (cc)
        result += cc;
    return format_to(ctx.out(), "{}", result);
  }
};

template <>
struct fmt::formatter<util::utf8string>
{
  constexpr auto parse(format_parse_context & ctx) { return ctx.begin(); }

  template <typename FormatContext>
  auto format(const util::utf8string & s, FormatContext & ctx)
  {
    std::string result;
    for (auto & c : s)
      result = fmt::format("{}{}", result, c);
    return format_to(ctx.out(), "{}", result);
  }
};

#endif