
// SPDX-License-Identifier: CC-BY-NC-SA-4.0
//
// Copyright (C) 2026 Bit by Bit Signal Processing LLC (https://bxbsp.com)
//
// This work is placed under the "Creative Commons Attribution
// NonCommercial ShareAlike 4.0 International" license, known
// by the shortened acronym "CC-BY-NC-SA-4.0".
//
// This work 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.
//
// A CC-BY-NC-SA-4.0 license allows you to use this work for
// noncommercial purposes so long as attribution is made to the
// original author.  Modified versions of this work may be distributed,
// but only under the same license.  For further details, see the
// Creative Commons License "CC-BY-NC-SA-4.0".
//
// You should have received a copy of the CC-BY-NC-SA-4.0 license
// along with this work. If not, see
// <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
//


#include "selection.hh"
#include "global_beep.hh"
#include "draw_text.hh"
#include "event_types.hh"
#include "send_events.hh"
#include "hotspot.hh"
#include "button.hh"
#include "multiwindow.hh"
#include "displays.hh"
#include "unalingua.hh"

#include <string.h>


class selection : public multiwindow
{
public:

  display*         d;

  color            BG_COLOR;
  color            BUTTON_COLOR;
  color            ACTIONTEXTCOLOR;
  color            TITLE_COLOR;
  
  //int              text_font_height;
  int              button_height;
  int              circle_width;

  unalingua        title;
  int              num_selections;
  button**         b;

  int*             answer;
  
  connection<button, selection_changed_event, selection, int, int>**  con;

  virtual void     draw_dynamic();  
  virtual bool     handle_event(my_event& me);

  virtual void     layout();
  virtual void     draw_dirty();
  
  bool got_char(char c);
  bool add_char(char c);
  
  
  selection(display*               d,
	    const char32_t*        title,
	    int                    num_selections,
	    const char32_t**       selections,
	    int*                   answer,
	    color                  BG_COLOR,
	    color                  TITLE_COLOR,
	    color                  BUTTON_COLOR,
	    const color*           TEXT_COLOR);

  ~selection();
};


bool selection_button_push(button*                      sender,
			      selection_changed_event   event_data,
			      selection*                receiver,
			      int                       receiver_data,
			      int&                      event_return)
{
  receiver->answer[0] = receiver_data;

  display* d = receiver->get_display();

  d->entry_accepted_beep();
  d->end_inner_event_loop();

  delete receiver;

  d->trash_events_until_release();

  return true;
}


int ask_selection(display*               d,
		  const char32_t*        title,
		  int                    num_selections,
		  const char32_t**       selections,
		  color                  BG_COLOR,
		  color                  TITLE_COLOR,
		  color                  BUTTON_COLOR,
		  const color*           TEXT_COLORS)
{
  int answer = -1;
  
  new selection(d,
		title,
		num_selections,
		selections,
		&answer,
		BG_COLOR,
		TITLE_COLOR,
		BUTTON_COLOR,
		TEXT_COLORS);

  d->event_loop();
  return answer;
}

selection::selection(display*               d,
		     const char32_t*        title,
		     int                    num_selections,
		     const char32_t**       selections,
		     int*                   answer, 
		     color                  BG_COLOR,
		     color                  TITLE_COLOR,
		     color                  BUTTON_COLOR,
		     const color*           TEXT_COLORS)
 : multiwindow(BG_COLOR)
{
  this->d      = d;
  this->answer = answer;
  this->num_selections = num_selections;

  button_height = 40;  // redefined later
  
  window_subject_to_layout = false;
  draw_hotspots = false;

  this->BG_COLOR     = BG_COLOR;
  this->TITLE_COLOR  = TITLE_COLOR;
  this->BUTTON_COLOR = BUTTON_COLOR;

  this->title.set_text(title);

  int button_circle_width_percent = 10;

  b = new button*[num_selections];
  
  dt_colors cf = { RED };
  
  for(int i=0; i<num_selections; i++)
    {
      dt_colors c = { TEXT_COLORS[i] };
      b[i] = new button(selections[i], 5, 5, button_circle_width_percent, c, BUTTON_COLOR, cf, BLUE);
      b[i]->silent    = true;
      b[i]->tighten_x = false;
    }

  //
  // Add subcomponents to multiwindow
  //
  for(int i=0; i<num_selections; i++)
    add(b[i], true);

  d->add(this, true);

  //
  // Make connectors
  //
  con = new connection<button, selection_changed_event, selection, int, int>*[num_selections];
  
  for(int i=0; i<num_selections; i++)
    con[i]  = new connection<button, selection_changed_event, selection, int, int>(this, i, selection_button_push);

  //
  // Connect connectors
  //

  for(int i=0; i<num_selections; i++)
    b[i] -> add_receiver(con[i]);

  layout();
  draw_dirty();
}


