/*
 * Copyright (c) 1993 Michael D. Bayne.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *    following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 *    following disclaimer in the documentation and/or other materials provided with the distribution.
 *
 * 3. All advertising materials mentioning features or use of this software must display the following
 *    acknowledgement:
 *
 *       This product includes software developed by Michael D. Bayne.
 *
 * 4. My name may not be used to endorse or promote products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY MICHAEL D. BAYNE ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL MICHAEL D. BAYNE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <exec/types.h>
#include <exec/memory.h>

#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <workbench/workbench.h>

#include <libraries/gadtools.h>
#include <libraries/reqtools.h>

#include <graphics/displayinfo.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/icon_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/reqtools_protos.h>
#include <clib/alib_protos.h>

#include "defs.h"
#include "Blanker.h"
#include "Blanker_rev.h"

LONG UpdateCX( void );

VOID loadModule( ULONG );
LONG sendModMsg( ULONG );

UBYTE *doPath( UBYTE *, UBYTE * );
void prefError( LONG );
LONG loadBlankerPrefs( UBYTE *, UBYTE *, struct bPrefObject * );
LONG saveBlankerPrefs( UBYTE *, UBYTE *, struct bPrefObject *, ULONG );

extern	struct	Task *bTask, *Task;
extern	struct	MsgPort *blankerPort, *modulePort;
extern	struct	bPrefObject bPrefs;
extern	CxObj	*bBroker, *pHotKey, *bHotKey;
extern	ULONG	rc, tags[];
	UBYTE	prefName[108] = "Blanker.pre", prefDir[108] = "SYS:Prefs/Presets/Blanker", modInfo[64];

ULONG doImage( UBYTE *path )
{
	struct DiskObject *bDO;
	struct Image *Image;

	ULONG x = ( FontX * 6 + 4 ) / 8 + 3, y = ( FontY * 35 + 4 ) / 8 + 2;
	ULONG dx = ( FontX * 85 + 4 ) / 8 - 6, dy = ( FontY * 45 + 4 ) / 8 - 4;

	if(!( bDO = GetDiskObjectNew( path ))) {
		EZRQ( "GetDiskObjectNew() failed. Can't load image." );
		return( 1L );
	}
	
	Image = ( struct Image * )( bDO->do_Gadget.GadgetRender );
	Image->LeftEdge = x + OffX + (dx-Image->Width)/2;
	Image->TopEdge = y + OffY + (dy-Image->Height)/2;
	EraseRect( BlankerWnd->RPort, x + OffX, y + OffY, x + dx + OffX, y + dy + OffY );
	DrawImage( BlankerWnd->RPort, Image, 0, 0 );
	FreeDiskObject( bDO );

	return( 0L );
}

void setPrefs( struct bPrefObject *cP, UBYTE gad )
{
	struct NameInfo sInf;
	struct Menu *MenuStrip;
	struct MenuItem *Item;

	if(( gad == GD_TOUT )||( gad == Blanker_CNT )) GT_SetGadgetAttrs( BlankerGadgets[GD_TOUT], BlankerWnd, 0L,
		GTIN_Number, (cP->bTimeout)/10, 0L );

	if(( gad == GD_PKEY )||( gad == Blanker_CNT )) GT_SetGadgetAttrs( BlankerGadgets[GD_PKEY], BlankerWnd, 0L,
		GTST_String, cP->pKey, 0L );

	if(( gad == GD_BKEY )||( gad == Blanker_CNT )) GT_SetGadgetAttrs( BlankerGadgets[GD_BKEY], BlankerWnd, 0L,
		GTST_String, cP->bKey, 0L );

	if(( gad == GD_MODINFO )||( gad == Blanker_CNT )) {
		GT_SetGadgetAttrs( BlankerGadgets[GD_BMOD], BlankerWnd, 0L, GA_Disabled, !(BS_VALMOD&cP->Flags), 0L );
		GT_SetGadgetAttrs( BlankerGadgets[GD_MODINFO], BlankerWnd, 0L, GTTX_Text, modInfo, 0L );
		if( BS_VALMOD & cP->Flags ) doImage( doPath( bPrefs.modName, bPrefs.modDir ));
		else doImage( "Blanker" );
	}

	if(( gad == GD_MDISPLAY )||( gad == Blanker_CNT )) {
		if( GetDisplayInfoData( 0l, ( UBYTE * )&sInf, sizeof( struct NameInfo ), DTAG_NAME, cP->sMod ))
			GT_SetGadgetAttrs( BlankerGadgets[GD_MDISPLAY], BlankerWnd, 0L, GTTX_Text, sInf.Name, 0L );
		else GT_SetGadgetAttrs( BlankerGadgets[GD_MDISPLAY], BlankerWnd, 0L, GTTX_Text, "No Monitor Info", 0L );
		GT_SetGadgetAttrs( BlankerGadgets[GD_SDEP], BlankerWnd, 0L, GTNM_Number, 1<<(cP->sDep), 0L );
		GT_SetGadgetAttrs( BlankerGadgets[GD_SMODE], BlankerWnd, 0L, GA_Disabled, !(cP->Flags&BS_ASKSCR), 0L );
	}

	if( gad == Blanker_CNT ) {
		MenuStrip = BlankerWnd->MenuStrip;
		ClearMenuStrip( BlankerWnd );

		Item = MenuStrip->NextMenu->NextMenu->FirstItem;
		if( bPrefs.Flags & BS_SICONS ) Item->Flags |= CHECKED;
		else Item->Flags &= ~CHECKED;

		Item = Item->NextItem;
		if( bPrefs.Flags & BS_RANDOM ) Item->Flags |= CHECKED;
		else Item->Flags &= ~CHECKED;

		ResetMenuStrip( BlankerWnd, MenuStrip );
	}
}

void defBlanker( void )
{
	struct	Screen	*Scr;
	UWORD   CTable[] = { 0x0222, 0x0AAA, 0x0AAA };

	bTask = Task;

	Scr = OpenScreenTags( 0l, SA_DisplayID, bPrefs.sMod, SA_Depth, bPrefs.sDep, SA_Quiet, TRUE, SA_Overscan,
		OSCAN_STANDARD, TAG_DONE );
	LoadRGB4( &(Scr->ViewPort), CTable, 2 );

	Wait( SIGBREAKF_CTRL_C );

	CloseScreen( Scr );
}

int TOUTClicked( void )
{
	bPrefs.bTimeout = 10*(((struct StringInfo*)(BlankerGadgets[GD_TOUT])->SpecialInfo)->LongInt);
	return( UpdateCX() );
}

int BKEYClicked( void )
{
	CopyMem( ((struct StringInfo *)(BlankerGadgets[GD_BKEY])->SpecialInfo )->Buffer, bPrefs.bKey, 256 );
	return( UpdateCX() );
}

int PKEYClicked( void )
{
	CopyMem( ((struct StringInfo *)(BlankerGadgets[GD_PKEY])->SpecialInfo )->Buffer, bPrefs.pKey, 256 );
	return( UpdateCX() );
}

int HIDEClicked( void )
{
	return( CLOSEWIN );
}

int SAVEClicked( void )
{
	if( rc = saveBlankerPrefs( "Blanker.prefs", "ENVARC:", &bPrefs, 0 )) prefError( rc );
	if( rc = saveBlankerPrefs( "Blanker.prefs", "ENV:", &bPrefs, 0 )) prefError( rc );

	return( OK );
}

int QUITClicked( void )
{
	return( QUIT );
}

int SMODEClicked( void )
{
	struct rtScreenModeRequester *smRequest;

	if( smRequest = rtAllocRequestA( RT_SCREENMODEREQ, 0l )) {
		rtChangeReqAttr( smRequest, RTSC_DisplayID, bPrefs.sMod, RTSC_DisplayDepth, bPrefs.sDep, TAG_END );
		tags[4] = RTSC_Flags;
		if( bPrefs.Flags & BS_ASKDEP ) {
			tags[5] = SCREQF_DEPTHGAD|SCREQF_NONSTDMODES;
			if( rtScreenModeRequestA( smRequest, "Screen Mode", BTAGS )) {
				bPrefs.sDep = smRequest->DisplayDepth;
				bPrefs.sMod = smRequest->DisplayID;
			}
		} else {
			tags[5] = SCREQF_NONSTDMODES;
			if( rtScreenModeRequestA( smRequest, "Screen Mode", BTAGS ))
				bPrefs.sMod = smRequest->DisplayID;
		}
		tags[4] = TAG_END;
		setPrefs( &bPrefs, GD_MDISPLAY );
		rtFreeRequest( smRequest );
	} else EZRQ( "Not enough memory to allocate\nscreen mode requester." );
	return( OK );
}

int BMODClicked( void )
{
	sendModMsg( BM_DOPREFS );

	return( OK );
}

int LMODClicked( void )
{
	struct rtFileRequester *fRequest;

	if( fRequest = rtAllocRequest( RT_FILEREQ, 0L )) {
		rtChangeReqAttr( fRequest, RTFI_Dir, bPrefs.modDir, TAG_END );
		tags[4] = RTFI_Flags;
		tags[5] = FREQF_PATGAD;
		if( rtFileRequestA( fRequest, bPrefs.modName, "Please choose blanker module...", BTAGS )) {
			if( modulePort ) sendModMsg( BM_DOQUIT );
			CopyMem( fRequest->Dir, bPrefs.modDir, 108 );
			loadModule( 1 );
		}
		tags[4] = TAG_END;
	} else EZRQ( "Couldn't allocate file requester." );
	return( OK );
}

int BlankerOpen( void )
{
	struct rtFileRequester *fRequest;

	if( fRequest = rtAllocRequest( RT_FILEREQ, 0L )) {
		rtChangeReqAttr( fRequest, RTFI_Dir, prefDir, RTFI_MatchPat, "#?.pre", TAG_END );
		tags[4] = RTFI_Flags;
		tags[5] = FREQF_PATGAD;
		if( rtFileRequestA( fRequest, prefName, "Please choose prefs file...", BTAGS ))
			if( rc = loadBlankerPrefs( prefName, fRequest->Dir, &bPrefs )) prefError( rc );
		tags[4] = TAG_END;
	} else EZRQ( "Couldn't allocate file requester." );
	return( OK );
}

int BlankerSaveAs( void )
{
	struct rtFileRequester *fRequest;

	if( fRequest = rtAllocRequest( RT_FILEREQ, 0L )) {
		rtChangeReqAttr( fRequest, RTFI_Dir, prefDir, RTFI_MatchPat, "#?.pre", TAG_END );
		tags[4] = RTFI_Flags;
		tags[5] = FREQF_PATGAD;
		if( rtFileRequestA( fRequest, prefName, "Please choose a save file...", BTAGS ))
			if( rc = saveBlankerPrefs( prefName, fRequest->Dir, &bPrefs, bPrefs.Flags & BS_SICONS ))
				prefError( rc );
		tags[4] = TAG_END;
	} else EZRQ( "Couldn't allocate file requester." );
	return( OK );
}

int BlankerAbout( void )
{
	EZRQ( VERS"\nby Michael D. Bayne\n\nbaynemd@nextwork.rose-hulman.edu" );
	return( OK );
}

int BlankerLoadMod( void )
{
	return( LMODClicked() );
}

int BlankerQuit( void )
{
	return( QUIT );
}

int BlankerLSaved( void )
{
	if( rc = loadBlankerPrefs( "Blanker.prefs", "ENVARC:", &bPrefs )) prefError( rc );
	return( OK );
}

int BlankerRandPrefs( void )
{
	bPrefs.Flags ^= BS_RANDOM;
	return( OK );
}

int BlankerSaveIcons( void )
{
	bPrefs.Flags ^= BS_SICONS;
	return( OK );
}

int BlankerCloseWindow( void )
{
	return( CLOSEWIN );
}

int BlankerVanillaKey( void )
{
	switch( BlankerMsg.Code ) {
	case 'c':
		return( SMODEClicked() );
	case 'r':
		return( BMODClicked() );
	case 'l':
		return( BlankerLoadMod());
	case 't':
		ActivateGadget( BlankerGadgets[GD_TOUT], BlankerWnd, 0l );
		return( OK );
	case 'b':
		ActivateGadget( BlankerGadgets[GD_BKEY], BlankerWnd, 0l );
		return( OK );
	case 'p':
		ActivateGadget( BlankerGadgets[GD_PKEY], BlankerWnd, 0l );
		return( OK );
	case 'h':
		return( HIDEClicked() );
	case 's':
		return( SAVEClicked() );
	case 'q':
		return( QUIT );
	default:
		return( OK );
	}
}
