# Copyright (c) 2023 M.J.N. Corino, The Netherlands
#
# This software is released under the MIT license.
#
# Adapted for wxRuby from wxWidgets widgets sample
# Copyright (c) 2001 Vadim Zeitlin

module Widgets

  module HeaderCtrl

    class HeaderCtrlPage < Widgets::Page

      NUMBER_OF_COLUMNS = 4

      COL_ALIGNMENTS = %w{none left centre right}
      COL_ALIGN_FLAGS = [Wx::ALIGN_NOT, Wx::ALIGN_LEFT, Wx::ALIGN_CENTRE, Wx::ALIGN_RIGHT]
      COL_WITH_BITMAP_DEFAULT = false
      COL_ALIGNMENT_FLAG_DEFAULT = Wx::ALIGN_NOT
      COL_ALIGNMENT_INDEX_DEFAULT = 0

      ColSettings = Struct.new(:chkAllowResize,
                               :chkAllowReorder,
                               :chkAllowSort,
                               :chkAllowHide,
                               :chkWithBitmap,
                               :rbAlignments)

      def initialize(book, images)
        super(book, images, :header)
        
        @header = nil
        @sizerHeader = nil
      end

      Info = Widgets::PageInfo.new(self, 'Header',
                                   if Wx::PLATFORM == 'WXMSW'
                                     NATIVE_CTRLS
                                   else
                                     GENERIC_CTRLS
                                   end)

      def get_widget
        @header
      end
      
      def recreate_widget
        @sizerHeader.clear(true) # delete windows
    
        flags = get_attrs.default_flags | get_header_style_flags
    
        @header = Wx::HeaderCtrlSimple.new(@sizerHeader.get_static_box, Wx::ID_ANY,
                                           style: flags)
    
        @header.evt_header_resizing(Wx::ID_ANY, self.method(:on_resizing))
        @header.evt_header_begin_resize(Wx::ID_ANY, self.method(:on_begin_resize))
        @header.evt_header_end_resize(Wx::ID_ANY, self.method(:on_end_resize))

        @colSettings.each_with_index do |cs, i|
          col = Wx::HeaderColumnSimple.new("Column #{i + 1}",
                                           from_dip(100),
                                           get_column_alignment_flag(i),
                                           get_column_style_flags(i))
          if cs.chkWithBitmap.is_checked
            icons = [ Wx::ART_ERROR, Wx::ART_QUESTION, Wx::ART_WARNING, Wx::ART_INFORMATION ]
            col.set_bitmap(Wx::ArtProvider.get_bitmap_bundle(icons[i % icons.size], Wx::ART_BUTTON))
          end
          @header.append_column(col)
        end
    
        @sizerHeader.add_stretch_spacer
        @sizerHeader.add(@header, Wx::SizerFlags.new.expand)
        @sizerHeader.add_stretch_spacer
        @sizerHeader.layout
      end
  
      # lazy creation of the content
      def create_content
        # top pane
        sizerTop = Wx::HBoxSizer.new
    
        # header style
        styleSizer = Wx::StaticBoxSizer.new(Wx::VERTICAL, self, '&Header style')
        styleSizerBox = styleSizer.get_static_box
    
        @chkAllowReorder = create_check_box_and_add_to_sizer(styleSizer, 'Allow &reorder', Wx::ID_ANY, styleSizerBox)
        @chkAllowHide = create_check_box_and_add_to_sizer(styleSizer, 'Allow &hide', Wx::ID_ANY, styleSizerBox)
        @chkBitmapOnRight = create_check_box_and_add_to_sizer(styleSizer, '&Bitmap on right', Wx::ID_ANY, styleSizerBox)
        reset_header_style
    
        styleSizer.add_stretch_spacer
        btnReset = Wx::Button.new(styleSizerBox, Wx::ID_ANY, '&Reset')
        styleSizer.add(btnReset, Wx::SizerFlags.new.center_horizontal.border)
        sizerTop.add(styleSizer, Wx::SizerFlags.new.expand)
    
        # column flags
        @colSettings = []
        NUMBER_OF_COLUMNS.times do |i|
          sizerCol = Wx::StaticBoxSizer.new(Wx::VERTICAL, self, "Column #{i+1} style")
          sizerColBox = sizerCol.get_static_box

          @colSettings << ColSettings.new(create_check_box_and_add_to_sizer(sizerCol, 'Allow resize', Wx::ID_ANY, sizerColBox),
                                          create_check_box_and_add_to_sizer(sizerCol, 'Allow reorder', Wx::ID_ANY, sizerColBox),
                                          create_check_box_and_add_to_sizer(sizerCol, 'Allow sort', Wx::ID_ANY, sizerColBox),
                                          create_check_box_and_add_to_sizer(sizerCol, 'Hidden', Wx::ID_ANY, sizerColBox),
                                          create_check_box_and_add_to_sizer(sizerCol, 'With bitmap', Wx::ID_ANY, sizerColBox),
                                          Wx::RadioBox.new(sizerColBox, Wx::ID_ANY, 'Alignment',
                                                           choices: COL_ALIGNMENTS,
                                                           major_dimension: 2,
                                                           style: Wx::RA_SPECIFY_COLS))
          sizerCol.add(@colSettings.last.rbAlignments, Wx::SizerFlags.new.expand.border)
          reset_column_style(i)
          sizerTop.add_spacer(15)
          sizerTop.add(sizerCol, Wx::SizerFlags.new.expand)
        end
    
        # bottom pane
        @sizerHeader = Wx::StaticBoxSizer.new(Wx::VERTICAL, self, 'Header')
        recreate_widget
    
        # the 2 panes compose the window
        sizerAll = Wx::VBoxSizer.new
        sizerAll.add(sizerTop, Wx::SizerFlags.new.expand.border)
        sizerAll.add(@sizerHeader, Wx::SizerFlags.new(1).expand.border)
    
        set_sizer(sizerAll)
    
        # connect event handlers
        @chkAllowReorder.evt_checkbox(Wx::ID_ANY, self.method(:on_style_check_or_radio_box))
        @chkAllowHide.evt_checkbox(Wx::ID_ANY, self.method(:on_style_check_or_radio_box))
        @chkBitmapOnRight.evt_checkbox(Wx::ID_ANY, self.method(:on_style_check_or_radio_box))
        @colSettings.each do |cs|
          cs.chkAllowResize.evt_checkbox(Wx::ID_ANY, self.method(:on_style_check_or_radio_box))
          cs.chkAllowReorder.evt_checkbox(Wx::ID_ANY, self.method(:on_style_check_or_radio_box))
          cs.chkAllowSort.evt_checkbox(Wx::ID_ANY, self.method(:on_style_check_or_radio_box))
          cs.chkAllowHide.evt_checkbox(Wx::ID_ANY, self.method(:on_style_check_or_radio_box))
          cs.chkWithBitmap.evt_checkbox(Wx::ID_ANY, self.method(:on_style_check_or_radio_box))
          cs.rbAlignments.evt_radiobox(Wx::ID_ANY, self.method(:on_style_check_or_radio_box))
        end
        btnReset.evt_button(btnReset, self.method(:on_reset_button))
        btnReset.evt_update_ui(btnReset, self.method(:on_update_ui_reset_button))
      end
  
      protected
      
      # event handlers
      def on_style_check_or_radio_box(_event)
        recreate_widget
      end

      def on_reset_button(_event)
        reset_header_style

        @colSettings.size.times { |i| reset_column_style(i) }

        recreate_widget
      end

      def on_update_ui_reset_button(event)
        enable = get_header_style_flags != Wx::HD_DEFAULT_STYLE
        @colSettings.each_with_index do |cs, i|
          enable = enable ||
            (get_column_style_flags(i) != Wx::COL_DEFAULT_FLAGS) ||
            (cs.chkWithBitmap.is_checked != COL_WITH_BITMAP_DEFAULT) ||
            (cs.rbAlignments.selection != COL_ALIGNMENT_INDEX_DEFAULT)
          break if enable
        end
        event.enable(enable)
      end

      def on_resizing(event)
        Wx.log_message('Column %i resizing, width = %i', event.column + 1, event.width)
        event.skip
      end

      def on_begin_resize(event)
        Wx.log_message('Column %i resize began, width = %i', event.column + 1, event.width)
        event.skip
      end

      def on_end_resize(event)
        Wx.log_message('Column %i resize ended, width = %i', event.column + 1, event.width)
        event.skip
      end
  
      # reset the header style
      def reset_header_style
        @chkAllowReorder.set_value(Wx::HD_DEFAULT_STYLE.allbits?(Wx::HD_ALLOW_REORDER))
        @chkAllowHide.set_value(Wx::HD_DEFAULT_STYLE.allbits?(Wx::HD_ALLOW_HIDE))
        @chkBitmapOnRight.set_value(Wx::HD_DEFAULT_STYLE.allbits?(Wx::HD_BITMAP_ON_RIGHT))
      end

      # compose header style flags based on selections
      def get_header_style_flags
        flags = 0

        flags |= Wx::HD_ALLOW_REORDER if @chkAllowReorder.is_checked
        flags |= Wx::HD_ALLOW_HIDE if @chkAllowHide.is_checked
        flags |= Wx::HD_BITMAP_ON_RIGHT if @chkBitmapOnRight.is_checked

        flags
      end

      # reset column style
      def reset_column_style(col)
        @colSettings[col].chkAllowResize.set_value(Wx::COL_DEFAULT_FLAGS.allbits?(Wx::COL_RESIZABLE))
        @colSettings[col].chkAllowReorder.set_value(Wx::COL_DEFAULT_FLAGS.allbits?(Wx::COL_REORDERABLE))
        @colSettings[col].chkAllowSort.set_value(Wx::COL_DEFAULT_FLAGS.allbits?(Wx::COL_SORTABLE))
        @colSettings[col].chkAllowHide.set_value(Wx::COL_DEFAULT_FLAGS.allbits?(Wx::COL_HIDDEN))
        @colSettings[col].chkWithBitmap.set_value(COL_WITH_BITMAP_DEFAULT)
        @colSettings[col].rbAlignments.set_selection(COL_ALIGNMENT_INDEX_DEFAULT)
      end

      # compose column style flags based on selections
      def get_column_style_flags(col)
        flags = 0

        flags |= Wx::COL_RESIZABLE if @colSettings[col].chkAllowResize.is_checked
        flags |= Wx::COL_REORDERABLE if @colSettings[col].chkAllowReorder.is_checked
        flags |= Wx::COL_SORTABLE if @colSettings[col].chkAllowSort.is_checked
        flags |= Wx::COL_HIDDEN if @colSettings[col].chkAllowHide.is_checked

        flags
      end

      # get column alignment flags based on selection
      def get_column_alignment_flag(col)
        sel = @colSettings[col].rbAlignments.selection
        sel == Wx::NOT_FOUND ? COL_ALIGNMENT_FLAG_DEFAULT : COL_ALIGN_FLAGS[sel]
      end
      
    end

  end

end