selection::~selection()
{
  // Delete the connections.
  
  for(int i=0; i<num_selections; i++)
    delete con[i];

  delete [] con;
  delete [] b;
  
  // Deleting everything else (including the buttons) is handled by the multiwindow subclass

  release_events();
  d->mark_layout_dirty();
}


  
void selection::draw_dynamic()
{
  multiwindow::draw_dynamic();
}
  

bool selection::handle_event(my_event& me)
{
  bool handled = multiwindow::handle_event(me);

  if(!handled  && (me.type == EVENT_TOUCH))
    {
      display* disp = get_display();
      disp->entry_rejected_beep();
      
      for(int i=0; i<num_selections; i++)
	b[i] -> highlight_count = 100;
    }
  
  return true;
}




void selection::layout()
{
  //printf("selection::layout() called.\n");
  
  release_events();
  claim_events();
  
  layout_dirty = false;
  dirty = true;
}

void selection::draw_dirty()
{
  //printf("selection::draw_static() called.\n");

  float designed_height = 1080.0;
  float designed_width  = 1920.0;
  float ratio_x = d->width / designed_width;
  float ratio_y = d->height / designed_height;
  float ratio = (ratio_x<ratio_y) ? ratio_x : ratio_y;

  //
  // Do the layout here
  //
  int title_margin   = 20 * ratio;
  int black_margin   = 20 * ratio;

  int top_margin    = 40 * ratio + black_margin;
  int left_margin   = 20 * ratio + black_margin;
  int right_margin  = 20 * ratio + black_margin;
  int bottom_margin = 20 * ratio + black_margin;

  int button_margin = 10 * ratio;

  //int title_font_height    =  60 * ratio;
  button_height           =  80 * ratio;
  int circle_width        =  30 * ratio;

  set_text_size(button_height);

  int title_width = calculate_text_width(title);
  
  //
  // x-layout
  //
  int column_width = title_width;

  //printf("title width for \"%s\" is %d\n", title, title_width);
  
  for(int i=0; i<num_selections; i++)
    {
      int button_width = b[i]->calculate_preferred_width(button_height);
      //printf("column %d width is %d\n", i, button_width);
      
      column_width = max(column_width, button_width);
      //printf("new column width is %d\n", column_width);
    }
  
  int all_button_height = num_selections * (button_height + button_margin) - button_margin;

  //
  // y-layout
  //
  int title_height       = button_height;

  width                = left_margin + column_width + right_margin;
  height               = top_margin + title_height + title_margin + all_button_height + bottom_margin;
  offset.x             = (parent->width  - width)/2;
  offset.y             = (parent->height - height)/2;


  draw_rect_with_curved_edges(GREY2, 0, 0, width, height, circle_width); 

  //  clear(BG_COLOR);
  draw_rect_with_curved_edges(BG_COLOR, black_margin, black_margin, width-2*black_margin, height-2*black_margin, circle_width); 

  draw_text(title, TITLE_COLOR, width/2, top_margin + title_height, DRAW_TEXT_X_CENTER | DRAW_TEXT_Y_BOTTOM | DRAW_TEXT_ROTATE_0);


  int right_column_offset   = left_margin;
  int this_button_y_offset  = top_margin + title_height + title_margin;
  int button_height_full    = button_height + button_margin;

  //
  // Do resizing
  //
  for(int i=0; i<num_selections; i++)
    {
      b[i]->resize(right_column_offset, this_button_y_offset, column_width, button_height);
      this_button_y_offset += button_height_full;
    }

  //
  // Do layout
  //
  for(int i=0; i<num_selections; i++)
      b[i]->layout();

  multiwindow::draw_dirty();
}

