/***************************************************************************
 begin       : Thut Oct 07 2020
 copyright   : (C) 2023 by Martin Preuss
 email       : martin@libchipcard.de

 ***************************************************************************
 *          Please see toplevel file COPYING for license details           *
 ***************************************************************************/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include <aqdiagram/aqdiagram.h>
#include <aqdiagram/placement/o_hlayout-t.h>
#include <aqdiagram/draw/w_drawable.h>
#include <aqdiagram/draw/w_hlayout.h>
#include <aqdiagram/draw/w_label.h>
#include <aqdiagram/draw/context_cairo.h>
#include <aqdiagram/graph/graph.h>
#include <aqdiagram/graph/axis.h>
#include <aqdiagram/graph/subgraph.h>
#include <aqdiagram/graph/w_graph.h>
#include <aqdiagram/graph/timegraph.h>
#include <aqdiagram/data/date.h>
#include <aqdiagram/data/accumulate.h>

#include <gwenhywfar/gwenhywfar.h>
#include <gwenhywfar/cgui.h>
#include <gwenhywfar/debug.h>


#define COLOUR1 0x00000000
#define COLOUR2 0xff000000
#define COLOUR3 0x0000ff00
#define COLOUR4 0x00ff0000
#define COLOUR5 0xffec5b00
#define COLOUR6 0xc0c0c000
#define COLOUR7 0xffffff00



static AQDG_GRAPH *_mkTestGraph();
static AQDG_GRAPH_DATAPAIR_LIST *_mkTestData1();
static AQDG_GRAPH_DATAPAIR_LIST *_mkTestData2();
static void _dumpTicks(const AQDG_GRAPH_TICK_LIST *tickList);



int test1(int argc, char **argv)
{
  AQDG_DRAW_CONTEXT *dc;
  AQDG_OBJECT *rootObject;
  AQDG_OBJECT *o;
  int rv;

  dc=AQDG_Draw_ContextCairo_Png_new("/tmp/test.png", 640, 480);
  rootObject=AQDG_HLayoutWidget_new(NULL, AQDG_OBJECT_OPTIONS_STRETCHX | AQDG_OBJECT_OPTIONS_STRETCHY, dc);
  AQDG_Object_SetWidth(rootObject, 640);
  AQDG_Object_SetHeight(rootObject, 480);
  rv=AQDG_Draw_Context_PenCreate(dc, COLOUR2, 1, AQDG_Dash_None);
  if (rv<0) {
    DBG_ERROR(NULL, "Error creating pen (%d)", rv);
    return 2;
  }
  AQDG_DrawableWidget_SetBackgroundPenId(rootObject, rv);

  rv=AQDG_Draw_Context_PenCreate(dc, COLOUR1, 1, AQDG_Dash_None);
  if (rv<0) {
    DBG_ERROR(NULL, "Error creating pen (%d)", rv);
    return 2;
  }
  AQDG_DrawableWidget_SetForegroundPenId(rootObject, rv);

  rv=AQDG_Draw_Context_FontCreate(dc, "", 16, AQDG_Slant_None, AQDG_Weight_None);
  if (rv<0) {
    DBG_ERROR(NULL, "Error creating font (%d)", rv);
    return 2;
  }
  AQDG_DrawableWidget_SetFontId(rootObject, rv);

  o=AQDG_LabelWidget_new(rootObject,
			 AQDG_OBJECT_OPTIONS_VALIGNCENTER|AQDG_OBJECT_OPTIONS_STRETCHY | AQDG_DRAWABLE_OPTIONS_JUSTIFY_VCENTER,
			 dc, "First Label");
  rv=AQDG_Draw_Context_PenCreate(dc, COLOUR3, 1, AQDG_Dash_None);
  if (rv<0) {
    DBG_ERROR(NULL, "Error creating pen (%d)", rv);
    return 2;
  }
  AQDG_DrawableWidget_SetBackgroundPenId(o, rv);

  o=AQDG_LabelWidget_new(rootObject, 0, dc, "Second Label");
  rv=AQDG_Draw_Context_PenCreate(dc, COLOUR4, 1, AQDG_Dash_None);
  if (rv<0) {
    DBG_ERROR(NULL, "Error creating pen (%d)", rv);
    return 2;
  }
  AQDG_DrawableWidget_SetBackgroundPenId(o, rv);
  rv=AQDG_Draw_Context_FontCreate(dc, "", 24, AQDG_Slant_None, AQDG_Weight_None);
  if (rv<0) {
    DBG_ERROR(NULL, "Error creating font (%d)", rv);
    return 2;
  }
  AQDG_DrawableWidget_SetFontId(o, rv);

  rv=AQDG_Object_Layout(rootObject);
  if (rv<0) {
    DBG_ERROR(NULL, "Error on layout (%d)", rv);
    return 2;
  }
  AQDG_Object_Tree2_CalculateAbsPositions(rootObject);

  AQDG_Object_Dump(rootObject, 2);

  rv=AQDG_DrawableWidget_Draw(rootObject);
  if (rv<0) {
    DBG_ERROR(NULL, "Error drawing (%d)", rv);
    return 2;
  }

  rv=AQDG_Draw_Context_Finish(dc);
  if (rv<0) {
    DBG_ERROR(NULL, "Error finishing drawing (%d)", rv);
    return 2;
  }

  return 0;
}



