// BOSS.CPP
//
// Copyright (c) 1998 Symbian Ltd.  All rights reserved.
//

#include <e32keys.h>

#include <coemain.h>

#include <eikenv.h>
#include <eikdef.h>
#include <eikcmds.hrh>
#include <eiklabel.h>

#include <eikproc.h>
#include <coeutils.h>

#include <boss.rsg>
#include "boss.hrh"
#include "boss.h"

#include "bossview.h"

void CBossAppView::ConstructL(const TRect& aRect, TBossPuzzle* aModel)
    {
	iModel=aModel;
    CreateWindowL();
    Window().SetShadowDisabled(ETrue);
    iContext=this;
   	iBrushStyle=CGraphicsContext::ESolidBrush;
    iBrushColor=KRgbWhite;
    SetRectL(aRect);
	CreateLabelL();
	ConstructViewL();
    ActivateL();
    }

CBossAppView::~CBossAppView()
    {
	delete iView;
	delete iLabel;
    }
    
TInt CBossAppView::CountComponentControls() const
	{
	return 1 + (iView ? 1 : 0); // always a label, sometimes a view
	}

CCoeControl* CBossAppView::ComponentControl(TInt aIndex) const
	{
	switch (aIndex)
		{
	case 0: return iLabel;
	case 1: return iView;
	default: return 0;
		};
	}

const TInt KLabelHeight=20;

void CBossAppView::CreateLabelL()
	{
	iLabel=new (ELeave) CEikLabel;
	TRect rect=Rect();
	rect.iTl.iY=rect.iBr.iY-KLabelHeight; // make it bottom 20 pixels
	iLabel->SetContainerWindowL(*this);
	iLabel->SetRectL(rect);
	iLabel->SetAlignment(EHCenterVCenter); // center text
	iLabel->SetBufferReserveLengthL(200); // nice long buffer
	iLabel->ActivateL(); // now ready
	}

void CBossAppView::ConstructViewL()
	{
	TRect rect=Rect(); // get our rect
	rect.iBr.iY-=KLabelHeight; // make way for label
	rect.Shrink(2,2); // shrink it a bit
	iView=new (ELeave) CBossView(this, rect, iModel);
	iView->ConstructL();
	SetFullyOrdered();
	}

void CBossAppView::NotifyStatus(const TDesC& aMessage)
	{
	iLabel->SetTextL(aMessage);
	iLabel->DrawNow();
	}

TKeyResponse CBossAppView::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
    {
	if	(iView)
   		return iView->OfferKeyEventL(aKeyEvent,aType);
	else
		return EKeyWasNotConsumed;
    }

void CBossAppView::Draw(const TRect& /*aRect*/) const
	{
	CWindowGc& gc = SystemGc();
	gc.SetPenStyle(CGraphicsContext::ENullPen);
	gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
	gc.DrawRect(Rect());
	}

// handle commands

void CBossAppView::Move(TBossPuzzle::TMoveType aMoveType)
	{
	// constant declarations
	_LIT(KTextUp,"up");
	_LIT(KTextDown,"down");
	_LIT(KTextLeft,"left");
	_LIT(KTextRight,"right");
	_LIT(KTextThatWay,"that way");
	_LIT(KTextNtMove,"cannot move %S");
	_LIT(KNotifyCongrats,"congratulations!");


	if (!iModel->CanMove(aMoveType))
		{
		TBuf<10> direction=
			aMoveType==TBossPuzzle::EUp ? TPtrC(KTextUp) :
			aMoveType==TBossPuzzle::EDown ? TPtrC(KTextDown) :
			aMoveType==TBossPuzzle::ELeft ? TPtrC(KTextLeft) :
			aMoveType==TBossPuzzle::ERight ? TPtrC(KTextRight) :
				TPtrC(KTextThatWay);
		TBuf<40> message;
		message.Format(KTextNtMove, &direction);
		NotifyStatus(message);
		return;
		}
	iModel->Move(aMoveType);
	iView->DrawNow();
	if (iModel->IsFullyOrdered())
		NotifyStatus(KNotifyCongrats);
	else
		NotifyStatus(KNullDesC);
	}

void CBossAppView::SetFullyOrdered()
	{
	_LIT(KNotifyOrdered,"fully ordered"); //constant declaration
	iModel->SetFullyOrdered();
	iView->DrawNow();
	NotifyStatus(KNotifyOrdered);
	}

void CBossAppView::SetBossOrdered()
	{
	_LIT(KNotifyBossOrder,"Boss ordered"); // constant declaration
	iModel->SetBossOrdered();
	iView->DrawNow();
	NotifyStatus(KNotifyBossOrder);
	}

//
// CBossAppUi
//

void CBossAppUi::ConstructL()
    {
	_LIT(KNotifyInitialised,"initialised"); //constant declaration

    BaseConstructL();
	iModel=((CBossDocument*)iDocument)->Model();
    iAppView=new(ELeave) CBossAppView;
    iAppView->ConstructL(ClientRect(),iModel);
	iAppView->NotifyStatus(KNotifyInitialised);
	// add app view to stack; enables key event handling.
	AddToStackL(iAppView);
    }

void CBossAppUi::HandleCommandL(TInt aCommand)
	{
	switch (aCommand)
		{
	case EBossUp:
		iAppView->Move(TBossPuzzle::EUp);
		return;
	case EBossDown:
		iAppView->Move(TBossPuzzle::EDown);
		return;
	case EBossLeft:
		iAppView->Move(TBossPuzzle::ELeft);
		return;
	case EBossRight:
		iAppView->Move(TBossPuzzle::ERight);
		return;
	case EBossSetFullyOrdered:
		iAppView->SetFullyOrdered();
		return;
	case EBossSetBossOrdered:
		iAppView->SetBossOrdered();
		return;
	case EEikCmdExit:
		SaveL();
		Exit();
		return;
		}
	}

TBool CBossAppUi::ProcessCommandParametersL(TApaCommand aCommand, TFileName& aDocumentName, const TDesC& /*aTail*/)
	{
	return CEikAppUi::ProcessCommandParametersL(aCommand, aDocumentName);
	}

void CBossAppUi::HandleModelChangeL()
	{
	iAppView->DrawNow();
	}

CBossAppUi::~CBossAppUi()
	{
    delete iAppView;
	}

//
// CBossDocument
//

CEikAppUi* CBossDocument::CreateAppUiL()
	{
    return(new(ELeave) CBossAppUi);
	}

void CBossDocument::RestoreL(const CStreamStore& aStore,const CStreamDictionary& aStreamDic)
	{
	TStreamId id=aStreamDic.At(KUidBossApp);
	iModel.RestoreL(aStore, id);
	}

void CBossDocument::StoreL(CStreamStore& aStore,CStreamDictionary& aStreamDic) const
	{
	TStreamId id=iModel.StoreL(aStore);
	aStreamDic.AssignL(KUidBossApp,id);
	}

//
// CBossApplication
//

TUid CBossApplication::AppDllUid() const
	{
	return KUidBossApp;
	}

CApaDocument* CBossApplication::CreateDocumentL()
	{
	return new(ELeave) CBossDocument(*this);
	}

//
// EXPORTed functions
//

EXPORT_C CApaApplication* NewApplication()
	{
	return new CBossApplication;
	}

GLDEF_C TInt E32Dll(TDllReason)
	{
	return KErrNone;
	}
