/****************************************************************************
 * 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 "w_drawable_p.h"

#include <gwenhywfar/debug.h>



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

static GWENHYWFAR_CB void _freeData(void *bp, void *p);

static int _drawFallback(AQDG_OBJECT *object);



/* ------------------------------------------------------------------------------------------------
 * implementations
 * ------------------------------------------------------------------------------------------------
 */

GWEN_INHERIT(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE);



AQDG_OBJECT *AQDG_DrawableWidget_new(AQDG_OBJECT *parent, uint32_t options, AQDG_DRAW_CONTEXT *drawContext)
{
  AQDG_OBJECT *object;

  object=AQDG_Object_new();
  AQDG_Object_SetName(object, "DrawableWidget");
  if (parent)
    AQDG_Object_Tree2_AddChild(parent, object);

  AQDG_DrawableWidget_Extend(object, drawContext);
  AQDG_Object_SetOptions(object, options);

  return object;
}



void AQDG_DrawableWidget_Extend(AQDG_OBJECT *object, AQDG_DRAW_CONTEXT *drawContext)
{
  AQDG_OBJECT_DRAWABLE *xo;
  AQDG_OBJECT *parent;

  GWEN_NEW_OBJECT(AQDG_OBJECT_DRAWABLE, xo);
  GWEN_INHERIT_SETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object, xo, _freeData);

  xo->drawContext=drawContext;
  xo->drawFn=_drawFallback;

  parent=AQDG_Object_Tree2_GetParent(object);
  if (parent) {
    if (GWEN_INHERIT_ISOFTYPE(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, parent)) {
      xo->fontId=AQDG_DrawableWidget_GetFontId(parent);
      xo->foregroundPenId=AQDG_DrawableWidget_GetForegroundPenId(parent);
      xo->backgroundPenId=AQDG_DrawableWidget_GetBackgroundPenId(parent);
    }
    AQDG_Object_SetBorderLeft(object, AQDG_Object_GetBorderLeft(parent));
    AQDG_Object_SetBorderRight(object,AQDG_Object_GetBorderRight(parent));
    AQDG_Object_SetBorderTop(object, AQDG_Object_GetBorderTop(parent));
    AQDG_Object_SetBorderBottom(object, AQDG_Object_GetBorderBottom(parent));
    AQDG_Object_SetHSpacing(object, AQDG_Object_GetHSpacing(parent));
    AQDG_Object_SetVSpacing(object, AQDG_Object_GetVSpacing(parent));
  }
  else {
    AQDG_Object_SetBorderLeft(object, AQDG_DRAWABLE_DEFAULT_BORDER);
    AQDG_Object_SetBorderRight(object, AQDG_DRAWABLE_DEFAULT_BORDER);
    AQDG_Object_SetBorderTop(object, AQDG_DRAWABLE_DEFAULT_BORDER);
    AQDG_Object_SetBorderBottom(object, AQDG_DRAWABLE_DEFAULT_BORDER);
    AQDG_Object_SetHSpacing(object, AQDG_DRAWABLE_DEFAULT_HSPACING);
    AQDG_Object_SetVSpacing(object, AQDG_DRAWABLE_DEFAULT_VSPACING);
  }
}



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

  xo=(AQDG_OBJECT_DRAWABLE*) p;
  free(xo->text);
  GWEN_FREE_OBJECT(xo);
}



AQDG_DRAW_CONTEXT *AQDG_DrawableWidget_GetDrawContext(const AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    return xo?xo->drawContext:NULL;
  }
  return NULL;
}



int AQDG_DrawableWidget_GetFontId(const AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    return xo?xo->fontId:0;
  }
  return 0;
}



void AQDG_DrawableWidget_SetFontId(AQDG_OBJECT *object, int i)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo) {
      if (xo->fontId!=i) {
	xo->fontId=i;
	AQDG_Object_AddFlags(object, AQDG_OBJECT_FLAGS_DRAW);
	AQDG_Object_ModifyBranchFlagsUp(object, AQDG_OBJECT_FLAGS_RECALC, AQDG_OBJECT_FLAGS_RECALC);
      }
    }
  }
}



