/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2025 Artem Pavlenko
 *
 * This library 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 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser 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
 *
 *****************************************************************************/

#ifndef MAPNIK_FONT_FEATURE_SETTINGS_HPP
#define MAPNIK_FONT_FEATURE_SETTINGS_HPP

// mapnik
#include <mapnik/config.hpp>

// stl
#include <vector>
#include <memory>
#include <limits>
#include <ostream>

#include <mapnik/warning.hpp>
MAPNIK_DISABLE_WARNING_PUSH
#include <mapnik/warning_ignore.hpp>
#include <harfbuzz/hb.h>
MAPNIK_DISABLE_WARNING_POP

// EqualityComparable
inline bool operator==(hb_feature_t const& lhs, hb_feature_t const& rhs)
{
    return (lhs.tag == rhs.tag && lhs.value == rhs.value && lhs.start == rhs.start && lhs.end == rhs.end);
}

namespace mapnik {

class MAPNIK_DECL font_feature_settings
{
  public:
    using font_feature = hb_feature_t;
    using feature_vector = std::vector<font_feature>;
    using feature_iterator = feature_vector::iterator;

    font_feature_settings(std::string const& features);
    font_feature_settings();

    void from_string(std::string const& features);
    std::string to_string() const;

    void append(std::string const& feature);
    void append(font_feature const& feature) { features_.push_back(feature); }

    font_feature const* get_features() const { return features_.data(); }
    feature_vector::size_type count() const { return features_.size(); }
    feature_vector const& features() const { return features_; }

  private:
    feature_vector features_;
};

template<typename charT, typename traits>
std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& s,
                                              mapnik::font_feature_settings const& f)
{
    s << f.to_string();
    return s;
}

inline bool operator==(font_feature_settings const& lhs, font_feature_settings const& rhs)
{
    return (lhs.features() == rhs.features());
}

constexpr unsigned int font_feature_range_global_start = 0u;
static unsigned int const font_feature_range_global_end = std::numeric_limits<unsigned int>::max();

#include <mapnik/warning.hpp>
MAPNIK_DISABLE_WARNING_PUSH
#include <mapnik/warning_ignore.hpp>
constexpr hb_feature_t font_feature_liga_off = {HB_TAG('l', 'i', 'g', 'a'),
                                                0,
                                                font_feature_range_global_start,
                                                font_feature_range_global_end};
MAPNIK_DISABLE_WARNING_POP

} // namespace mapnik

#endif // MAPNIK_FONT_FEATURE_SETTINGS_HPP
