#include "spcore/baseobj.h"
#include "spcore/basictypes.h"
#include "testcommon/testcommon.h"

#include <assert.h>
#include <iostream>
#include <stdio.h>

using namespace spcore;

static
void DoTest()
{
	if (!spcore::getSpCoreRuntime())
		ExitErr("getSpCoreRuntime() failed");

	// Create CTypeInt instance
	SmartPtr<CTypeInt> intPtr= spcore::CTypeInt::CreateInstance();
	if (!intPtr.get()) ExitErr("cannot create CTypeInt instance");

	// Assignement to the same smart pointed type but const
	SmartPtr<const CTypeInt> intConstPtr= intPtr;

	// Smart pointers to CTypeAny. const and non-const
	SmartPtr<CTypeAny> anyPtr;
	SmartPtr<const CTypeAny> anyConstPtr;

	// Upcasting
	anyPtr= intPtr;
	//anyPtr= intConstPtr;	// Compilation error
	anyConstPtr= intPtr;
	anyConstPtr= intConstPtr;
	
	//
	// Static downcasting
	//
	intPtr= sptype_static_cast<CTypeInt>(anyPtr);
//	intPtr= sptype_static_cast<const CTypeInt>(anyPtr);	// Compilation error
//	intPtr= sptype_static_cast<CTypeInt>(anyConstPtr); // Compilation error. Casting const away not allowed
	intConstPtr= sptype_static_cast<const CTypeInt>(anyPtr);
	intConstPtr= sptype_static_cast<const CTypeInt>(anyConstPtr);

	// Usage
	intPtr->setValue(12);
	if (intConstPtr->getValue()!= 12) ExitErr("static downcasting. usage error");

	//
	// Dynamic downcasting
	//
	intPtr= sptype_dynamic_cast<CTypeInt>(anyPtr);
	if (intPtr.get()== NULL) ExitErr("intPtr= sptype_dynamic_cast<CTypeInt>(anyPtr): failed");
	intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyPtr);
	if (intConstPtr.get()== NULL) ExitErr("intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyPtr): failed");
	intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyConstPtr);
	if (intConstPtr.get()== NULL) ExitErr("intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyConstPtr): failed");
	
	// These dynamic downcasts must fail
	SmartPtr<CTypeBool> boolPtr= CTypeBool::CreateInstance();
	SmartPtr<const CTypeBool> boolConstPtr= boolPtr;
	anyPtr= boolPtr;
	anyConstPtr= boolConstPtr;
	intPtr= sptype_dynamic_cast<CTypeInt>(anyPtr);
	if (intPtr.get()!= NULL) ExitErr("bool downcasting: intPtr= sptype_dynamic_cast<CTypeInt>(anyPtr): failed");
	intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyPtr);
	if (intConstPtr.get()!= NULL) ExitErr("bool downcasting: intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyPtr): failed");
	intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyConstPtr);
	if (intConstPtr.get()!= NULL) ExitErr("bool downcasting: intConstPtr= sptype_dynamic_cast<const CTypeInt>(anyConstPtr): failed");

	
}

int main (int, char**)
{
	DoTest();
	
	// Cleanup
	spcore::freeSpCoreRuntime();
	
	return 0;
}