int test2(int argc, char **argv)
{
  AQDG_GRAPH *g;

  g=_mkTestGraph();
  AQDG_Graph_free(g);
  return 0;
}



int test3()
{
  AQDG_GRAPH *g;
  AQDG_DRAW_CONTEXT *dc;
  AQDG_OBJECT *graphObject;

  g=_mkTestGraph();
  dc=AQDG_Draw_ContextCairo_Png_new("/tmp/testgraph.png", 800, 600);
  graphObject=AQDG_GraphWidget_new(NULL, AQDG_OBJECT_OPTIONS_STRETCHX | AQDG_OBJECT_OPTIONS_STRETCHY, dc);
  AQDG_Object_SetWidth(graphObject, 800);
  AQDG_Object_SetHeight(graphObject, 600);

  AQDG_GraphWidget_SetupDefaultPens(graphObject);
  AQDG_GraphWidget_SetupDefaultFonts(graphObject);
  AQDG_GraphWidget_SetupForGraph(graphObject, g);

  AQDG_Object_ModifyBranchFlagsDown(graphObject, AQDG_OBJECT_FLAGS_RECALC, AQDG_OBJECT_FLAGS_RECALC);
  AQDG_Object_ModifyBranchFlagsDown(graphObject, AQDG_OBJECT_FLAGS_LAYOUT, AQDG_OBJECT_FLAGS_LAYOUT);
  AQDG_Object_Layout(graphObject);
  AQDG_Object_Tree2_CalculateAbsPositions(graphObject);
  AQDG_Object_Dump(graphObject, 2);

  AQDG_DrawableWidget_Draw(graphObject);
  AQDG_Draw_Context_Finish(dc);

  return 0;
}



int test4()
{
  AQDG_GRAPH *g;
  AQDG_GRAPH_DATAPAIR_LIST *dpList;
  AQDG_DRAW_CONTEXT *dc;
  AQDG_OBJECT *graphObject;

  g=AQDG_TimeGraph_new("Title", "Subtitle", "Value", "mm", 0);
  dpList=_mkTestData1();
  AQDG_TimeGraph_AddCurve(g, "Testdata1", AQDG_GRAPH_TYPE_LINE, dpList);

  dpList=_mkTestData2();
  AQDG_TimeGraph_AddCurve(g, "Testdata2", AQDG_GRAPH_TYPE_POINTS, dpList);

  AQDG_TimeGraph_SetupTicks(g, 0, 0.0, 0.0);

  dc=AQDG_Draw_ContextCairo_Png_new("/tmp/testgraph.png", 800, 600);
  graphObject=AQDG_GraphWidget_new(NULL, AQDG_OBJECT_OPTIONS_STRETCHX | AQDG_OBJECT_OPTIONS_STRETCHY, dc);
  AQDG_Object_SetWidth(graphObject, 800);
  AQDG_Object_SetHeight(graphObject, 600);

  AQDG_GraphWidget_SetupDefaultPens(graphObject);
  AQDG_GraphWidget_SetupDefaultFonts(graphObject);

  AQDG_GraphWidget_SetupForGraph(graphObject, g);

  AQDG_Object_ModifyBranchFlagsDown(graphObject, AQDG_OBJECT_FLAGS_RECALC, AQDG_OBJECT_FLAGS_RECALC);
  AQDG_Object_ModifyBranchFlagsDown(graphObject, AQDG_OBJECT_FLAGS_LAYOUT, AQDG_OBJECT_FLAGS_LAYOUT);
  AQDG_Object_Layout(graphObject);
  AQDG_Object_Tree2_CalculateAbsPositions(graphObject);
  AQDG_Object_Dump(graphObject, 2);

  AQDG_DrawableWidget_Draw(graphObject);
  AQDG_Draw_Context_Finish(dc);

  return 0;
}



