#include <exec/types.h>
#include <graphics/gfx.h>
#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/graphics.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/icon.h>
#include <proto/layers.h>
#include <prefs/wbpattern.h>
#include <prefs/prefhdr.h>
#include <graphics/gfxmacros.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <exec/memory.h>

#include "ProgressWindow.h"
#include "WBStartup+.h"

#define winwidth 400
#define winheight 80
#define BARHEIGHT 12
#define XOFFSET 75

static UWORD BackgroundPen, HighlightTextPen, ShinePen, ShadowPen;
ULONG __chip Crosshatch = 0x5555AAAA;
static struct WBStartup *wbarg=NULL;


struct ProgressWindowData *CreateProgressWindow(struct WBStartupPrefs *prefs);
void CloseProgressWindow(struct ProgressWindowData *data);
void UpdateProgressBar(struct Window *win, int current, int total);
void ShowIconImage(struct ProgressWindowData *data, struct Image *image);
BOOL InteractiveRunProgram(struct Window *win);
void DisplayProgramName(struct ProgressWindowData *data, char *name, BOOL query);


struct ProgressWindowData *CreateProgressWindow(struct WBStartupPrefs *prefs)
{
  ULONG scrwidth=640,scrheight=200;
  struct Rectangle rect;
  LONG screen_modeID;
  void *vi;
  char buffer[7],*TitleText="Amiga Workbench \0\0\0\0\0\0\0";
  struct IntuiText iText = { 2,0,0,0,0,NULL,NULL,NULL};
  struct DrawInfo *dri;
  struct Screen *scr;

  struct DiskObject *diskobj=NULL;  /* This must be initialized to NULL */
  struct Process *process;
  char buf[200];
  struct Image *image;
  struct ProgressWindowData *windata;
  BOOL success=FALSE;

  if (windata = AllocVec(sizeof(struct ProgressWindowData),MEMF_ANY))
  {
    if (scr=LockPubScreen(prefs->PubScreenName))
    {

      /********************************************/
      /* Determine the Size of the visible screen */
      /********************************************/
      screen_modeID = GetVPModeID(&(scr->ViewPort));
      if (screen_modeID != INVALID_ID)
      {
        if (QueryOverscan(screen_modeID, &rect, OSCAN_TEXT))
        {
          scrwidth  = rect.MaxX - rect.MinX + 1;
          scrheight = rect.MaxY - rect.MinY + 1;

          scrwidth  = min(scrwidth,scr->Width);
          scrheight = min(scrheight,scr->Height);
        }
      }

      /*******************************/
      /* Get WBStartup+'s Icon image */
      /*******************************/
      if (process = (struct Process *)FindTask(NULL))
      {
        NameFromLock(process->pr_HomeDir,buf,199);
        AddPart(buf,process->pr_Task.tc_Node.ln_Name,199);

        if (diskobj=(GetDiskObject(buf)))  // We release the Disk Object down below!
          image = (struct Image *)diskobj->do_Gadget.GadgetRender;
      }

      if (windata->win = OpenWindowTags(NULL,
          WA_Left,   (scrwidth-winwidth)/2,
          WA_Top,    (scrheight-winheight)/2,
          WA_Width, winwidth,
          WA_Height, winheight,
          WA_AutoAdjust, TRUE,
          WA_Activate, prefs->Interactive,
          WA_IDCMP,  (prefs->Interactive) ? IDCMP_VANILLAKEY : 0L,
          WA_Flags,  WFLG_SMART_REFRESH | WFLG_ACTIVATE,
          WA_PubScreen, scr,
          WA_PubScreenFallBack, "Workbench",
          TAG_END))
      {
        /* Set Global Pen Numbers */
        if (dri = GetScreenDrawInfo(scr))
        {
          BackgroundPen = dri->dri_Pens[BACKGROUNDPEN];
          HighlightTextPen = dri->dri_Pens[HIGHLIGHTTEXTPEN];
          ShinePen = dri->dri_Pens[SHINEPEN];
          ShadowPen = dri->dri_Pens[SHADOWPEN];
          FreeScreenDrawInfo( scr, dri );
        }

        if (vi=GetVisualInfo(scr,TAG_DONE))
        {
          DrawBevelBox(windata->win->RPort, XOFFSET, 34, windata->win->Width-150, BARHEIGHT, GTBB_Recessed, TRUE, GT_VisualInfo, vi, TAG_DONE);  /* Draw Progress Indicator Box */
          FreeVisualInfo(vi);
        }

        /************************/
        /* Write text to window */
        /************************/
        if (GetVar("Workbench",buffer,7,0)>=0)
          strcat(TitleText,buffer);
        iText.IText = TitleText;
        iText.FrontPen = ShadowPen;
        PrintIText(windata->win->RPort, &iText, ((windata->win->Width-IntuiTextLength(&iText))/2)+1, 16);
        iText.FrontPen = HighlightTextPen;
        PrintIText(windata->win->RPort, &iText, (windata->win->Width-IntuiTextLength(&iText))/2, 15);

        SetAfPt(windata->win->RPort, NULL, 0);

        success=TRUE;

      }

      if (diskobj)
      {
        DrawImage(windata->win->RPort,image,((XOFFSET-windata->win->BorderLeft-image->Width)/2)+windata->win->BorderLeft,((80-image->Height)/2));
        FreeDiskObject(diskobj);
      }

      UnlockPubScreen(NULL,scr);
    }
  }

