#define DEBUG
#include <debug.h>
#include "sysi2.h"

extern LONG Enabled;

void Rescale(struct SysIData *SIData, struct DrawInfo *DI, UWORD Width, UWORD Height);

ULONG __saveds __asm Dispatcher(register __a0 Class *C, register __a2 struct Image *O, register __a1 Msgs M )
{
  struct SysIData *sidata;
  struct Image *object;
  ULONG retval=0;

  switch(M->MethodID)
  {
    case OM_NEW:
      {
        struct DrawInfo *di;
        
        di=(struct DrawInfo *)GetTagData(SYSIA_DrawInfo,0, M->opSet.ops_AttrList);
        
        if(di)
        {
          if(object=(struct Image *)DoSuperMethodA(C,(Object *)O,(Msg)M))
          {
            sidata=INST_DATA(C, object);
            
            sidata->si_Which   =GetTagData(SYSIA_Which,   0, M->opSet.ops_AttrList);;
            sidata->si_DrawInfo=di;
            Rescale(sidata,di,O->Width,O->Height);
          }
        }
        retval=(ULONG)object;
      }
      break;

    case IM_DRAWFRAME:
    case IM_DRAW:
      if(Enabled)
        retval=RenderImage(C,O,(Msgs)M);
      else
        retval=DoSuperMethodA(C,O,M);
      break;

    default:
      retval=DoSuperMethodA(C,(Object *)O,(Msg)M);
      break;
  }
  return(retval);
}

#define SI2_INACTIVE    1<<0
#define SI2_SELECTED    1<<1
#define SI2_DISABLED    1<<2

