/****************************************************************************
 * This file is part of the project AqDiagram.
 * AqDiagram (c) by 2025 Martin Preuss, all rights reserved.
 *
 * The license for this file can be found in the file COPYING which you
 * should have received along with this file.
 ****************************************************************************/

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

#include "./w_legend_p.h"
#include "aqdiagram/draw/w_drawable.h"
#include "aqdiagram/draw/w_mlayout.h"
#include "aqdiagram/draw/w_label.h"

#include <gwenhywfar/debug.h>



/* ------------------------------------------------------------------------------------------------
 * forward declarations
 * ------------------------------------------------------------------------------------------------
 */

static GWENHYWFAR_CB void _freeData(void *bp, void *p);
static void _setupWidget(AQDG_OBJECT *o, AQDG_WIDGET_LEGEND *xo);
static void _addCurve(AQDG_OBJECT *o, AQDG_DRAW_CONTEXT *drawContext, const AQDG_GRAPH_CURVE *curve, int pen);



/* ------------------------------------------------------------------------------------------------
 * code
 * ------------------------------------------------------------------------------------------------
 */

GWEN_INHERIT(AQDG_OBJECT, AQDG_WIDGET_LEGEND);



AQDG_OBJECT *AQDG_LegendWidget_new(AQDG_OBJECT *parent, uint32_t options, AQDG_OBJECT *graphWidget)
{
  AQDG_OBJECT *o;
  AQDG_WIDGET_LEGEND *xo;

  o=AQDG_MatrixLayoutWidgetByRows_new(parent, options, AQDG_DrawableWidget_GetDrawContext(graphWidget), 5);
  AQDG_Object_SetName(o, "LegendWidget");
  GWEN_NEW_OBJECT(AQDG_WIDGET_LEGEND, xo);
  GWEN_INHERIT_SETDATA(AQDG_OBJECT, AQDG_WIDGET_LEGEND, o, xo, _freeData);
  xo->graphWidget=graphWidget;

  AQDG_Object_SetVSpacing(o, 1);
  AQDG_Object_SetHSpacing(o, 4);
  _setupWidget(o, xo);

  return o;
}



GWENHYWFAR_CB void _freeData(void *bp, void *p)
{
  AQDG_WIDGET_LEGEND *xo;

  xo=(AQDG_WIDGET_LEGEND*) p;

  GWEN_FREE_OBJECT(xo);
}




void _setupWidget(AQDG_OBJECT *o, AQDG_WIDGET_LEGEND *xo)
{
  AQDG_DRAW_CONTEXT *dc;
  AQDG_GRAPH *graph;
  const AQDG_GRAPH_SUBGRAPH_LIST *subGraphList;
  const AQDG_GRAPH_SUBGRAPH *subGraph;
  int penIdx=AQDG_GRAPHWIDGET_PEN_IDX_CURVE0;

  dc=AQDG_DrawableWidget_GetDrawContext(o);
  AQDG_DrawableWidget_SetFontId(o, AQDG_GraphWidget_GetFont(xo->graphWidget, AQDG_GRAPHWIDGET_FONT_IDX_LEGEND));

  AQDG_DrawableWidget_new(o, 0, dc);
  AQDG_LabelWidget_new(o, 0, dc, "Cur:");
  AQDG_LabelWidget_new(o, AQDG_OBJECT_OPTIONS_HALIGNCENTER | AQDG_DRAWABLE_OPTIONS_JUSTIFY_HCENTER, dc, "Min:");
  AQDG_LabelWidget_new(o, AQDG_OBJECT_OPTIONS_HALIGNCENTER | AQDG_DRAWABLE_OPTIONS_JUSTIFY_HCENTER, dc, "Avg:");
  AQDG_LabelWidget_new(o, AQDG_OBJECT_OPTIONS_HALIGNCENTER | AQDG_DRAWABLE_OPTIONS_JUSTIFY_HCENTER, dc, "Max:");

  graph=AQDG_GraphWidget_GetGraph(xo->graphWidget);
  subGraphList=AQDG_Graph_GetSubGraphList(graph);
  subGraph=subGraphList?AQDG_Graph_SubGraph_List_First(subGraphList):NULL;
  while (subGraph) {
    const AQDG_GRAPH_CURVE_LIST *curveList;
    const AQDG_GRAPH_CURVE *curve;

    curveList=AQDG_Graph_SubGraph_GetCurves(subGraph);
    curve=curveList?AQDG_Graph_Curve_List_First(curveList):NULL;
    while(curve) {
      int pen;

      pen=AQDG_GraphWidget_GetPen(xo->graphWidget, penIdx);
      _addCurve(o, dc, curve, pen);

      penIdx++;
      if (penIdx>=AQDG_GRAPHWIDGET_PEN_IDX_LAST)
        penIdx=AQDG_GRAPHWIDGET_PEN_IDX_CURVE0;
      curve=AQDG_Graph_Curve_List_Next(curve);
    }

    subGraph=AQDG_Graph_SubGraph_List_Next(subGraph);
  }
}



