# Copyright (c) 2023 M.J.N. Corino, The Netherlands
#
# This software is released under the MIT license.
# 
# Some parts are
# Copyright 2004-2007, wxRuby development team
# released under the MIT-like wxRuby2 license

# Copyright 2004-2006 by Kevin Smith
# released under the MIT-style wxruby2 license

require_relative './ext'

# Controller class which creates and manages all windows.
class Wx::App

  if Wx::PLATFORM == 'WXOSX'
    class << self
      # provide aliases for macosx specials
      alias :mac_about_menu_itemid= :set_mac_about_menu_itemid
      alias :mac_about_menu_itemid :get_mac_about_menu_itemid
      alias :mac_preferences_menu_itemid= :set_mac_preferences_menu_itemid
      alias :mac_preferences_menu_itemid :get_mac_preferences_menu_itemid
      alias :mac_exit_menu_itemid= :set_mac_exit_menu_itemid
      alias :mac_exit_menu_itemid :get_mac_exit_menu_itemid
      alias :mac_help_menu_title= :set_mac_help_menu_title
      alias :mac_help_menu_title :get_mac_help_menu_title
      alias :mac_window_menu_title= :set_mac_window_menu_title
      alias :mac_window_menu_title :get_mac_window_menu_title
    end
  end

  # convenience method to retrieve global Wx::App instance
  def self.the_app
    if Wx::const_defined?(:THE_APP) and Wx::THE_APP.is_running
      Wx::THE_APP
    else
      nil
    end
  end

  # Ruby init callback.
  # Initializes delayed load constants and than calls the user defined 'on_init'
  def on_ruby_init
    Wx.load_delayed_constants
    self.respond_to?(:on_init) ? self.on_init : false
  end
  private :on_ruby_init

  # Make C-ext main_loop method private
  private :main_loop

  # App instance run method.
  # Accepts optional 'on_init' block.
  # The block will be ignored when the (derived) App class
  # already has an 'on_init' method defined.
  def run(&block)
    if block_given?
      if self.respond_to?(:on_init)
        Wx.log_warning("'on_init' block ignored as #{self.class.name} already has an #on_init method defined")
      else
        self.singleton_class.class_eval do
          define_method(:on_init, &block)
        end
      end
    end
    main_loop # run the main loop (which triggers the call to on_init)
  end

  # Convenience class method to create simple apps. Starts an
  # application main_loop, setting up initial windows etc as specified
  # in the passed block.
  # block 
  def self.run(&block)
    if block_given?
      app_klass = Class.new(self)
      app_klass.class_eval do
        define_method(:on_init, &block)
      end
    else
      app_klass = self
    end
    app_klass.new.run
  end


  # This is a class method in Wx, but permit it to be an instance method
  # in wxRuby
  def is_main_loop_running
    Wx::App.is_main_loop_running
  end

  # This method handles failed assertions from within the WxWidgets C++
  # code. These messages are only generated by a DEBUG build of
  # WxRuby. Such messages usually indicate that the API is being used
  # incorrectly; the file/line reference points to the place in the
  # WxWidgets source code where the assertion was made.
  wx_redefine_method :on_assert_failure do |file, line, func, condition, message|
    warn %Q{Wx WARNING: ASSERT #{condition} fired with "#{message}" at (#{func}@#{file}:#{line})}
  end

  # For use in development only, of no practical use in production code.
  # This method causes Ruby's garbage collection to run (roughly) at
  # interval +interval+ (seconds) - the default is 1, i.e. every
  # second. This should help ferret out bugs in memory management more
  # quickly.
  def gc_stress(interval = 1)
    t = Wx::Timer.new(self, 9999)
    evt_timer(9999) { Thread.pass }
    Thread.new { loop { sleep interval; GC.start } }
    t.start(100)
  end
end
