#include "../../configure.h"

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Intrinsic.h>
#include <unistd.h>
#include <stdio.h>

#include "../../include/aftersteplib.h"
#include "../../include/afterstep.h"
#include "../../include/parse.h"
#include "../../include/misc.h"
#include "../../include/style.h"
#include "../../include/screen.h"
#include "../../include/module.h"
#ifndef NO_TEXTURE
#include "../../include/ascolor.h"
#include "../../include/stepgfx.h"
#endif /* NO_TEXTURE */

#include "../../include/loadimg.h"
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif /* SHAPE */

static void frame_set_sizes ();
typedef struct
{
  Pixmap pix;
  Pixmap mask;
  int w;
  int h;
}side;

typedef struct
{
  side handle[8];
}framed_win;

static framed_win ff;

/* get width and height of a drawable */

static int frame_get_pix_size (Drawable pix, unsigned int *ret_w,
                         unsigned int *ret_h)
{
  Window root;
  unsigned int bw, depth, height, width;
  int x, y;

  XGetGeometry (dpy, pix, &root, &x, &y, &width, &height, &bw, &depth);
  *ret_w = width;
  *ret_h = height;
  return 1;
}

/* load the images */
  
static int frame_load_images ()
{
  extern char *FrameN, *FrameS, *FrameE, *FrameW,
              *FrameNW, *FrameNE, *FrameSW, *FrameSE;
  extern char *PixmapPath;
  char *path;
  int maxcols;

  if (Scr.d_depth > 8)
    maxcols = -1;
  else
    maxcols = 10;

  if (FrameSE != NULL && (path = findIconFile (FrameSE, PixmapPath, R_OK)) != NULL)
    {
      ff.handle[FR_SE].pix = LoadImageWithMask (dpy, Scr.Root, maxcols, path, &ff.handle[FR_SE].mask);
      free (path);
    }
  if (FrameSW != NULL && (path = findIconFile (FrameSW, PixmapPath, R_OK)) != NULL)
    {
      ff.handle[FR_SW].pix = LoadImageWithMask (dpy, Scr.Root, maxcols, path, &ff.handle[FR_SW].mask);
      free (path);
    }
  if (FrameNE != NULL && (path = findIconFile (FrameNE, PixmapPath, R_OK)) != NULL)
    {
      ff.handle[FR_NE].pix = LoadImageWithMask (dpy, Scr.Root, maxcols, path, &ff.handle[FR_NE].mask);
      free (path);
    }
  if (FrameNW != NULL && (path = findIconFile (FrameNW, PixmapPath, R_OK)) != NULL)
    {
      ff.handle[FR_NW].pix = LoadImageWithMask (dpy, Scr.Root, maxcols, path, &ff.handle[FR_NW].mask);
      free (path);
    }
  if (FrameS != NULL && (path = findIconFile (FrameS, PixmapPath, R_OK)) != NULL)
    {
      ff.handle[FR_S].pix = LoadImageWithMask (dpy, Scr.Root, maxcols, path, &ff.handle[FR_S].mask);
      free (path);
    }
  if (FrameN != NULL && (path = findIconFile (FrameN, PixmapPath, R_OK)) != NULL)
    {
      ff.handle[FR_N].pix = LoadImageWithMask (dpy, Scr.Root, maxcols, path, &ff.handle[FR_N].mask);
      free (path);
    }
  if (FrameE != NULL && (path = findIconFile (FrameE, PixmapPath, R_OK)) != NULL)
    {
      ff.handle[FR_E].pix = LoadImageWithMask (dpy, Scr.Root, maxcols, path, &ff.handle[FR_E].mask);
      free (path);
    }
  if (FrameW != NULL && (path = findIconFile (FrameW, PixmapPath, R_OK)) != NULL)
    {
      ff.handle[FR_W].pix = LoadImageWithMask (dpy, Scr.Root, maxcols, path, &ff.handle[FR_W].mask);
      free (path);
    }

  return 1;
}