void _addCurve(AQDG_OBJECT *o, AQDG_DRAW_CONTEXT *dc, const AQDG_GRAPH_CURVE *curve, int labelPen)
{
  const AQDG_GRAPH_DATAPAIR_LIST *dpList;

  dpList=AQDG_Graph_Curve_GetDataPairs(curve);
  if (dpList && AQDG_Graph_DataPair_List_GetCount(dpList)) {
    GWEN_BUFFER *dbuf;
    const AQDG_GRAPH_DATAPAIR *dp;
    AQDG_OBJECT *label;
    const char *s;
    double v;

    dbuf=GWEN_Buffer_new(0, 256, 0, 1);

    /* curve label */
    s=AQDG_Graph_Curve_GetLabel(curve);
    label=AQDG_LabelWidget_new(o, 0, dc, (s && *s)?s:"no label");
    AQDG_Object_SetName(label, "CurveLabel");
    AQDG_DrawableWidget_SetForegroundPenId(label, labelPen);  /* color label */

    /* last value */
    dp=AQDG_Graph_DataPair_List_Last(dpList);
    v=AQDG_Graph_DataPair_GetValueY(dp);
    GWEN_Buffer_AppendArgs(dbuf, "%.2f", v);
    label=AQDG_LabelWidget_new(o, AQDG_OBJECT_OPTIONS_HALIGNRIGHT | AQDG_DRAWABLE_OPTIONS_JUSTIFY_RIGHT, dc, GWEN_Buffer_GetStart(dbuf));
    AQDG_Object_SetName(label, "LastValueLabel");
    GWEN_Buffer_Reset(dbuf);

    /* min value */
    GWEN_Buffer_AppendArgs(dbuf, "%.2f", AQDG_Graph_Curve_GetMinValueY(curve));
    label=AQDG_LabelWidget_new(o, AQDG_OBJECT_OPTIONS_HALIGNRIGHT | AQDG_DRAWABLE_OPTIONS_JUSTIFY_RIGHT, dc, GWEN_Buffer_GetStart(dbuf));
    AQDG_Object_SetName(label, "MinValueLabel");
    GWEN_Buffer_Reset(dbuf);

    /* calculate average */
    dp=AQDG_Graph_DataPair_List_First(dpList);
    v=0.0;
    while(dp) {
      v+=AQDG_Graph_DataPair_GetValueY(dp);
      dp=AQDG_Graph_DataPair_List_Next(dp);
    }
    v/=(double) AQDG_Graph_DataPair_List_GetCount(dpList);
    GWEN_Buffer_AppendArgs(dbuf, "%.2f", v);
    label=AQDG_LabelWidget_new(o, AQDG_OBJECT_OPTIONS_HALIGNRIGHT | AQDG_DRAWABLE_OPTIONS_JUSTIFY_RIGHT, dc, GWEN_Buffer_GetStart(dbuf));
    AQDG_Object_SetName(label, "AvgValueLabel");
    GWEN_Buffer_Reset(dbuf);

    /* max value */
    GWEN_Buffer_AppendArgs(dbuf, "%.2f", AQDG_Graph_Curve_GetMaxValueY(curve));
    label=AQDG_LabelWidget_new(o, AQDG_OBJECT_OPTIONS_HALIGNRIGHT | AQDG_DRAWABLE_OPTIONS_JUSTIFY_RIGHT, dc, GWEN_Buffer_GetStart(dbuf));
    AQDG_Object_SetName(label, "MaxValueLabel");
    GWEN_Buffer_Reset(dbuf);

    GWEN_Buffer_free(dbuf);
  }
}




