# Copyright (c) 2023 M.J.N. Corino, The Netherlands
#
# This software is released under the MIT license.

###
# wxRuby3 wxWidgets interface director
###

module WXRuby3

  class Director

    class Font < Director

      def setup
        super
        spec.items << 'wxFontInfo'
        spec.gc_as_untracked 'wxFontInfo'
        spec.gc_as_untracked 'wxFont'
        # all but the default ctor require a running App
        spec.require_app 'wxFont::wxFont(const wxFont &)',
                         'wxFont::wxFont(const wxFontInfo &)',
                         'wxFont::wxFont(int, wxFontFamily, wxFontStyle, wxFontWeight, bool, const wxString &, wxFontEncoding)',
                         'wxFont::wxFont(const wxSize &, wxFontFamily, wxFontStyle, wxFontWeight, bool, const wxString &, wxFontEncoding)',
                         'wxFont::wxFont(const wxString &)',
                         # and these statics
                         'wxFont::GetDefaultEncoding',
                         'wxFont::SetDefaultEncoding'
        spec.rename_for_ruby 'create' => 'wxFont::New'
        spec.ignore [ 'wxFont::SetNativeFontInfo(const wxNativeFontInfo &)', 'wxFont::GetNativeFontInfo', 'wxFont::operator!=' ]
        spec.ignore 'wxFont::wxFont(const wxNativeFontInfo &)',
                    'wxFont::New(const wxNativeFontInfo &)'
        if Config.instance.wx_port == :wxqt
          # not implemented
          spec.ignore 'wxFont::AddPrivateFont'
        end
        # ignore stock objects here; need special init in app mainloop
        spec.ignore %w[
          wxNORMAL_FONT
          wxSMALL_FONT
          wxITALIC_FONT
          wxSWISS_FONT
          wxTheFontList
          ]
        # for methods altering the font and returning reference to self
        spec.map 'wxFont &' => 'Wx::Font' do
          map_out code: '$result = self; wxUnusedVar($1);'
        end
        # for methods setting up the fontinfo and returning reference to self
        spec.map 'wxFontInfo &' => 'Wx::FontInfo' do
          map_out code: '$result = self; wxUnusedVar($1);'
        end
        spec.add_wrapper_code <<~__HEREDOC
          WXRUBY_EXPORT bool wxRuby_IsRubyFont(VALUE rbfont)
          {
            swig_class *sklass_font = (swig_class *) SWIGTYPE_p_wxFont->clientdata;
            swig_class *sklass_font_info = (swig_class *) SWIGTYPE_p_wxFontInfo->clientdata;
            return TYPE(rbfont) == T_DATA && 
                    (rb_obj_is_kind_of(rbfont, sklass_font->klass) || 
                     rb_obj_is_kind_of(rbfont, sklass_font_info->klass));
          }
          WXRUBY_EXPORT wxFont wxRuby_FontFromRuby(VALUE rbfont)
          {
            if (TYPE(rbfont) == T_DATA)
            {
              void *ptr;
              swig_class *sklass_font_info = (swig_class *) SWIGTYPE_p_wxFontInfo->clientdata;
              if (rb_obj_is_kind_of(rbfont, sklass_font_info->klass))
              {
                int res = SWIG_ConvertPtr(rbfont, &ptr, SWIGTYPE_p_wxFontInfo, 0);
                if (SWIG_IsOK(res) && ptr) 
                {
                  return wxFont(*reinterpret_cast<wxFontInfo *>(ptr));
                }
              }
              else
              {
                int res = SWIG_ConvertPtr(rbfont, &ptr, SWIGTYPE_p_wxFont, 0);
                if (SWIG_IsOK(res) && ptr) 
                {
                  return *reinterpret_cast<wxFont *>(ptr);
                }
              }
            }
            return wxFont();
          }
          WXRUBY_EXPORT VALUE wxRuby_FontToRuby(const wxFont& font)
          {
            return SWIG_NewPointerObj(new wxFont(font), SWIGTYPE_p_wxFont, SWIG_POINTER_OWN);
          }
          __HEREDOC
        # implement wxTheFontList methods as static methods of Wx::Font
        spec.add_extend_code 'wxFont', <<~__HEREDOC
          static wxFont * find_or_create_font(int point_size, wxFontFamily family, wxFontStyle style, wxFontWeight weight, bool underline=false, const wxString &facename=wxEmptyString, wxFontEncoding encoding=wxFONTENCODING_DEFAULT)
          {
            return wxTheFontList->FindOrCreateFont(point_size, family, style, weight, underline, facename, encoding);
          }
          static wxFont *	find_or_create_font(const wxFontInfo &fontInfo)
          {
            return wxTheFontList->FindOrCreateFont(fontInfo);
          }
          __HEREDOC
        spec.do_not_generate :functions
      end

      def generator
        WXRuby3::FontGenerator.new(self)
      end
      protected :generator

    end # class Font

  end # class Director

  class FontGenerator < InterfaceGenerator

    def run
      # determine Ruby library font root for package
      rbfont_root = File.join(package.ruby_classes_path, 'font')
      Stream.transaction do
        f = CodeStream.new(File.join(rbfont_root, 'encoding.rb'))
        f << <<~__HEREDOC
          # --
          # This file is automatically generated by the WXRuby3 interface generator.
          # Do not alter this file.
          # --

          class Wx::Font
            # String names of the constants provided by C++
            # (extracted from enum defined in include/wx/fontenc.h)
            ENCODING_NAMES = %w[
          __HEREDOC
        f.indent(2) do
          def_item('wxFontEncoding').items.each do |item|
            unless item.name == 'wxFONTENCODING_SYSTEM'
              const_name = item.name.sub(/\AwxFONTENCODING_/, '')
              const_name.tr!('_', '-')
              const_name.sub!(/\AISO/, 'ISO-')
              f.puts const_name
            end
          end
        end
        f.indent { f.puts ']' }
        f.puts 'end'
      end
      # make sure to keep this last for the parallel builds synchronize on the *.i files
      super
    end

  end

end # module WXRuby3