void frame_init (int free_resources)
{
  int i;
  extern char *FrameN, *FrameS, *FrameE, *FrameW,
              *FrameNW, *FrameNE, *FrameSW, *FrameSE;
  if (free_resources)
    {
      if (FrameN != NULL) free (FrameN);
      if (FrameS != NULL) free (FrameS);
      if (FrameE != NULL) free (FrameE);
      if (FrameW != NULL) free (FrameW);
      if (FrameNE != NULL) free (FrameNE);
      if (FrameSE != NULL) free (FrameSE);
      if (FrameNW != NULL) free (FrameNW);
      if (FrameSW != NULL) free (FrameSW);
      for (i = 0 ; i < 8 ; i++)
        if (ff.handle[i].pix != None)
          UnloadImage(ff.handle[i].pix);
    }
  FrameN = NULL;
  FrameS = NULL;
  FrameE = NULL;
  FrameW = NULL;
  FrameNE = NULL;
  FrameSE = NULL;
  FrameNW = NULL;
  FrameSW = NULL;
  for (i = 0 ; i < 8 ; i++)
    ff.handle[i].pix = None;
}

/* create the gc and fill Scr.frame* with pix sizes */

void frame_create_gcs ()
{
  frame_load_images ();
  frame_set_sizes ();
  return;
}

/* draw the frame */
 
void frame_draw_frame (ASWindow *t)
{
  int i;
  for (i=0; i < 8; i++)
  {
    if (ff.handle[i].pix != None)
      XSetWindowBackgroundPixmap (dpy, t->fw[i], ff.handle[i].pix);
/*    if (ff.handle[i].mask != None)
      XShapeCombineMask (dpy, t->fw[i], ShapeBounding, 0, 0,
                         ff.handle[i].mask, ShapeUnion);*/
    XClearWindow (dpy, t->fw[i]);
  }
  XSetWindowBackgroundPixmap (dpy, t->frame, None);
  XFlush (dpy);
  return;
}

/* free all data, should be called on restart or exit */

void frame_free_data (ASWindow *tw, Bool all)
{
  int i;

  for (i=0; i<8; i++)
  {
    if (all)
      {
        if (ff.handle[i].pix != None)
          UnloadImage (ff.handle[i].pix);
      }
    if (tw != NULL)
      XDeleteContext (dpy, tw->fw[i], ASContext);
  }
  return;
}