ULONG __saveds RenderImage(Class *C, struct Image *Image, Msgs M)
{
  struct DrawInfo *di;
  struct SysIData *sidata;
  struct RastPort *rp,rirp;
  LONG state;
  LONG left,top,right,bottom,width,height;
  LONG oleft,otop,oright,obottom,owidth,oheight;
  ULONG l,
        shinepen,shadowpen,backgroundpen,fillpen,
        btoppen,bbotpen,bfillpen; // These are for the images button colors.
  WORD w[11],h[11];
  ULONG rv=1;
  BOOL selected,active;

  ULONG att[]=
  {
    0,
    SI2_SELECTED,
    SI2_DISABLED,
    0,
    0,
    SI2_INACTIVE,
    SI2_INACTIVE | SI2_SELECTED,
    SI2_INACTIVE | SI2_DISABLED,
    SI2_SELECTED | SI2_DISABLED,
  };


  sidata=INST_DATA(C, Image);

  if(!(di=M->impDraw.imp_DrInfo))
    di=sidata->si_DrawInfo;

  shinepen      =di->dri_Pens[SHINEPEN];
  shadowpen     =di->dri_Pens[SHADOWPEN];
  backgroundpen =di->dri_Pens[BACKGROUNDPEN];
  fillpen       =di->dri_Pens[FILLPEN];
  
  rirp=*M->impDraw.imp_RPort;
  rp=&rirp;
  
  SetDrMd(rp,JAM1);
  SetDrPt(rp,65535);
  
  
  if(M->MethodID==IM_DRAWFRAME)
  {
    Rescale(sidata,di,M->impDraw.imp_Dimensions.Width,M->impDraw.imp_Dimensions.Height);
  }
  else
  {
    Rescale(sidata,di,Image->Width,Image->Height);
  }
  
  width =sidata->si_Width;
  height=sidata->si_Height;
  
  oleft   =M->impDraw.imp_Offset.X;
  otop    =M->impDraw.imp_Offset.Y;
  left    =oleft + sidata->si_X;
  top     =otop  + sidata->si_Y;
  
  owidth  =sidata->si_OW;
  oheight =sidata->si_OH;
  oright  =oleft + owidth-1;
  obottom =otop  + oheight-1;

  right =left + width  -1;
  bottom=top  + height -1;

  // precalculates a 10 x 10 grid for rendering.
  
  for(l=0;l<6;l++)
  {
    LONG x,y;
    
    x=(width  * l)/10;
    y=(height * l)/10;
    w[l]=x + left;
    h[l]=y + top;
    w[10-l]=right-x;
    h[10-l]=bottom-y;
  }
  
  state=att[M->impDraw.imp_State];
  selected  =  state & SI2_SELECTED;
  active    =!(state & SI2_INACTIVE);

  if(selected)
  {
    btoppen=shadowpen;
    bbotpen=shinepen;
  }
  else
  {
    btoppen=shinepen;
    bbotpen=shadowpen;
  }
  
  if(active)
    bfillpen=fillpen;
  else
    bfillpen=backgroundpen;
  
  switch(sidata->si_Which)
  {
    case SDEPTHIMAGE:
      bfillpen=backgroundpen;
    case DEPTHIMAGE:
      DrawBack(rp,btoppen,bbotpen,bfillpen,left,top,right,bottom);
      if(selected)
      {
        DrawBack(rp,shadowpen,shinepen ,bfillpen,w[4],h[4],w[8],h[8]);
        DrawBack(rp,shadowpen,shinepen ,backgroundpen,w[2],h[2],w[6],h[6]);
        SetAPen(rp,shadowpen);
        DrawPoly(rp,3,w[6]+1,h[4],
                      w[6]+1,h[6]+1,
                      w[4]  ,h[6]+1);
        
      }
      else
      {
        DrawBack(rp,shadowpen,shinepen ,bfillpen,w[2],h[2],w[6],h[6]);
        DrawBack(rp,shadowpen,shinepen ,backgroundpen,w[4],h[4],w[8],h[8]);
        SetAPen(rp,shinepen);
        DrawPoly(rp,3,w[6]  ,h[4]-1,
                      w[4]-1,h[4]-1,
                      w[4]-1,h[6]);
      }

      if(sidata->si_Which==SDEPTHIMAGE && di->dri_Version>=2) 
        shadowpen=di->dri_Pens[BARTRIMPEN];

      SetAPen(rp,shadowpen);
      Move(rp,left-1,top+1);
        Draw(rp,left-1,bottom);
      break;

    case ZOOMIMAGE:
      DrawBack(rp,btoppen,bbotpen,bfillpen,left,top,right,bottom);    

      {
        int s;
        
        if(selected)
          s=6;
        else
          s=5;
      
      DrawBack(rp,shadowpen,shinepen,bfillpen,w[2],h[2],w[s-1],h[s-1]);

      SetAPen(rp,backgroundpen);
      FillPoly(rp, 6,w[s],h[2],
                     w[8],h[2],
                     w[8],h[8],
                     w[2],h[8],
                     w[2],h[s],
                     w[s],h[s]);
      SetAPen(rp,shinepen);
        DrawPoly(rp,3,w[8],h[2],
                      w[8],h[8],
                      w[2],h[8]);
      SetAPen(rp,shadowpen);
        DrawPoly(rp,5,w[2],h[8],
                      w[2],h[s],
                      w[s],h[s],
                      w[s],h[2],
                      w[8],h[2]);
      }        

      SetAPen(rp,shadowpen);
      Move(rp,left-1,top+1);
        Draw(rp,left-1,bottom);
      break;

    case SIZEIMAGE:
      DrawBack(rp,btoppen,bbotpen,bfillpen,oleft,otop,oright,obottom);    

      SetAPen(rp,backgroundpen);
      FillPoly(rp,3,w[8],h[1],
                    w[8],h[8],
                    w[1],h[8]);
       
      SetAPen(rp,shinepen);
      Move(rp,w[1],h[8]);
        Draw(rp,w[8],h[8]);
        Draw(rp,w[8],h[1]);
      
      SetAPen(rp,shadowpen);
        Draw(rp,w[1],h[8]);

/*
      SetAPen(rp,backgroundpen);
      FillPoly(rp,3,w[8],h[2],
                    w[8],h[8],
                    w[2],h[8]);
       
      SetAPen(rp,shinepen);
      Move(rp,w[8],h[2]);
        Draw(rp,w[8],h[8]);
        Draw(rp,w[2],h[8]);
      
      SetAPen(rp,shadowpen);
        Draw(rp,w[8],h[2]);
*/
      break;

    case CLOSEIMAGE:
      {
        int x1,x2,y1,y2;
        DrawBack(rp,btoppen,bbotpen,bfillpen,left,top,right,bottom);    
        y1=4;
        y2=6;
      
        if(selected)
        {
          x1=4;
          x2=6;
        } 
        else
        {
          x1=2;
          x2=8;
        }
        
        SetAPen(rp,shadowpen);
        Move(rp,w[x1],h[6]-1);
          Draw(rp,w[x1],h[4]+1);
        Move(rp,w[x1]+1,h[4]);
          Draw(rp,w[x2]-1,h[4]);
        
        SetAPen(rp,shinepen);
        Move(rp,w[x2],h[4]+1);
          Draw(rp,w[x2],h[6]-1);
        Move(rp,w[x2]-1,h[6]);
          Draw(rp,w[x1]+1,h[6]);
        Move(rp,right+1,top+1);
          Draw(rp,right+1,bottom);
        
        SetAPen(rp,backgroundpen);
        MyRectFill(rp,w[x1]+1,h[4]+1,w[x2]-1,h[6]-1);
      }
      break;
      
    case LEFTIMAGE:
      DrawBack(rp,btoppen,bbotpen,bfillpen,oleft,otop,oright,obottom);          

      SetAPen(rp,backgroundpen);
      FillPoly(rp,3,w[8],h[1],
                    w[8],h[9],
                    w[1],h[5]);
      SetAPen(rp,shinepen);
      Move(rp,w[8],h[1]);
        Draw(rp,w[8],h[9]);
        Draw(rp,w[1],h[5]);
      
      SetAPen(rp,shadowpen);
      Move(rp,w[1],h[5]);
        Draw(rp,w[8],h[1]);
      break;

    case UPIMAGE:
      DrawBack(rp,btoppen,bbotpen,bfillpen,oleft,otop,oright,obottom);    
      
      SetAPen(rp,backgroundpen);
      FillPoly(rp,3,w[1],h[8],
                    w[5],h[1],
                    w[9],h[8]);
      SetAPen(rp,shinepen);
      Move(rp,w[9],h[8]);
        Draw(rp,w[1],h[8]);
      
      SetAPen(rp,shadowpen);
      Move(rp,w[1],h[8]);
        Draw(rp,w[5],h[1]);
        Draw(rp,w[9],h[8]);
      break;

    case RIGHTIMAGE:
      DrawBack(rp,btoppen,bbotpen,bfillpen,oleft,otop,oright,obottom);    

      SetAPen(rp,backgroundpen);
      FillPoly(rp,3,w[9],h[5],
                    w[2],h[9],
                    w[2],h[1]);
      
      SetAPen(rp,shinepen);
      Move(rp,w[9],h[5]);
        Draw(rp,w[2],h[9]);
        
      SetAPen(rp,shadowpen);
      Move(rp,w[2],h[9]);
        Draw(rp,w[2],h[1]);
        Draw(rp,w[9],h[5]);
      break;

    case DOWNIMAGE:
      DrawBack(rp,btoppen,bbotpen,bfillpen,oleft,otop,oright,obottom);    
  
      SetAPen(rp,backgroundpen);     
      FillPoly(rp,3,w[1],h[2],
                    w[9],h[2],
                    w[5],h[9]);
      
      SetAPen(rp,shinepen);
      Move(rp,w[9],h[2]);
        Draw(rp,w[5],h[9]);
        Draw(rp,w[1],h[2]);
      
      SetAPen(rp,shadowpen);
      Move(rp,w[1],h[2]);
        Draw(rp,w[9],h[2]);
      break;

/*    case MENUCHECK:
        Doesn't Work! I don't know why
*/

    case CHECKIMAGE:
      SetAPen(rp,backgroundpen);
      RectFill(rp,oleft,otop,oright,obottom);
      
      SetAPen(rp,shinepen);
        Move(rp,w[1]+1,h[9]-2);
          Draw(rp, w[1]+1,h[1]+1);
          Draw(rp, w[9]-2,h[1]+1);
        Move(rp,w[1]+1,h[9]);
          Draw(rp, w[9],h[9]);
          Draw(rp, w[9],h[1]+1);

      SetAPen(rp,shadowpen);
        Move(rp,w[1],h[9]-1);
          Draw(rp, w[1],h[1]);
          Draw(rp, w[9]-1,h[1]);
        Move(rp,w[1]+2,h[9]-1);
          Draw(rp, w[9]-1,h[9]-1);
          Draw(rp,w[9]-1,h[1]+2);

/*      
      DrawBack(rp,shadowpen,shinepen,backgroundpen,w[1],h[1],w[9],h[9]);    
      DrawBack(rp,shinepen,shadowpen,backgroundpen,w[1]+1,h[1]+1,w[9]-1,h[9]-1);    
*/
      if(selected)
      {
        SetAPen(rp,di->dri_Pens[TEXTPEN]);     
        
        FillPoly(rp,6,w[0],h[5],
                      w[1],  h[4],
                      w[3],  h[6],
                      w[9],  h[0],
                      w[10], h[1],
                      w[3],  h[8]);
/*
      

        SetAPen(rp,shadowpen);
          Draw(rp,w[3],h[8]);
          Draw(rp,w[0],h[5]);
*/
      }
      break;

    case MXIMAGE:
    /*
      if(state & SI2_SELECTED)
        SetAPen(rp,fillpen);
      else
        SetAPen(rp,backgroundpen);
        
      FillPoly(rp,4,w[2],h[5],
                    w[5],h[2],
                    w[8],h[5],
                    w[5],h[8]);
      
      SetAPen(rp,bbotpen);
      Move(rp,w[0],h[5]);
        Draw(rp,w[5],h[10]);
        Draw(rp,w[10],h[5]);
      
      SetAPen(rp,btoppen);
      Move(rp,w[0],h[5]);
        Draw(rp,w[5],h[0]);
        Draw(rp,w[10],h[5]);
*/

      if(selected)
        SetAPen(rp,fillpen);
      else
        SetAPen(rp,backgroundpen);
      
      FillPoly(rp,16,w[10],h[4],
                     w[10],h[6],
                     w[9],h[8],
                     w[8],h[9],
                     w[6],h[10],
                     w[4],h[10],
                     w[2],h[9],
                     w[1],h[8],
                     w[0],h[6],
                     w[0],h[4],
                     w[1],h[2],
                     w[2],h[1],      
                     w[4],h[0],      
                     w[6],h[0],      
                     w[8],h[1],      
                     w[9],h[2]);      
      
      SetAPen(rp,bbotpen);
      Move(rp,w[9],h[2]);
        Draw(rp,w[10],h[4]);
        Draw(rp,w[10],h[6]);
        Draw(rp,w[9],h[8]);
        Draw(rp,w[8],h[9]);
        Draw(rp,w[6],h[10]);
        Draw(rp,w[4],h[10]);
        Draw(rp,w[2],h[9]);
        Draw(rp,w[1],h[8]);
      SetAPen(rp,btoppen);
        Draw(rp,w[0],h[6]);
        Draw(rp,w[0],h[4]);
        Draw(rp,w[1],h[2]);
        Draw(rp,w[2],h[1]);
        Draw(rp,w[4],h[0]);
        Draw(rp,w[6],h[0]);
        Draw(rp,w[8],h[1]);
        Draw(rp,w[9],h[2]); 
      break;
    default:
      rv=DoSuperMethodA(C,(Object *)Image,(Msg)M);
  }
  return(rv);
}



