// license:BSD-3-Clause
// copyright-holders:Vas Crabb
//============================================================
//
//  deviceinfoviewer.m - MacOS X Cocoa debug window handling
//
//============================================================

#include "emu.h"
#import "deviceinfoviewer.h"

#include "util/xmlfile.h"


@interface MAMEDeviceInfoView : NSView
{
	CGFloat minWidth;
}

- (id)initWithFrame:(NSRect)frame;

- (void)setMinWidth:(CGFloat)aWidth;

@end


@implementation MAMEDeviceInfoView

- (id)initWithFrame:(NSRect)frame {
	if (!(self = [super initWithFrame:frame]))
		return nil;
	minWidth = 0;
	return self;
}

- (void)setMinWidth:(CGFloat)aWidth {
	minWidth = aWidth;
}

- (BOOL)isFlipped {
	return YES;
}

- (void)resizeWithOldSuperviewSize:(NSSize)oldBoundsSize {
	NSSize const newBoundsSize = [[self superview] bounds].size;
	[self setFrameSize:NSMakeSize(std::max(newBoundsSize.width, minWidth), [self frame].size.height)];
}

@end


@implementation MAMEDeviceInfoViewer

- (NSTextField *)makeLabel:(NSString *)text {
	NSTextField *const result = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 14)];
	[result setAutoresizingMask:(NSViewMaxYMargin | NSViewMaxXMargin)];
	[[result cell] setControlSize:NSSmallControlSize];
	[result setEditable:NO];
	[result setSelectable:NO];
	[result setBezeled:NO];
	[result setBordered:NO];
	[result setDrawsBackground:NO];
	[result setAlignment:NSRightTextAlignment];
	[result setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
	[result setStringValue:text];
	[result sizeToFit];
	return result;
}


- (NSTextField *)makeField:(NSString *)text {
	NSTextField *const result = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 14)];
	[result setAutoresizingMask:(NSViewWidthSizable | NSViewMaxYMargin)];
	[[result cell] setControlSize:NSSmallControlSize];
	[result setEditable:NO];
	[result setSelectable:YES];
	[result setBezeled:NO];
	[result setBordered:NO];
	[result setDrawsBackground:NO];
	[result setAlignment:NSLeftTextAlignment];
	[result setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
	[result setStringValue:text];
	[result sizeToFit];
	return result;
}


- (NSBox *)makeBox:(NSString *)t toFit:(NSView *)v {
	NSBox *const result = [[NSBox alloc] initWithFrame:NSMakeRect(0, 0, [v frame].size.width - 34, 32)];
	[result setAutoresizingMask:(NSViewWidthSizable | NSViewMaxYMargin)];
	[result setTitle:t];
	[result setBoxType:NSBoxPrimary];
	[result setBorderType:NSLineBorder];
	[result setContentViewMargins:NSMakeSize(0, 0)];
	[result setAutoresizesSubviews:YES];
	return result;
}


- (void)addLabel:(NSString *)l withWidth:(CGFloat)w andField:(NSString *)f toView:(NSView *)v {
	NSTextField *const label = [self makeLabel:l];
	NSTextField *const field = [self makeField:f];
	CGFloat const height = std::max([label frame].size.height, [field frame].size.height);
	NSSize space = [v bounds].size;
	space.width = std::max(space.width, [field frame].size.width + w + 52);
	space.height += height + 8;
	[label setFrame:NSMakeRect(25, space.height - height - 20, w, height)];
	[field setFrame:NSMakeRect(w + 27, space.height - height - 20, space.width - w - 52, height)];
	[v setFrameSize:space];
	[v addSubview:label];
	[v addSubview:field];
	[label release];
	[field release];
}


- (void)addField:(NSString *)f toBox:(NSBox *)b {
	NSTextField *const field = [self makeField:f];
	[field setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)];
	NSSize space = [b frame].size;
	space.width = std::max(space.width, [field frame].size.width + 32);
	space.height += [field frame].size.height + 8;
	[field setFrame:NSMakeRect(15, 14, space.width - 32, [field frame].size.height)];
	[b setFrameSize:space];
	[[b contentView] addSubview:field];
	[field release];
}