int test5()
{
  AQDG_GRAPH *g;
  AQDG_GRAPH_DATAPAIR_LIST *dpList;
  AQDG_GRAPH_DATAPAIR_LIST *derivedDpList;
  AQDG_DRAW_CONTEXT *dc;
  AQDG_OBJECT *graphObject;

  g=AQDG_TimeGraph_new("Title", "Subtitle", "Value", "mm", 0);
  dpList=_mkTestData1();
  AQDG_TimeGraph_AddCurve(g, "Testdata", AQDG_GRAPH_TYPE_LINE, dpList);

  derivedDpList=AQDG_Data_Accumulate(dpList);
  AQDG_TimeGraph_AddCurve(g, "Accumulated", AQDG_GRAPH_TYPE_LINE, derivedDpList);

  AQDG_TimeGraph_SetupTicks(g, 0, 0.0, 0.0);

  dc=AQDG_Draw_ContextCairo_Png_new("/tmp/testgraph.png", 800, 600);
  graphObject=AQDG_GraphWidget_new(NULL, AQDG_OBJECT_OPTIONS_STRETCHX | AQDG_OBJECT_OPTIONS_STRETCHY, dc);
  AQDG_Object_SetWidth(graphObject, 800);
  AQDG_Object_SetHeight(graphObject, 600);

  AQDG_GraphWidget_SetupDefaultPens(graphObject);
  AQDG_GraphWidget_SetupDefaultFonts(graphObject);

  AQDG_GraphWidget_FinishWithGraph(graphObject, g);
  AQDG_Object_Dump(graphObject, 2);

  return 0;
}



AQDG_GRAPH *_mkTestGraph()
{
  AQDG_GRAPH *g;
  AQDG_GRAPH_AXIS *xAxis;
  AQDG_GRAPH_AXIS *yAxis;

  g=AQDG_Graph_new();
  AQDG_Graph_SetTitle(g, "Test Graph");
  AQDG_Graph_SetSubTitle(g, "Test Data");

  xAxis=AQDG_Graph_Axis_new();
  AQDG_Graph_Axis_SetLabel(xAxis, "Label X");
  AQDG_Graph_Axis_SetMinValue(xAxis, time(NULL)-(4*7*24*60*60));
  AQDG_Graph_Axis_SetMaxValue(xAxis, time(NULL));
  AQDG_Graph_Axis_SetPrecision(xAxis, 0);
  AQDG_Graph_SetAxis(g, AQDG_GRAPH_AXISPOS_BOTTOM, xAxis);
  fprintf(stderr, "Generating ticks for X-axis\n");
  AQDG_Graph_Axis_GenWeekTicks(xAxis, 0);
  AQDG_Graph_Axis_GenDayTicks(xAxis, 1);
  fprintf(stderr, "Ticks for X-Axis (%f - %f)\n",
	  AQDG_Graph_Axis_GetMinValue(xAxis),
	  AQDG_Graph_Axis_GetMaxValue(xAxis));
  _dumpTicks(AQDG_Graph_Axis_GetTickList(xAxis));

  yAxis=AQDG_Graph_Axis_new();
  AQDG_Graph_Axis_SetLabel(yAxis, "Label Y");
  AQDG_Graph_Axis_SetMinValue(yAxis, -127.0);
  AQDG_Graph_Axis_SetMaxValue(yAxis, 1235.0);
  AQDG_Graph_Axis_SetPrecision(yAxis, 2);
  AQDG_Graph_SetAxis(g, AQDG_GRAPH_AXISPOS_LEFT, yAxis);
  fprintf(stderr, "Generating ticks for Y-axis\n");
  AQDG_Graph_Axis_GenLog10Ticks(yAxis);
  fprintf(stderr, "Ticks for Y-Axis (%f - %f)\n",
	  AQDG_Graph_Axis_GetMinValue(yAxis),
	  AQDG_Graph_Axis_GetMaxValue(yAxis));
  _dumpTicks(AQDG_Graph_Axis_GetTickList(yAxis));

  return g;
}