/* fill the Screen struct with frame sizes */
static void frame_set_sizes ()
{
  int w, h, i;

  for (i=0;i < 8; i++)
  {
    if (ff.handle[i].pix != None)
    {
      frame_get_pix_size (ff.handle[i].pix, &w, &h);
      fprintf (stderr, "no: %d w: %d h: %d\n", i, w, h);
      Scr.fs[i].w = w;
      Scr.fs[i].h = h;
    }
    else
    {
      Scr.fs[i].w = 0;
      Scr.fs[i].h = 0;
    }
  } 
}
void frame_set_positions (ASWindow *tmp_win)
{
  int i, px, py, pw, ph;

  /* get geometry of parent of client window */
  get_parent_geometry(tmp_win, tmp_win->frame_width, tmp_win->frame_height, &px, &py, &pw, &ph);
  /* get outside geometry of frame */
  px += tmp_win->bw - Scr.fs[FR_W].w;
  py += tmp_win->bw - Scr.fs[FR_N].h;
  pw += Scr.fs[FR_W].w + Scr.fs[FR_E].w;
  ph += Scr.fs[FR_N].h + Scr.fs[FR_S].h;
  for (i=0;i < 8; i++)
  {
    switch (i)
    {
      case FR_N:
        tmp_win->fp[i].x = px + Scr.fs[FR_NW].w;
        tmp_win->fp[i].y = py;
        tmp_win->fp[i].w = pw - Scr.fs[FR_NW].w - Scr.fs[FR_NE].w;
        tmp_win->fp[i].h = Scr.fs[FR_N].h;
        break;
      case FR_S:
        tmp_win->fp[i].x = px + Scr.fs[FR_SW].w;
        tmp_win->fp[i].y = py + ph - Scr.fs[FR_S].h;
        tmp_win->fp[i].w = pw - Scr.fs[FR_SW].w - Scr.fs[FR_SE].w;
        tmp_win->fp[i].h = Scr.fs[FR_S].h;
        break;
      case FR_E:
        tmp_win->fp[i].x = px + pw - Scr.fs[FR_E].w;
        tmp_win->fp[i].y = py + Scr.fs[FR_NE].h;
        tmp_win->fp[i].w = Scr.fs[FR_E].w;
        tmp_win->fp[i].h = ph - Scr.fs[FR_NE].h - Scr.fs[FR_SE].h;
        break;
      case FR_W:
        tmp_win->fp[i].x = px;
        tmp_win->fp[i].y = py + Scr.fs[FR_NW].h;
        tmp_win->fp[i].w = Scr.fs[FR_W].w;
        tmp_win->fp[i].h = ph - Scr.fs[FR_NW].h - Scr.fs[FR_SW].h;
        break;
      case FR_NW:
        tmp_win->fp[i].x = px;
        tmp_win->fp[i].y = py;
        tmp_win->fp[i].w = Scr.fs[FR_NW].w;
        tmp_win->fp[i].h = Scr.fs[FR_NW].h;
        break;
      case FR_NE:
        tmp_win->fp[i].x = px + pw - Scr.fs[FR_NE].w;
        tmp_win->fp[i].y = py;
        tmp_win->fp[i].w = Scr.fs[FR_NE].w;
        tmp_win->fp[i].h = Scr.fs[FR_NE].h;
        break;
      case FR_SE:
        tmp_win->fp[i].x = px + pw - Scr.fs[FR_SE].w;
        tmp_win->fp[i].y = py + ph - Scr.fs[FR_SE].h;
        tmp_win->fp[i].w = Scr.fs[FR_SE].w;
        tmp_win->fp[i].h = Scr.fs[FR_SE].h;
        break;
      case FR_SW:
        tmp_win->fp[i].x = px;
        tmp_win->fp[i].y = py + ph - Scr.fs[FR_SW].h;
        tmp_win->fp[i].w = Scr.fs[FR_SW].w;
        tmp_win->fp[i].h = Scr.fs[FR_SW].h;
        break;
     }
  }
}
Bool
frame_create_windows (ASWindow *tmp_win)
{    
  unsigned long valuemask;
  XSetWindowAttributes attributes;
  int i;

  if (!(tmp_win->flags & FRAME))
    return False;

  valuemask = CWBackPixmap | CWBorderPixel | CWCursor | CWEventMask;
  attributes.background_pixmap = ParentRelative;
  attributes.border_pixel = BlackPixel (dpy, Scr.screen);
  if (Scr.flags & BackingStore)  
    {
      valuemask |= CWBackingStore;
      attributes.backing_store = WhenMapped;
    }
  attributes.event_mask = (ButtonPressMask | ButtonReleaseMask | ExposureMask |
                           EnterWindowMask | LeaveWindowMask);
  frame_set_positions (tmp_win);
  
  for (i=0;i < 8; i++)
  {
    if (ff.handle[i].pix != None)
    {
    switch (i)
    {
      case FR_N:
        attributes.cursor = Scr.ASCursors[TOP];
        break;
      case FR_S:
        attributes.cursor = Scr.ASCursors[BOTTOM];
        break;
      case FR_E:
       attributes.cursor = Scr.ASCursors[RIGHT];
       break;
      case FR_W:
       attributes.cursor = Scr.ASCursors[LEFT];
       break;
      case FR_NW:
       attributes.cursor = Scr.ASCursors[TOP_LEFT];
       break;
      case FR_NE:
       attributes.cursor = Scr.ASCursors[TOP_RIGHT];
       break;
      case FR_SE:
       attributes.cursor = Scr.ASCursors[BOTTOM_RIGHT];
       break;
      case FR_SW:
       attributes.cursor = Scr.ASCursors[BOTTOM_LEFT];
       break;
     }
    tmp_win->fw[i]=
      XCreateWindow (dpy, tmp_win->frame, tmp_win->fp[i].x, tmp_win->fp[i].y,
                     tmp_win->fp[i].w, tmp_win->fp[i].h, 0, CopyFromParent,
                     InputOutput, CopyFromParent, valuemask, &attributes);
    XSaveContext (dpy, tmp_win->fw[i], ASContext, (caddr_t) tmp_win);
    }
  }
  return True;
}    

