#import "ToyWin.h"
#import <appkit/Application.h>
#import <appkit/publicWraps.h>
#import <appkit/SavePanel.h>
#import <appkit/NXImage.h>
#import <appkit/NXBitmapImageRep.h>
#import <appkit/NXEPSImageRep.h>
#import <appkit/Control.h>
#import  <objc/NXBundle.h>	/* LocalizedString */
#import <appkit/Panel.h>
#import <appkit/tiff.h>
#import <streams/streams.h> // NXStream
#import <stdio.h>
#import <stdlib.h>
#import <string.h>
#import <libc.h>
#import <time.h>
#import "ToyView.h"
#import "TVController.h"
#import "ColorMap.h"
#import "common.h"
#import "getpixel.h"

#define  BINFixedLength   120

@implementation ToyWin (Saving)

static void wrFixedLength(NXStream *stream,
	const unsigned char *plane, int length,
	const unsigned char *alp, int oneisblack)
{
	int	n, cc;
	int	idx = 0;
	static const char hex[] = "0123456789abcdef";

	for (n = 0; n < length; n++) {
		cc = oneisblack ? ~plane[n] : plane[n];
		if (alp)
			cc |= ~alp[n];
		cc &= 0xff;
		NXPutc(stream, hex[cc >> 4]); 
		NXPutc(stream, hex[cc & 0x0f]);
		if (++idx >= BINFixedLength) {
			idx = 0;
			NXPutc(stream, '\n');
		}
	}
	if (idx) NXPutc(stream, '\n');
}

/* Local Method */
/* ...... Don't call this method when (cinf->alpha && !cinf->isplanar) */
- writeBitmapAsEPS:(unsigned char **)map
		info:(commonInfo *)cinf to:(NXStream *)stream
{
	const char *p, *q;
	int	cc, i, bwid, buflen;
	time_t	tt;

	NXPrintf(stream, "%s\n%s",
		"%!PS-Adobe-2.0 EPSF-2.0", "%%Title: ");
	for (p = q = [self filename]; *p; p++)
		if (*p == '/') q = p + 1;
	for (p = q; *p; p++) {
		if ((cc = *p & 0xff) <= ' ' || cc == '(' || cc == ')')
			break;
		NXPutc(stream, cc);
	}
	(void)time(&tt);
	NXPrintf(stream, "\n%s\n%s%s",
		"%%Creator: ToyViewer", "%%CreationDate: ", ctime(&tt));
	NXPrintf(stream, "%s\n%s 0 0 %d %d\n%s\n\n",
		"%%DocumentFonts: (atend)", "%%BoundingBox:",
		cinf->width, cinf->height,
		"%%EndComments");

	bwid = byte_length(cinf->bits, cinf->width);
	buflen = bwid;
	if (cinf->numcolors == 1)
		NXPrintf(stream, "/pictstr %d string def\n", bwid);
	else if (!cinf->isplanar) { /* mesh */
		buflen = byte_length(cinf->bits, cinf->width * 3);
		NXPrintf(stream, "/pictstr %d string def\n", buflen);
	}else {
		NXPrintf(stream, "/pictstr %d string def\n", bwid * 3);
		for (i = 0; i < 3; i++)
		    NXPrintf(stream,
			"/subStr%d pictstr %d %d getinterval def\n",
			i, bwid * i, bwid);
	}
	NXPrintf(stream, "gsave\n0 0 translate\n%d %d %d [1 0 0 -1 0 %d]\n",
		cinf->width, cinf->height, cinf->bits, cinf->height);
	if (cinf->numcolors == 1 || !cinf->isplanar)
		NXPrintf(stream, "{currentfile pictstr readhexstring pop}\n");
	else {
		for (i = 0; i < 3; i++)
		    NXPrintf(stream, 
			"{currentfile subStr%d readhexstring pop}\n", i);
	}
	if (cinf->numcolors == 1) {
		NXPrintf(stream, "image\n");
		wrFixedLength(stream, map[0], bwid * cinf->height,
			(cinf->alpha ? map[1]: NULL),
			(cinf->cspace == NX_OneIsBlackColorSpace) );
	}else if (cinf->isplanar) {
		int	y, idx;
		unsigned char *alp;
		NXPrintf(stream, "true 3 colorimage\n");
		for (y = 0; y < cinf->height; y++) {
			idx = y * bwid;
			alp = cinf->alpha ? &map[3][idx]: NULL;
			for (i = 0; i < 3; i++)
			    wrFixedLength(stream, &map[i][idx], bwid, alp, NO);
		}
	}else {
		/* IGNORE (cinf->alpha && !cinf->isplanar) */
		NXPrintf(stream, "false 3 colorimage\n");
		wrFixedLength(stream, map[0], buflen * cinf->height, NULL, NO);
	}
	NXPrintf(stream, "grestore\n%s\n", "%%Trailer");
	return self;
}

- (NXStream *)openEPSStream
{
	NXStream *stream;
	id	tv;
	commonInfo *cinf;

	if ((stream = NXOpenMemory(NULL, 0, NX_READWRITE)) == NULL)
		return NULL;
	tv = [self toyView];
	cinf = [tv commonInfo];
	if (cinf->type == Type_eps || cinf->cspace == NX_CMYKColorSpace
		|| (cinf->alpha && !cinf->isplanar)) {
		/* This code may be no use */
		NXRect	rect;
		[tv getFrame:&rect];
		[tv copyPSCodeInside:&rect to:stream];
	}else {
		unsigned char *map[MAXPLANE];
		[self getBitmap: map info: &cinf];
		[self writeBitmapAsEPS: map info: cinf to: stream];
		[self freeTempBitmap];
	}
	NXFlush(stream);
	NXSeek(stream, 0L, NX_FROMSTART);
	return stream;
}

- (int)getBitmap:(unsigned char **)map info:(commonInfo **)infp
{
	NXImageRep *rep;
	rep = [[[self toyView] image] bestRepresentation];
	[(NXBitmapImageRep *)rep getDataPlanes: map];
	return 0;
}

- freeTempBitmap
{
	return self;
}

- print: sender
{
	[[self toyView] printPSCode:sender];
	return self;
}

@end