  if (!success)
  {
    FreeVec(windata);
    windata=NULL;
  }

  return(windata);
}

void CloseProgressWindow(struct ProgressWindowData *data)
{
  CloseWindow(data->win);
  FreeVec(data);
}

void UpdateProgressBar(struct Window *win, int current, int total)
{
  int x;
  x = ((win->Width-(2*(XOFFSET+2)))*current/total)+(XOFFSET+2);

  SetAfPt(win->RPort,(UWORD *)&Crosshatch,1);
  SetBPen(win->RPort,ShinePen);
  SetAPen(win->RPort,3);
  RectFill(win->RPort,(XOFFSET+2),35,x,35+BARHEIGHT-3);
}

void ShowIconImage(struct ProgressWindowData *data, struct Image *image)
{
  struct Region *reg;
  struct Region *oldreg;
  struct Rectangle rect;

  SetAfPt(data->win->RPort,NULL,0);
  SetAPen(data->win->RPort,BackgroundPen);
  RectFill(data->win->RPort,winwidth-XOFFSET,data->win->BorderTop,winwidth-data->win->BorderRight-1,winheight-data->win->BorderBottom-1);

  rect.MinX=winwidth-XOFFSET;
  rect.MinY=data->win->BorderTop;
  rect.MaxX=winwidth-data->win->BorderRight-1;
  rect.MaxY=winheight-data->win->BorderBottom-1;
  if (reg=NewRegion())
  {
    OrRectRegion(reg,&rect);

    oldreg=InstallClipRegion(data->win->WLayer,reg);

    DrawImage(data->win->RPort,image,(400-XOFFSET)+((XOFFSET-image->Width)/2),((80-image->Height)/2));

    InstallClipRegion(data->win->WLayer,oldreg);

    DisposeRegion(reg);
  }

}




BOOL InteractiveRunProgram(struct Window *win)
{
  BOOL runprogram=FALSE;
  struct IntuiMessage *msg;
  BOOL done=FALSE;

  while (!done)
  {
    Wait(1L<<win->UserPort->mp_SigBit);

    while (msg = (struct IntuiMessage *)GetMsg(win->UserPort))
    {
      if (msg->Class == IDCMP_VANILLAKEY)
        if (msg->Code=='Y' || msg->Code=='y')
        {
          done=TRUE;
          runprogram = TRUE;
        }
        else if (msg->Code=='N' || msg->Code=='n')
        {
          done=TRUE;
          runprogram = FALSE;
        }
      ReplyMsg((struct Message *)msg);
    }
  }

  return(runprogram);
}

void DisplayProgramName(struct ProgressWindowData *data, char *name, BOOL query)
{
  struct IntuiText iText = { 2,0,0,0,0,NULL,NULL,NULL};
  char *outputbuffer;

  SetAfPt(data->win->RPort,NULL,0);
  SetAPen(data->win->RPort,BackgroundPen);
  RectFill(data->win->RPort,XOFFSET,34+BARHEIGHT,winwidth-XOFFSET-1,winheight-data->win->BorderBottom-1);

  if (outputbuffer = AllocVec(strlen(name)+3,MEMF_ANY))
  {
    strcpy(outputbuffer,name);
    if (query)
      strcat(outputbuffer," ?");
    iText.IText = outputbuffer;
    iText.FrontPen = ShadowPen;
    PrintIText(data->win->RPort, &iText, (data->win->Width-IntuiTextLength(&iText))/2, 34+BARHEIGHT+((data->win->Height-34-BARHEIGHT-data->win->WScreen->Font->ta_YSize)/2)+2);

    FreeVec(outputbuffer);
  }
}