int AQDG_DrawableWidget_GetForegroundPenId(const AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    return xo?xo->foregroundPenId:0;
  }
  return 0;
}



void AQDG_DrawableWidget_SetForegroundPenId(AQDG_OBJECT *object, int i)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo) {
      if (xo->foregroundPenId!=i) {
	xo->foregroundPenId=i;
	AQDG_Object_AddFlags(object, AQDG_OBJECT_FLAGS_DRAW);
      }
    }
  }
}



int AQDG_DrawableWidget_GetBackgroundPenId(const AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    return xo?xo->backgroundPenId:0;
  }
  return 0;
}



void AQDG_DrawableWidget_SetBackgroundPenId(AQDG_OBJECT *object, int i)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo) {
      if (xo->backgroundPenId!=i) {
	xo->backgroundPenId=i;
	AQDG_Object_AddFlags(object, AQDG_OBJECT_FLAGS_DRAW);
      }
    }
  }
}



const char *AQDG_DrawableWidget_GetText(const AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    return xo?xo->text:NULL;
  }
  return NULL;
}



void AQDG_DrawableWidget_SetText(AQDG_OBJECT *object, const char *s)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo) {
      free(xo->text);
      xo->text=s?strdup(s):NULL;

      AQDG_Object_AddFlags(object, AQDG_OBJECT_FLAGS_DRAW);
      AQDG_Object_ModifyBranchFlagsUp(object, AQDG_OBJECT_FLAGS_RECALC, AQDG_OBJECT_FLAGS_RECALC);
    }
  }
}



double AQDG_DrawableWidget_GetValue(const AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    return xo?xo->value:0.0;
  }
  return 0.0;
}



void AQDG_DrawableWidget_SetValue(AQDG_OBJECT *object, double v)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo)
      xo->value=v;
  }
}



AQDG_WIDGET_DRAWABLE_DRAW_FN AQDG_DrawableWidget_SetDrawFn(AQDG_OBJECT *object, AQDG_WIDGET_DRAWABLE_DRAW_FN fn)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo) {
      AQDG_WIDGET_DRAWABLE_DRAW_FN oldFn;

      oldFn=xo->drawFn;
      xo->drawFn=fn;
      return oldFn;
    }
  }

  return NULL;
}



int AQDG_DrawableWidget_Draw(AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo && xo->drawFn)
      return xo->drawFn(object);
  }
  AQDG_Object_SubFlags(object, AQDG_OBJECT_FLAGS_DRAW);
  return 0;
}



int AQDG_DrawableWidget_DrawBackground(AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo) {
#if 0
      DBG_ERROR(AQDG_LOGDOMAIN, "Drawing background with pen %d to %d/%d  %d/%d",
                xo->backgroundPenId,
                AQDG_Object_GetAbsoluteX(object),
                AQDG_Object_GetAbsoluteY(object),
                AQDG_Object_GetWidth(object),
                AQDG_Object_GetHeight(object));
#endif
      AQDG_Draw_Context_DrawFilledRect(xo->drawContext,
				       xo->backgroundPenId,
				       AQDG_Object_GetAbsoluteX(object),
				       AQDG_Object_GetAbsoluteY(object),
				       AQDG_Object_GetWidth(object),
				       AQDG_Object_GetHeight(object));
      return 1;
    }
  }
  return 0;
}



void AQDG_DrawableWidget_DrawText(AQDG_OBJECT *object, int x, int y, const char *text)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo) {
      x+=AQDG_Object_GetAbsoluteX(object);
      y+=AQDG_Object_GetAbsoluteY(object);
      AQDG_Draw_Context_DrawText(xo->drawContext, xo->foregroundPenId, xo->fontId, AQDG_Direction_Horizontal, x, y, text?text:"");
    }
  }
}