AQDG_GRAPH_DATAPAIR_LIST *_mkTestData1()
{
  AQDG_GRAPH_DATAPAIR_LIST *dpList;
  GWEN_TIMESTAMP *ts;
  int i;

  dpList=AQDG_Graph_DataPair_List_new();
  ts=GWEN_Timestamp_new(2025, 1, 15, 2, 0, 0);
  for(i=0; i<60; i++) {
    AQDG_GRAPH_DATAPAIR *dp;
    double v;

    v=i*2;
    dp=AQDG_Graph_DataPair_new();
    AQDG_Graph_DataPair_SetValueX(dp, GWEN_Timestamp_toTimeT(ts));
    AQDG_Graph_DataPair_SetValueY(dp, v);
    AQDG_Graph_DataPair_List_Add(dp, dpList);

    GWEN_Timestamp_AddSeconds(ts, 24*60*60); /* add a day */
  }

  return dpList;
}



AQDG_GRAPH_DATAPAIR_LIST *_mkTestData2()
{
  AQDG_GRAPH_DATAPAIR_LIST *dpList;
  GWEN_TIMESTAMP *ts;
  int i;

  dpList=AQDG_Graph_DataPair_List_new();
  ts=GWEN_Timestamp_new(2025, 1, 1, 0, 0, 0);
  for(i=0; i<60; i++) {
    AQDG_GRAPH_DATAPAIR *dp;
    double v;

    v=random() % 200;
    dp=AQDG_Graph_DataPair_new();
    AQDG_Graph_DataPair_SetValueX(dp, GWEN_Timestamp_toTimeT(ts));
    AQDG_Graph_DataPair_SetValueY(dp, v);
    AQDG_Graph_DataPair_List_Add(dp, dpList);

    GWEN_Timestamp_AddSeconds(ts, 24*60*60); /* add a day */
  }

  return dpList;
}



void _dumpTicks(const AQDG_GRAPH_TICK_LIST *tickList)
{
  const AQDG_GRAPH_TICK *tick;

  fprintf(stderr, "Ticks:\n");
  tick=AQDG_Graph_Tick_List_First(tickList);
  while(tick) {
    fprintf(stderr,
	    "- %f (\"%s\") [%d]\n",
	    AQDG_Graph_Tick_GetValue(tick),
	    AQDG_Graph_Tick_GetLabel(tick),
	    AQDG_Graph_Tick_GetLevel(tick));
    tick=AQDG_Graph_Tick_List_Next(tick);
  }
}




int modTest(int argc, char **argv)
{
  int rv;
  GWEN_TEST_FRAMEWORK *tf;

  tf=TestFramework_new();

  rv=AQDG_HLayoutObject_AddTests(TestFramework_GetModulesRoot(tf));
  if (rv) {
    fprintf(stderr, "FAILED: test_hlayout()\n");
    return 2;
  }

  rv=TestFramework_Run(tf, argc, argv);
  if (rv) {
    fprintf(stderr, "Some tests failed.\n");
    return 2;
  }
  TestFramework_free(tf);


  return 0;
}



int main(int argc, char **argv)
{
  int rv;
  GWEN_GUI *gui;

  rv=GWEN_Init();
  if (rv) {
    DBG_ERROR_ERR(0, rv);
    return rv;
  }

  gui=GWEN_Gui_CGui_new();
  //GWEN_Gui_SetCharSet(gui, "ISO-8859-15");
  GWEN_Gui_SetGui(gui);
  GWEN_Logger_SetLevel(AQDG_LOGDOMAIN, GWEN_LoggerLevel_Info);
  GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Info);

//  rv=test1(argc, argv);
//  rv=test2(argc, argv);
  rv=test5();

  if (rv!=0){
    DBG_ERROR(NULL, "here (%d)", rv);
    GWEN_Gui_SetGui(NULL);
    GWEN_Gui_free(gui);
    GWEN_Fini();
    return 2;
  }


  rv=GWEN_Fini();
  if (rv) {
    DBG_ERROR_ERR(0, rv);
    return 2;
  }


  return 0;
}