void Rescale(struct SysIData *SIData, struct DrawInfo *DI, UWORD Width, UWORD Height)
{
  WORD ow,oh,width,height;
  
  SIData->si_OW =ow=width =Width;
  SIData->si_OH =oh=height=Height;

//  kprintf("%8lx %8lx %ld %ld\n",SIData,DI,Width,Height);

  switch(SIData->si_Which)
  {
    case DEPTHIMAGE:
    case ZOOMIMAGE:
      width--;
      break;
    /* Aspect Correction for the following images */
    case LEFTIMAGE:
    case UPIMAGE:
    case DOWNIMAGE:
    case RIGHTIMAGE:
    case SIZEIMAGE:
      Width -=2; // area inside border
      Height-=2;
    case CHECKIMAGE:
    case MXIMAGE:
      /* I like even numbers */

      height= Width  * DI->dri_Resolution.X / (max(DI->dri_Resolution.Y,1));
      width = Height * DI->dri_Resolution.Y / (max(DI->dri_Resolution.X,1));
      
      if(height>Height)
        height=Height;
      else
        width=Width;      
      
      width &=(~1);
      height&=(~1);
      break;
  }
  SIData->si_Y=(oh-height)/2;
  SIData->si_X=(ow-width)/2;
  SIData->si_Width =width;
  SIData->si_Height=height;

}

/*
  switch(sidata->si_Which)
  {
    case DEPTHIMAGE:
    case ZOOMIMAGE:
      width--;
      break;
    case LEFTIMAGE:
    case UPIMAGE:
    case DOWNIMAGE:
    case RIGHTIMAGE:
    case CHECKIMAGE:
    case MXIMAGE:
    case SIZEIMAGE:
      {
        width &=(~1);
        height&=(~1);
        kprintf("sx=%ld sy=%ld x=%ld  y=%ld\n",sidata->si_DrawInfo->dri_Resolution.X,sidata->si_DrawInfo->dri_Resolution.Y,
                                               di->dri_Resolution.X,                 di->dri_Resolution.Y);
        if(di->dri_Resolution.Y > di->dri_Resolution.X)
        {
          height=width*di->dri_Resolution.X/di->dri_Resolution.Y;
          top+=(oheight-height)/2;
        }
        else
        {
          width=height*di->dri_Resolution.Y/di->dri_Resolution.X;
          left+=(owidth-width)/2;
        }
      }
      break;
  }
*/