int AQDG_DrawableWidget_DrawChildren(AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo) {
      AQDG_OBJECT *child;

      child=AQDG_Object_Tree2_GetFirstChild(object);
      if (child) {
        while (child) {
          if (!(AQDG_Object_GetFlags(child) & AQDG_OBJECT_FLAGS_HIDDEN))
            AQDG_DrawableWidget_Draw(child);
	  child=AQDG_Object_Tree2_GetNext(child);
	}
	return 1;
      }
    }
  }
  return 0;
}



void AQDG_DrawableWidget_DefaultDraw(AQDG_OBJECT *object)
{
  AQDG_OBJECT_DRAWABLE *xo;

  xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
  if (xo) {
    AQDG_DrawableWidget_DrawBackground(object);
    AQDG_DrawableWidget_DrawChildren(object);
    AQDG_Object_SubFlags(object, AQDG_OBJECT_FLAGS_DRAW);
  }
}



int _drawFallback(AQDG_OBJECT *object)
{
  AQDG_DrawableWidget_DefaultDraw(object);
  return 1;
}



int AQDG_DrawableWidget_GetTextDefaultWidth(AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo) {
      if (xo->text) {
        int w;

        w=AQDG_DrawableWidget_GetTextWidth(object);
        w+=AQDG_Object_GetBorderLeft(object)+AQDG_Object_GetBorderRight(object);
        return w;
      }
    }
  }
  return 0;
}



int AQDG_DrawableWidget_GetTextDefaultHeight(AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo) {
      if (xo->text) {
        int h;

        h=AQDG_DrawableWidget_GetTextHeight(object);
        h+=AQDG_Object_GetBorderTop(object)+AQDG_Object_GetBorderBottom(object);
        return h;
      }
    }
  }
  return 0;
}



int AQDG_DrawableWidget_GetTextWidth(AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo) {
      if (xo->text) {
        int w;

	w=AQDG_Draw_Context_GetTextWidth(xo->drawContext, xo->fontId, xo->text);
	if (w<0) {
          DBG_INFO(AQDG_LOGDOMAIN, "here (%d)", w);
          return 0;
        }
        return w;
      }
    }
  }
  return 0;
}



int AQDG_DrawableWidget_GetTextHeight(AQDG_OBJECT *object)
{
  if (object) {
    AQDG_OBJECT_DRAWABLE *xo;

    xo=GWEN_INHERIT_GETDATA(AQDG_OBJECT, AQDG_OBJECT_DRAWABLE, object);
    if (xo) {
      if (xo->text) {
        int h;

	h=AQDG_Draw_Context_GetTextHeight(xo->drawContext, xo->fontId, xo->text);
	if (h<0) {
          DBG_INFO(AQDG_LOGDOMAIN, "here (%d)", h);
          return 0;
        }
        return h;
      }
    }
  }
  return 0;
}



AQDG_OBJECT *AQDG_DrawableWidget_GetFirstVisibleChild(const AQDG_OBJECT *o)
{
  if (o) {
    AQDG_OBJECT *child;

    child=AQDG_Object_Tree2_GetFirstChild(o);
    while(child) {
      if (child && !(AQDG_Object_GetFlags(child) & AQDG_OBJECT_FLAGS_HIDDEN))
        return child;
      child=AQDG_Object_Tree2_GetNext(child);
    }
  }
  return NULL;
}



AQDG_OBJECT *AQDG_DrawableWidget_GetNextVisibleWidget(AQDG_OBJECT *o)
{
  while(o) {
    o=AQDG_Object_Tree2_GetNext(o);
    if (o && !(AQDG_Object_GetFlags(o) & AQDG_OBJECT_FLAGS_HIDDEN))
      return o;
  }
  return NULL;
}



void AQDG_DrawableWidget_UnhideAllChildren(AQDG_OBJECT *o)
{
  AQDG_OBJECT *child;

  child=AQDG_Object_Tree2_GetFirstChild(o);
  while(child) {
    AQDG_Object_SubFlags(child, AQDG_OBJECT_FLAGS_HIDDEN);
    child=AQDG_Object_Tree2_GetNext(child);
  }
}








