
// 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 "point.hh"
#include "displays.hh"
#include "input_event_handler.hh"
#include "draw_text.hh"
#include "graph.hh"
#include <math.h>
#include "multiwindow.hh"
#include "color.hh"
#include "graph_data.hh"
#include "local_display.hh"

//
// Not used here.  This mechanism is a bit of a hack.
//
int adc_captured_at_this_time = 0;
bool do_captures = true;

void update_adc_to_capture(int adc)
{
}


double sinc(double x)
{
  if(x==0.0)
    return 1.0;
  
  return sin(x)/x;
}


int main()
{
  displays dpys;

  while(dpys.num_local_displays==0)
    {
      printf("Checking_for_displays.\n");
      dpys.check_for_new_displays();
      sleep(1);
    }

  local_display* primary_display = (local_display*)dpys.local_displays[0];
  //input_event_handler eh(primary_display->width, primary_display->height);

  primary_display->draw();

  
  int oldx;
  int oldy;
  point cursor_point(0,0);

  
  point p0;
  point p1;
  p0.x = 500; p0.y = 500;
  p1.x = 100; p1.y = 600;
  for(; p1.x<=900; p1.x+=20)
    for(int i=0; i<dpys.num_local_displays; i++)
      {
	panel* p = ((local_display*)dpys.local_displays[i])->active_panel;
	p->draw_line(p0, p1, RED);
      }

  //
  // Test text, bottom left
  //
  {
    point text_bottom_left(200,100);
  
    const char* text = "Test Text from bottom left.";
    
    int textwidth  = primary_display->calculate_text_width(text);
    int textheight = primary_display->calculate_text_height(text);
    
    //printf("Text width/height is (%d,%d)\n", textwidth, textheight);
    
    primary_display->active_panel->draw_text(text, BLUE, text_bottom_left.x, text_bottom_left.y, DRAW_TEXT_X_LEFT|DRAW_TEXT_Y_BOTTOM);
    
    p0.x = text_bottom_left.x - 3;
    p0.y = text_bottom_left.y + 3;
    p1.x = text_bottom_left.x + textwidth + 3;
    p1.y = text_bottom_left.y + 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.x = text_bottom_left.x - 3;
    p0.y = text_bottom_left.y + 3;
    p1.x = text_bottom_left.x - 3;
    p1.y = text_bottom_left.y - textheight - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.x = text_bottom_left.x + textwidth + 3;
    p0.y = text_bottom_left.y + 3;
    p1.x = text_bottom_left.x + textwidth + 3;
    p1.y = text_bottom_left.y - textheight - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.x = text_bottom_left.x - 3;
    p0.y = text_bottom_left.y - textheight - 3;
    p1.x = text_bottom_left.x + textwidth + 3;
    p1.y = text_bottom_left.y - textheight - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
  }


  //
  // Test text, x centered y centered
  //
  {
    point text_centered(600,100);
  
    const char* text = "Test Text Centered.";
  
    int textwidth  = primary_display->calculate_text_width(text);
    int textheight = primary_display->calculate_text_height(text);
    
    //printf("Text width/height is (%d,%d)\n", textwidth, textheight);
    
    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_CENTER|DRAW_TEXT_Y_CENTER);
    
    p0.x = text_centered.x - textwidth/2  - 3;
    p0.y = text_centered.y + textheight/2 + 3;
    p1.x = text_centered.x + textwidth/2  + 3;
    p1.y = text_centered.y + textheight/2 + 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.x = text_centered.x - textwidth/2  - 3;
    p0.y = text_centered.y + textheight/2 + 3;
    p1.x = text_centered.x - textwidth/2  - 3;
    p1.y = text_centered.y - textheight/2 - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.x = text_centered.x + textwidth/2  + 3;
    p0.y = text_centered.y + textheight/2 + 3;
    p1.x = text_centered.x + textwidth/2  + 3;
    p1.y = text_centered.y - textheight/2 - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.x = text_centered.x - textwidth/2  - 3;
    p0.y = text_centered.y - textheight/2 - 3;
    p1.x = text_centered.x + textwidth/2 + 3;
    p1.y = text_centered.y - textheight/2 - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
  }


  //
  // Test text, point given at top right
  //
  {
    point text_top_right(1000,100);
  
    const char* text = "Test Text given top right point.";
  
    int textwidth  = primary_display->calculate_text_width(text);
    int textheight = primary_display->calculate_text_height(text);
    
    //printf("Text width/height is (%d,%d)\n", textwidth, textheight);
    
    primary_display->active_panel->draw_text(text, BLUE, text_top_right.x, text_top_right.y, DRAW_TEXT_X_RIGHT|DRAW_TEXT_Y_TOP);
    
    p0.x = text_top_right.x - textwidth  - 3;
    p0.y = text_top_right.y + textheight + 3;
    p1.x = text_top_right.x + 3;
    p1.y = text_top_right.y + textheight + 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.x = text_top_right.x - textwidth  - 3;
    p0.y = text_top_right.y + textheight + 3;
    p1.x = text_top_right.x - textwidth  - 3;
    p1.y = text_top_right.y - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.x = text_top_right.x + 3;
    p0.y = text_top_right.y + textheight + 3;
    p1.x = text_top_right.x + 3;
    p1.y = text_top_right.y - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.x = text_top_right.x - textwidth  - 3;
    p0.y = text_top_right.y - 3;
    p1.x = text_top_right.x + 3;
    p1.y = text_top_right.y - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
  }



  //
  // Test text, BIG x centered y centered
  //
  {
    point text_centered(600,300);
  
    const char* text = "BIG Text center justified.";

    primary_display->set_text_size(80);

    int textwidth  = primary_display->calculate_text_width(text);
    int textheight = primary_display->calculate_text_height(text);
    
    //printf("Text width/height is (%d,%d)\n", textwidth, textheight);

    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_CENTER|DRAW_TEXT_Y_CENTER);
    
    p0.x = text_centered.x - textwidth/2  - 3;
    p0.y = text_centered.y + textheight/2 + 3;
    p1.x = text_centered.x + textwidth/2  + 3;
    p1.y = text_centered.y + textheight/2 + 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.x = text_centered.x - textwidth/2  - 3;
    p0.y = text_centered.y + textheight/2 + 3;
    p1.x = text_centered.x - textwidth/2  - 3;
    p1.y = text_centered.y - textheight/2 - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.x = text_centered.x + textwidth/2  + 3;
    p0.y = text_centered.y + textheight/2 + 3;
    p1.x = text_centered.x + textwidth/2  + 3;
    p1.y = text_centered.y - textheight/2 - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.x = text_centered.x - textwidth/2  - 3;
    p0.y = text_centered.y - textheight/2 - 3;
    p1.x = text_centered.x + textwidth/2 + 3;
    p1.y = text_centered.y - textheight/2 - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
  }



  //
  // Test text, big x centered y centered rotate 90 right
  //
  {
    point text_centered(1000,800);
  
    const char* text = "Center justified Rotate Right.";

    primary_display->set_text_size(25);

    int textwidth  = primary_display->calculate_text_width(text);
    int textheight = primary_display->calculate_text_height(text);
    
    //printf("Text width/height is (%d,%d)\n", textwidth, textheight);

    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_CENTER|DRAW_TEXT_Y_CENTER|DRAW_TEXT_ROTATE_90_RIGHT);
    
    p0.y = text_centered.y - textwidth/2  - 3;
    p0.x = text_centered.x + textheight/2 + 3;
    p1.y = text_centered.y + textwidth/2  + 3;
    p1.x = text_centered.x + textheight/2 + 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.y = text_centered.y - textwidth/2  - 3;
    p0.x = text_centered.x + textheight/2 + 3;
    p1.y = text_centered.y - textwidth/2  - 3;
    p1.x = text_centered.x - textheight/2 - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.y = text_centered.y + textwidth/2  + 3;
    p0.x = text_centered.x + textheight/2 + 3;
    p1.y = text_centered.y + textwidth/2  + 3;
    p1.x = text_centered.x - textheight/2 - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.y = text_centered.y - textwidth/2  - 3;
    p0.x = text_centered.x - textheight/2 - 3;
    p1.y = text_centered.y + textwidth/2 + 3;
    p1.x = text_centered.x - textheight/2 - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
  }

  printf("************************ Beginning text tests.\n");
  fflush(stdout);

  //
  // Test text, big x centered y centered rotate 90 left
  //
  {
    point text_centered(1100,800);
  
    const char* text = "Center justified Rotate Left.";

    primary_display->set_text_size(25);

    int textwidth  = primary_display->calculate_text_width(text);
    int textheight = primary_display->calculate_text_height(text);
    
    //printf("Text width/height is (%d,%d)\n", textwidth, textheight);

    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_CENTER|DRAW_TEXT_Y_CENTER|DRAW_TEXT_ROTATE_90_LEFT);
    
    p0.y = text_centered.y - textwidth/2  - 3;
    p0.x = text_centered.x + textheight/2 + 3;
    p1.y = text_centered.y + textwidth/2  + 3;
    p1.x = text_centered.x + textheight/2 + 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.y = text_centered.y - textwidth/2  - 3;
    p0.x = text_centered.x + textheight/2 + 3;
    p1.y = text_centered.y - textwidth/2  - 3;
    p1.x = text_centered.x - textheight/2 - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.y = text_centered.y + textwidth/2  + 3;
    p0.x = text_centered.x + textheight/2 + 3;
    p1.y = text_centered.y + textwidth/2  + 3;
    p1.x = text_centered.x - textheight/2 - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
    
    p0.y = text_centered.y - textwidth/2  - 3;
    p0.x = text_centered.x - textheight/2 - 3;
    p1.y = text_centered.y + textwidth/2 + 3;
    p1.x = text_centered.x - textheight/2 - 3;
    primary_display->active_panel->draw_line(p0, p1, BLUE);
  }


  //
  // Text rotation stars, centered
  //
  {
    point text_centered(1400,200);
  
    const char* text = "Centered_3_Rotations.";

    primary_display->set_text_size(12);

    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_CENTER|DRAW_TEXT_Y_CENTER|DRAW_TEXT_ROTATE_0);
    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_CENTER|DRAW_TEXT_Y_CENTER|DRAW_TEXT_ROTATE_90_LEFT);
    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_CENTER|DRAW_TEXT_Y_CENTER|DRAW_TEXT_ROTATE_90_RIGHT);
  }

  
  //
  // Text rotation stars, top left
  //
  {
    point text_centered(1400,500);
  
    const char* text = "Bottom_Right_3_Rotations.";

    primary_display->set_text_size(12);

    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_RIGHT|DRAW_TEXT_Y_BOTTOM|DRAW_TEXT_ROTATE_0);
    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_RIGHT|DRAW_TEXT_Y_BOTTOM|DRAW_TEXT_ROTATE_90_LEFT);
    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_RIGHT|DRAW_TEXT_Y_BOTTOM|DRAW_TEXT_ROTATE_90_RIGHT);
  }


  //
  // Text rotation stars, bottom right
  //
  {
    point text_centered(1400,800);
  
    const char* text = "Top_Left_3_Rotations.";

    primary_display->set_text_size(12);

    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_LEFT|DRAW_TEXT_Y_TOP|DRAW_TEXT_ROTATE_0);
    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_LEFT|DRAW_TEXT_Y_TOP|DRAW_TEXT_ROTATE_90_LEFT);
    primary_display->active_panel->draw_text(text, BLUE, text_centered.x, text_centered.y, DRAW_TEXT_X_LEFT|DRAW_TEXT_Y_TOP|DRAW_TEXT_ROTATE_90_RIGHT);
  }


  printf("************************ Beginning graph setup.\n");
  fflush(stdout);


  
  oldx = oldy = 0;
  bool button_pressed = false;



  //
  // Draw a graph.
  //

  int num_graph_points = 201;

  graph_data* gd = new graph_data(2,                         // num_graphs
				  num_graph_points,          // num_points
				  -1.0,                      // x_data_start
				  2.0/(num_graph_points-1)); // x_data_step

  graph* gr = new graph();

  for(int i=0; i<num_graph_points; i++)
    {
      double x = 2.0 * i / (num_graph_points-1) - 1.0;
      gd->y_data[0][i] = sinc(10.0*x);
    }


  printf("************************ Beginning graph2 setup.\n");
  fflush(stdout);

