###
# wxRuby3 TextCtrl based sampler editor control
# Copyright (c) M.J.N. Corino, The Netherlands
###

module WxRuby

  class SampleEditorCtrl < Wx::TextCtrl

    DEF_STYLE = Wx::TE_MULTILINE |  Wx::HSCROLL | Wx::VSCROLL |
      Wx::TE_RICH | Wx::TE_RICH2 | Wx::TE_NOHIDESEL

    def initialize(owner, *args)
      super(*args, value: '', style: DEF_STYLE)
      set_max_length(0) unless Wx::PLATFORM == 'WXGTK'
      @owner = owner

      # last search area matched
      @search_indicator = nil
      @find_replace = false

      font = Wx::Font.new(10, Wx::FONTFAMILY_TELETYPE, Wx::FONTSTYLE_NORMAL, Wx::FONTWEIGHT_NORMAL)
      self.font = font

      default_theme

      evt_text(self.id, :on_change)
    end

    def default_theme
      self.background_colour = Wx::WHITE
      self.foreground_colour = Wx::BLACK
      self.set_default_style(txtatt = Wx::TextAttr.new(Wx::BLACK, Wx::WHITE, self.font))
      self.set_style(0, self.get_last_position, txtatt)
    end

    def dark_theme
      self.background_colour = Wx::Colour.new('DarkSlateGray')
      self.foreground_colour = Wx::WHITE
      self.set_default_style(txtatt = Wx::TextAttr.new(Wx::WHITE, Wx::Colour.new('DarkSlateGray'), self.font))
      self.set_style(0, self.get_last_position, txtatt)
    end

    def clear_all
      clear
    end

    def do_find(txt, forward, whole_word, match_case)
      options = (match_case ? 0 : Regexp::IGNORECASE)
      pattern = if whole_word
                  ::Regexp.new(%Q{(\\A|\\W)#{txt}(\\W|\\Z)}, options)
                else
                  ::Regexp.new(txt, options)
                end
      forward ? self.value.index(pattern, self.insertion_point) : self.value.rindex(pattern, self.insertion_point)
    end

    def indicator_clear_range(pos, len)
      att = self.default_style
      att.set_font_underlined(false)
      self.set_style(pos, pos+len, att)
    end

    def indicator_fill_range(pos, len)
      att = self.default_style
      att.set_font_underlined(true)
      self.set_style(pos, pos+len, att)
    end

    def find(txt, forward, whole_word, match_case)
      if (pos = do_find(txt, forward, whole_word, match_case))
        indicator_clear_range(*@search_indicator) if @search_indicator
        @search_indicator = [pos, txt.size]
        self.show_position(pos + txt.size)
        self.insertion_point = pos + txt.size
        indicator_fill_range(*@search_indicator)
        @find_replace = true
        true
      else
        false
      end
    end

    def replace(from, to, forward, whole_word, match_case, all=false)
      count = 0
      begin
        if (pos = do_find(from, forward, whole_word, match_case))
          indicator_clear_range(*@search_indicator) if @search_indicator
          super(pos, pos+from.size, to)
          self.show_position(pos + to.size)
          self.insertion_point = pos + to.size
          @search_indicator = [pos, to.size]
          indicator_fill_range(*@search_indicator)
          count += 1
          @find_replace = true
        else
          return count
        end
      end while all
      return count
    end

    def find_close
      if @search_indicator
        indicator_clear_range(*@search_indicator)
        @search_indicator = nil
      end
    end

    def display_dark(f = true)
      f ? dark_theme : default_theme
    end

    def show_whitespace(f = true)
    end

    def show_eol(f = true)
    end

    def update_ui
      @owner.update_undo_redo(self.id, self.can_undo, self.can_redo)
      @owner.update_paste(self.id, self.can_paste)
    end

    def on_change(_)
      update_ui
      unless @find_replace
        find_close
      end
      @find_replace = false
      @owner.update_modify(self.id, modified?)
    end
  end

end