#import  "TVController.h"
#import  <appkit/Application.h>
#import  <appkit/publicWraps.h>
#import  <appkit/Control.h>
#import  <appkit/MenuCell.h>
#import  <appkit/workspaceRequest.h>
#import  <objc/NXBundle.h>	/* LocalizedString */
#import  <defaults/defaults.h>
#import  <stdio.h>
#import  <stdlib.h>
#import  <string.h>
#import  <libc.h>
#import  <bsd/libc.h>
#import  <mach/mach_init.h>
#import  <sys/types.h>
#import  <time.h>
#import  "ToyWin.h"
#import  "ToyWinEPS.h"
#import  "ToyView.h"
#import  "BackgCtr.h"
#import  "common.h"
#import  "strfunc.h"
#import  "backgops.h"

@implementation TVController (BackgroundManager)


/* Local Method */
- loadBackgBundle
{
	char bdir[MAXFILENAMELEN];
	id bundle;
	int n;
	static id classBackg = nil;

	if (classBackg)
		return self;
	n = dircopy(bdir, NXArgv[0], YES);
	strcpy(&bdir[n], "BackgCtr.bundle");
	bundle = [[NXBundle alloc] initForDirectory: bdir];
	if (bundle == nil) /* ERROR */
		return nil;
	classBackg = [bundle classNamed:"BackgCtr"];
	if (classBackg == nil) /* ERROR */
		return nil;
	backgCtr = [(BackgCtr *)[classBackg alloc] init];
	return self;
}


/* Local Method */
- readRCWallpaper
{
	char	rc[MAXFILENAMELEN], buf[MAXFILENAMELEN], *fnam, *home;
	int	i, j, n, cc, ln, method;
	NXStream *stream;
	FILE	*fp;
	id	rtn;

	home = getenv("HOME");
	sprintf(rc, "%s/Library/ToyViewer/rc.wallpaper", home);
	if ((fp = fopen(rc, "r")) == NULL)
		return nil;
	buf[0] = 0;
	for (ln = 0; fgets(buf, MAXFILENAMELEN, fp); ) {
		if (buf[0] == '#') continue;
		for (i = 0; i < 4 && buf[i]; i++) ;
		if (i < 4) break;
		ln++;
	}
	n = 1;
	if (ln > 1) {
		static int prev = -1;
		n = ((int)time(NULL) >> 1) % ln + 1;
		if (n == prev)
			n = (n % ln) + 1;
		prev = n;
	}
	rewind(fp);
	for (i = 0; i < n; ) {
		fgets(buf, MAXFILENAMELEN, fp);
		if (buf[0] == '#') continue;
		i++;
	}
	fclose(fp);
	method = bk_CoverScreen; /* default */
	for (i = 0; i < MAXFILENAMELEN - 4; i++) {
		if ((cc = buf[i] & 0xff) == ' ' || cc == '\t') {
			buf[i] = 0;
			while ((cc = buf[++i] & 0xff) == ' ' || cc == '\t') ;
			switch (cc) {
			case 'c':  case 'C': /* Centering */
				method = bk_Centering;  break;
			case 't':  case 'T': /* Tiling */
				method = bk_Tiling;  break;
			case 'b':  case 'B': /* Brick */
				method = bk_BrickWork;  break;
			case 'f':  case 'F': /* Fit */
				method = bk_FitScreen;  break;
			case 'v':  case 'V': /* coVer */
				method = bk_CoverScreen;  break;
			}
			break;
		}
	}

	if ((j = getExtension(buf)) == 0)
		return nil; /* No Extension */
	fnam = buf;
	if (buf[0] == '~') {
		sprintf(rc, "%s%s", home, &buf[1]);
		fnam = rc;
	}
	if (access(fnam, R_OK) != 0) {
		errAlert(fnam, Err_OPEN);
		return nil;
	}
	if ((stream = [self openStreamFromFile: fnam : &buf[j]]) == NULL)
		return nil;
	if (backgCtr == nil)
		[self loadBackgBundle];
	rtn = [backgCtr setStream: stream with: method];
	NXCloseMemory(stream, NX_FREEBUFFER);
	if (rtn == nil)
		warnAlert(fnam, Err_MEMORY);
	return self;
}

- initWallpaper
{
	const char *apname = [NXApp appName];

	if (NXGetDefaultValue(apname, "NXServiceLaunch") != NULL
		|| NXGetDefaultValue(apname, "NXOpen") != NULL)
		return self;
	[self readRCWallpaper];
	return self;
}

- readWallpaperSetting: sender
{
	if ([self readRCWallpaper] == nil)
		NXBeep();
	return self;
}


- cleanBackground: sender
{
	if (backgCtr == nil || [backgCtr cleanBackground: sender] == nil)
		NXBeep();
	return self;
}

- backgMenuEnabled:(BOOL)flag
{
	[menuToFront setEnabled: flag];
	[menuClear setEnabled: flag];
	return self;
}

- makeFront: sender
{
	if (backgCtr == nil || [backgCtr makeFront: sender] == nil)
		NXBeep();
	return self;
}

- backWinFront: (BOOL)flag
{
	const char *title;

	if (flag)
		title = NXLocalizedString("Send to Back", NULL, Background);
	else
		title = NXLocalizedString("Bring to Front", NULL, Background);
	[menuToFront setTitle: title];
	return self;
}

- makeBackground: sender
{
	NXRect	*ir;
	id	tw, tv, rtn;
	commonInfo *cinf;
	int method = [sender selectedTag];
	
	if ((tw = [self keyWindow]) == nil) {
		NXBeep();
		return self;
	}
	tv = [tw toyView];
	if (backgCtr == nil)
		[self loadBackgBundle];
	cinf = [tv commonInfo];
	ir = [tv selectedRect];
	rtn = nil;
	if (ir->size.width > 0.0 && ir->size.height > 0.0) {
		id tmp = [[NXImage alloc] initFromImage:[tv image] rect:ir];
		[tmp setScalable:YES];
		rtn = [backgCtr setImage: tmp hasAlpha: cinf->alpha with: method];
		[tmp free];
	}else if ([tw isKindOf: [ToyWinEPS class]]) {
		NXStream *stream = [tw openEPSStream];
		rtn = [backgCtr setStream: stream with: method];
		NXCloseMemory(stream, NX_FREEBUFFER);
	}else
		rtn = [backgCtr setImage: [tv image] hasAlpha: cinf->alpha with: method];
	if (rtn == nil)
		warnAlert([tw filename], Err_MEMORY);
	return self;
}

@end