#ifdef NOTDEF
  
  graph_data* gd2 = new graph_data(TYPE_TIME,
				   2,                         // num_graphs
				   num_graph_points,          // num_points
				   -1.0,                      // x_data_start
				   2.0/(num_graph_points-1)); // x_data_step
  
  graph* gr2 = new graph();

  
  for(int i=0; i<num_graph_points; i++)
    {
      double x = 16.0 * i / (num_graph_points-1) - 4.0;
      gd2->y_data[0][i] = sinc(10.0*x);
    }

  #endif

  printf("Adding graphs to display.\n");
  fflush(stdout);

  primary_display->add(gr);
  //primary_display->add(gr2);

  if(!primary_display->ieh)
    primary_display->ieh = new input_event_handler(primary_display->width, primary_display->height, primary_display);


  printf("Entering main loop.\n");
  fflush(stdout);
  
  for(;;)
    {  
      my_event me = primary_display->ieh->check_for_event();
      while(me.type == EVENT_NONE)
	{
	  me = primary_display->ieh->check_for_event();
	  usleep(1000);
	}
      
      if(me.type == EVENT_MOVE)
	{
	  //printf("Mouse Move     (%3d,%3d)\n", me.c[0].x, me.c[0].y);
	  
	  if(button_pressed)
	    {
	      for(int i=0; i<dpys.num_local_displays; i++)
		{
		  panel* p = ((local_display*)dpys.local_displays[i])->active_panel;
		  p->draw_line(point(oldx, oldy), point(me.c[0].x, me.c[0].y), GREEN);
		}
	    }

	  oldx = me.c[0].x;
	  oldy = me.c[0].y;
	}
      else if(me.type == EVENT_TOUCH)
	{
	  //printf("Button Press   (%3d,%3d)\n", me.c[0].x, me.c[0].y);
	  button_pressed = true;
	  oldx = me.c[0].x;
	  oldy = me.c[0].y;
	}
      else if(me.type == EVENT_RELEASE)
	{
	  //printf("Button Release (%3d,%3d)\n", me.c[0].x, me.c[0].y);
	  button_pressed = false;
	}
      else if(me.type == EVENT_KEY_PRESS)
	{
	  //printf("Key %d (%c)\n", me.key_code, me.key_ascii);


	  if(me.key_ascii>='0' && me.key_ascii<='9')
	    {
	      int screen = me.key_ascii - '0';

	      if(screen<dpys.num_local_displays)
		{
		  //printf("Flip screen %d\n", screen);

		  
		  dpys.local_displays[screen]->draw();
		  
		}
	    }
	}
    }
}
