// This file illustrates the cross language polymorphism using directors.

package main

import (
	"fmt"

	. "swigtests/example"
)

func main() {
	// Create an instance of CEO, a class derived from the Go
	// proxy of the underlying C++ class.  The calls to getName()
	// and getPosition() are standard, the call to getTitle() uses
	// the director wrappers to call CEO.getPosition().
	e := NewCEO("Alice")
	fmt.Println(e.GetName(), " is a ", e.GetPosition())
	fmt.Println("Just call her \"", e.GetTitle(), "\"")
	fmt.Println("----------------------")

	// Create a new EmployeeList instance.  This class does not
	// have a C++ director wrapper, but can be used freely with
	// other classes that do.
	list := NewEmployeeList()

	// EmployeeList owns its items, so we must surrender ownership
	// of objects we add.
	// e.DisownMemory()
	list.AddEmployee(e)
	fmt.Println("----------------------")

	// Now we access the first four items in list (three are C++
	// objects that EmployeeList's constructor adds, the last is
	// our CEO).  The virtual methods of all these instances are
	// treated the same.  For items 0, 1, and 2, all methods
	// resolve in C++.  For item 3, our CEO, GetTitle calls
	// GetPosition which resolves in Go.  The call to GetPosition
	// is slightly different, however, because of the overridden
	// GetPosition() call, since now the object reference has been
	// "laundered" by passing through EmployeeList as an
	// Employee*.  Previously, Go resolved the call immediately in
	// CEO, but now Go thinks the object is an instance of class
	// Employee.  So the call passes through the Employee proxy
	// class and on to the C wrappers and C++ director, eventually
	// ending up back at the Go CEO implementation of
	// getPosition().  The call to GetTitle() for item 3 runs the
	// C++ Employee::getTitle() method, which in turn calls
	// GetPosition().  This virtual method call passes down
	// through the C++ director class to the Go implementation
	// in CEO.  All this routing takes place transparently.
	fmt.Println("(position, title) for items 0-3:")
	fmt.Println("  ", list.Get_item(0).GetPosition(), ", \"", list.Get_item(0).GetTitle(), "\"")
	fmt.Println("  ", list.Get_item(1).GetPosition(), ", \"", list.Get_item(1).GetTitle(), "\"")
	fmt.Println("  ", list.Get_item(2).GetPosition(), ", \"", list.Get_item(2).GetTitle(), "\"")
	fmt.Println("  ", list.Get_item(3).GetPosition(), ", \"", list.Get_item(3).GetTitle(), "\"")
	fmt.Println("----------------------")

	// Time to delete the EmployeeList, which will delete all the
	// Employee* items it contains. The last item is our CEO,
	// which gets destroyed as well and hence there is no need to
	// call DeleteCEO.
	DeleteEmployeeList(list)
	fmt.Println("----------------------")

	// All done.
	fmt.Println("Go exit")
}
