#import <appkit/appkit.h>
#import "Rectangle.h"
#import "Square.h"

// a program that demonstrates dynamic binding

// function prototypes
void createObjects(void), run(void);
void calculateAreas(void), freeAll(void);
void main(void);
BOOL readInput(void);

// global variable
id theList;

void createObjects(void)
{
	// create list to hold shapes
	theList = [[List alloc] init];
}

void run(void)
{
	// stay in loop until Q is pressed
	BOOL done = NO;
	while (!done)
		{
		done = readInput();
		}
}

BOOL readInput(void)
{
	char inputString[10];
	unsigned int choice;
	float width, height;
	id object;

	// print the menu
	printf("\nShapeArea calculates the ");
	printf("areas of various shapes\n");
	printf("==============\n");
	printf("Select a shape\n");
	printf("Type Q to quit\n\n");
	printf("1 rectangle\n");
	printf("2 square\n");
	printf("===============\n");
	// get input
	scanf("%s", inputString);
	if (strcmp(inputString, "Q") != 0)
		{
		choice = atoi(inputString);
		switch (choice)
			{
			case 1:
				// get width and height
				printf("Enter the height\n");
				scanf("%f", &height);
				printf("Enter the width\n");
				scanf("%f", &width);
				// create rectangle and init it
				object = [[Rectangle alloc]
					initHeight:height
					width:width];
				// add rectangle to list
				[theList addObject:object];
				printf("The area of this shape is %.2f\n",
					[object calcArea]);
				break;
			case 2:
				// get height for square
				printf("Enter the height\n");
				// since a square's height
				// is equal to its width,
				// get only one value
				scanf("%f", &height);
				// create square and init it
				object = [[Square alloc]
					initHeight:height
					width:height];
				// add square to list
				[theList addObject:object];
				printf("The area of this shape is %.2f\n",
					[object calcArea]);
				break;
			default:
				// invalid choice
				printf("No such shape!\n");
				printf("Please try again!\n\n");
				break;
			}
		// return NO to stay in while loop
		// of run() function
		return NO;
		}
	else
		// return YES to abort while loop
		return YES;
}

void calculateAreas(void)
{
	int i;
	// traverse the list and request each
	// instance to perform its calcArea method
	// this demonstrates dynamic binding
	// since it impossible to determine
	// the class of each instance until runtime
	for (i=0; i < [theList count]; i++)
		{
		printf("\nThis shape is an instance of %s\n",
			[[theList objectAt:i] name]);
		printf("The area of this shape is %.2f\n",
			[[theList objectAt:i] calcArea]);
		}
}

void freeAll(void)
{
	// free the objects in the list
	// freeObjects sends a free message
	// to each object in the list
	[theList freeObjects];
	// free the list itself
	[theList free];
}

void main(void)
{
	createObjects();
	run();
	calculateAreas();
	freeAll();
	exit(0);
}