- (void)addBox:(NSBox *)b toView:(NSView *)v {
	NSSize space = [v frame].size;
	space.width = std::max(space.width, [b frame].size.width + 34);
	space.height += [b frame].size.height + 4;
	[b setFrameOrigin:NSMakePoint(17, space.height - [b frame].size.height - 16)];
	[v setFrameSize:space];
	[v addSubview:b];
}


- (id)initWithDevice:(device_t &)d machine:(running_machine &)m console:(MAMEDebugConsole *)c {
	MAMEDeviceInfoView  *contentView;
	NSScrollView        *contentScroll;

	if (!(self = [super initWithMachine:m
								  title:[NSString stringWithFormat:@"Device %s", d.tag()]
								console:c]))
	{
		return nil;
	}
	device = &d;

	// Create a view to hold everything
	contentView = [[MAMEDeviceInfoView alloc] initWithFrame:NSMakeRect(0, 0, 320, 32)];
	[contentView setAutoresizesSubviews:YES];

	// add the stuff that's always present
	[self addLabel:@"Tag:"
		 withWidth:100
		  andField:[NSString stringWithUTF8String:device->tag()]
			toView:contentView];
	[self addLabel:@"Name:"
		 withWidth:100
		  andField:[NSString stringWithUTF8String:device->name()]
			toView:contentView];
	[self addLabel:@"Shortname:"
		 withWidth:100
		  andField:[NSString stringWithUTF8String:device->shortname()]
			toView:contentView];

	// add interfaces if present
	device_interface *interface = device->interfaces().first();
	if (interface != nullptr)
	{
		NSBox *const interfacesBox = [self makeBox:@"Interfaces" toFit:contentView];
		while (interface != nullptr)
		{
			[self addField:[NSString stringWithUTF8String:interface->interface_type()]
					 toBox:interfacesBox];
			interface = interface->interface_next();
		}
		[self addBox:interfacesBox toView:contentView];
		[interfacesBox release];
	}

	// add memory maps if present
	device_memory_interface *memory;
	if (device->interface(memory))
	{
		NSBox *memoryBox = nil;
		for (int i = 0; i < memory->max_space_count(); i++)
		{
			if (memory->has_space(i))
			{
				if (memoryBox == nil)
					memoryBox = [self makeBox:@"Memory maps" toFit:contentView];
				[self addField:[NSString stringWithUTF8String:memory->space_config(i)->name()]
						 toBox:memoryBox];
			}
		}
		if (memoryBox != nil)
		{
			[self addBox:memoryBox toView:contentView];
			[memoryBox release];
		}
	}

	// lock minimum content size
	[contentView setMinWidth:[contentView frame].size.width];
	[contentView setAutoresizingMask:NSViewWidthSizable];

	// create a scroll view for holding everything
	NSSize desired = [NSScrollView frameSizeForContentSize:[contentView frame].size
									 hasHorizontalScroller:YES
									   hasVerticalScroller:YES
												borderType:NSNoBorder];
	[window setContentSize:desired];
	contentScroll = [[NSScrollView alloc] initWithFrame:[[window contentView] bounds]];
	[contentScroll setDrawsBackground:NO];
	[contentScroll setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
	[contentScroll setHasHorizontalScroller:YES];
	[contentScroll setHasVerticalScroller:YES];
	[contentScroll setAutohidesScrollers:YES];
	[contentScroll setBorderType:NSNoBorder];
	[contentScroll setDrawsBackground:NO];
	[contentScroll setDocumentView:contentView];
	[contentView release];
	[[window contentView] addSubview:contentScroll];
	[contentScroll release];

	// calculate the optimal size for everything
	[self cascadeWindowWithDesiredSize:[contentScroll frame].size forView:contentScroll];

	// don't forget the result
	return self;
}


- (void)saveConfigurationToNode:(util::xml::data_node *)node {
	[super saveConfigurationToNode:node];
	node->set_attribute_int("type", MAME_DEBUGGER_WINDOW_TYPE_DEVICE_INFO_VIEWER);
}

@end
