// 28 april 2015
#import "uipriv_darwin.h"

@interface containerView : NSView {
	uiContainer *c;
	uiContainer *parent;
	int hidden;
}
@property uiContainer *containerParent;
@property int containerHidden;
- (void)setContainer:(uiContainer *)cc;
- (void)containerUpdate;
@end

@implementation containerView

- (void)setContainer:(uiContainer *)cc
{
	self->c = cc;
}

// These are based on measurements from Interface Builder.
// These seem to be based on Auto Layout constants, but I don't see an API that exposes these...
// This one is 8 for most pairs of controls that I've tried; the only difference is between two pushbuttons, where it's 12...
#define macXPadding 8
// Likewise, this one appears to be 12 for pairs of push buttons...
#define macYPadding 8

- (void)containerUpdate
{
	uiSizing d;
	intmax_t x, y, width, height;

	x = [self bounds].origin.x;
	y = [self bounds].origin.y;
	width = [self bounds].size.width;
	height = [self bounds].size.height;
	d.xPadding = macXPadding;
	d.yPadding = macYPadding;
	uiContainerResizeChildren(self->c, x, y, width, height, &d);
}

- (void)setFrameSize:(NSSize)s
{
	[super setFrameSize:s];
	[self containerUpdate];
}

@end

// subclasses override this and call back here when all children are destroyed
static void containerDestroy(uiControl *cc)
{
	containerView *c = (containerView *) (cc->Internal);

	if (c.containerParent != NULL)
		complain("attempt to destroy uiContainer %p while it has a parent", cc);
	[c release];		// release our initial reference, which destroys the view
}

static uintptr_t containerHandle(uiControl *cc)
{
	containerView *c = (containerView *) (cc->Internal);

	return (uintptr_t) c;
}

static void containerSetParent(uiControl *cc, uiContainer *parent)
{
	containerView *c = (containerView *) (cc->Internal);
	uiContainer *oldparent;
	NSView *newcontainer;

	oldparent = c.containerParent;
	c.containerParent = parent;
	if (oldparent != NULL)
		[c removeFromSuperview];
	if (c.containerParent != NULL) {
		newcontainer = (NSView *) uiControlHandle(uiControl(c.containerParent));
		[newcontainer addSubview:c];
	}
	if (oldparent != NULL)
		uiContainerUpdate(oldparent);
	if (c.containerParent != NULL)
		uiContainerUpdate(c.containerParent);
}

static void containerResize(uiControl *cc, intmax_t x, intmax_t y, intmax_t width, intmax_t height, uiSizing *d)
{
	containerView *c = (containerView *) (cc->Internal);
	NSRect r;

	r.origin.x = x;
	// mac os x coordinate system has (0,0) in the lower-left
	r.origin.y = ([[c superview] bounds].size.height - height) - y;
	r.size.width = width;
	r.size.height = height;
	// we can safely use setFrame here since we have no alignment rect to worry about
	[c setFrame:r];
}

static int containerVisible(uiControl *cc)
{
	containerView *c = (containerView *) (cc->Internal);

	return !c.containerHidden;
}

static void containerShow(uiControl *cc)
{
	containerView *c = (containerView *) (cc->Internal);

	[c setHidden:NO];
	// hidden controls don't count in boxes and grids
	// be sure to change the hidden variable FIRST, otherwise immediate resizes like on OS X don't work right
	c.containerHidden = 0;
	if (c.containerParent != NULL)
		uiContainerUpdate(c.containerParent);
}

static void containerHide(uiControl *cc)
{
	containerView *c = (containerView *) (cc->Internal);

	[c setHidden:YES];
	c.containerHidden = 1;
	if (c.containerParent != NULL)
		uiContainerUpdate(c.containerParent);
}

static void containerEnable(uiControl *cc)
{
	containerView *c = (containerView *) (cc->Internal);
	uiControlSysFuncParams p;

	p.Func = uiDarwinSysFuncContainerEnable;
	uiControlSysFunc(cc, &p);
}

static void containerDisable(uiControl *cc)
{
	containerView *c = (containerView *) (cc->Internal);
	uiControlSysFuncParams p;

	p.Func = uiDarwinSysFuncContainerDisable;
	uiControlSysFunc(cc, &p);
}

static void containerUpdate(uiContainer *cc)
{
	containerView *c = (containerView *) (uiControl(cc)->Internal);

	[c containerUpdate];
}

void uiMakeContainer(uiContainer *cc)
{
	containerView *c;

	c = [[containerView alloc] initWithFrame:NSZeroRect];
	[c setContainer:cc];
	// keep a reference to our container so it stays alive when reparented
	[c retain];

	uiControl(cc)->Internal = c;
	uiControl(cc)->Destroy = containerDestroy;
	uiControl(cc)->Handle = containerHandle;
	uiControl(cc)->SetParent = containerSetParent;
	// PreferredSize() is provided by subclasses
	uiControl(cc)->Resize = containerResize;
	uiControl(cc)->Visible = containerVisible;
	uiControl(cc)->Show = containerShow;
	uiControl(cc)->Hide = containerHide;
	uiControl(cc)->Enable = containerEnable;
	uiControl(cc)->Disable = containerDisable;
	// SysFunc() is provided by subclasses

	// ResizeChildren() is provided by subclasses
	uiContainer(cc)->Update = containerUpdate;
}