/****************************************************************************
 * This file is part of the project AqDiagram.
 * AqDiagram (c) by 2024 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 "./graph_p.h"


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


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


static void _updateAxisMinMaxValues(AQDG_GRAPH_AXIS *axis, double minValue, double maxValue);



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


AQDG_GRAPH *AQDG_Graph_new(void)
{
  AQDG_GRAPH *g;

  GWEN_NEW_OBJECT(AQDG_GRAPH, g);

  g->subGraphList=AQDG_Graph_SubGraph_List_new();

  return g;
}



void AQDG_Graph_free(AQDG_GRAPH *g)
{
  if (g) {
    int i;

    for (i=0; i<AQDG_GRAPH_NUMAXIS; i++) {
      AQDG_Graph_Axis_free(g->axisArray[i]);
      g->axisArray[i]=NULL;
    }
    AQDG_Graph_SubGraph_List_free(g->subGraphList);
    g->subGraphList=NULL;
    GWEN_FREE_OBJECT(g);
  }
}



const char *AQDG_Graph_GetTitle(const AQDG_GRAPH *g)
{
  return g?g->title:NULL;
}



void AQDG_Graph_SetTitle(AQDG_GRAPH *g, const char *s)
{
  if (g) {
    free(g->title);
    g->title=s?strdup(s):NULL;
  }
}



const char *AQDG_Graph_GetSubTitle(const AQDG_GRAPH *g)
{
  return g?g->subTitle:NULL;
}



void AQDG_Graph_SetSubTitle(AQDG_GRAPH *g, const char *s)
{
  if (g) {
    free(g->subTitle);
    g->subTitle=s?strdup(s):NULL;
  }
}



AQDG_DRAW_CONTEXT *AQDG_Graph_GetDrawContext(const AQDG_GRAPH *g)
{
  return g?g->drawContext:NULL;
}



void AQDG_Graph_SetDrawContext(AQDG_GRAPH *g, AQDG_DRAW_CONTEXT *dc)
{
  if (g)
    g->drawContext=dc;
}



AQDG_GRAPH_AXIS *AQDG_Graph_GetAxisByIndex(const AQDG_GRAPH *g, int idx)
{
  return (g && idx<AQDG_GRAPH_NUMAXIS)?(g->axisArray[idx]):NULL;
}



int AQDG_Graph_SetAxis(AQDG_GRAPH *g, int idx, AQDG_GRAPH_AXIS *ax)
{
  if (g && idx<AQDG_GRAPH_NUMAXIS) {
    if (g->axisArray[idx])
      AQDG_Graph_Axis_free(g->axisArray[idx]);
    g->axisArray[idx]=ax;
    return 0;
  }
  return GWEN_ERROR_INVALID;
}



AQDG_GRAPH_SUBGRAPH_LIST *AQDG_Graph_GetSubGraphList(const AQDG_GRAPH *g)
{
  return g?g->subGraphList:NULL;
}



void AQDG_Graph_AddSubGraph(AQDG_GRAPH *g, AQDG_GRAPH_SUBGRAPH *sg)
{
  if (g && g->subGraphList && sg)
    AQDG_Graph_SubGraph_List_Add(sg, g->subGraphList);
  else {
    DBG_ERROR(AQDG_LOGDOMAIN, "Nullpointer");
  }
}



AQDG_GRAPH_SUBGRAPH *AQDG_Graph_GetFirstSubGraph(const AQDG_GRAPH *g)
{
  return (g && g->subGraphList)?AQDG_Graph_SubGraph_List_First(g->subGraphList):NULL;
}



void AQDG_Graph_CalcMinMaxValues(AQDG_GRAPH *g)
{
  if (g) {
    AQDG_GRAPH_SUBGRAPH *sg;

    sg=AQDG_Graph_SubGraph_List_First(g->subGraphList);
    while(sg) {
      AQDG_GRAPH_AXIS *axis;

      AQDG_Graph_SubGraph_CalcMinMaxValues(sg);
      axis=AQDG_Graph_GetAxisByIndex(g, AQDG_Graph_SubGraph_GetIndexAxisX(sg));
      if (axis)
        _updateAxisMinMaxValues(axis, AQDG_Graph_SubGraph_GetMinValueX(sg), AQDG_Graph_SubGraph_GetMaxValueX(sg));
      axis=AQDG_Graph_GetAxisByIndex(g, AQDG_Graph_SubGraph_GetIndexAxisY(sg));
      if (axis)
        _updateAxisMinMaxValues(axis, AQDG_Graph_SubGraph_GetMinValueY(sg), AQDG_Graph_SubGraph_GetMaxValueY(sg));

      sg=AQDG_Graph_SubGraph_List_Next(sg);
    }
  }
}



void _updateAxisMinMaxValues(AQDG_GRAPH_AXIS *axis, double minValue, double maxValue)
{
  if (axis) {
    uint32_t flags;

    flags=AQDG_Graph_Axis_GetFlags(axis);

    if (flags & AQDG_GRAPH_AXIS_FLAGS_HASMINVALUE) {
      double value;

      value=AQDG_Graph_Axis_GetMinValue(axis);
      if (minValue<value)
        AQDG_Graph_Axis_SetMinValue(axis, minValue);
    }
    else {
      AQDG_Graph_Axis_SetMinValue(axis, minValue);
      AQDG_Graph_Axis_AddFlags(axis, AQDG_GRAPH_AXIS_FLAGS_HASMINVALUE);
    }

    if (flags & AQDG_GRAPH_AXIS_FLAGS_HASMAXVALUE) {
      double value;

      value=AQDG_Graph_Axis_GetMaxValue(axis);
      if (maxValue>value)
        AQDG_Graph_Axis_SetMaxValue(axis, maxValue);
    }
    else {
      AQDG_Graph_Axis_SetMaxValue(axis, maxValue);
      AQDG_Graph_Axis_AddFlags(axis, AQDG_GRAPH_AXIS_FLAGS_HASMAXVALUE);
    }
  }
}






