// TDIAL.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include "tdial.hrh"
#include <tdial.rsg>

#include <s32stor.h>
#include <s32file.h>
#include <basched.h>
#include <eikdial.h>
#include <eikdialg.h>
#include <eikappui.h>
#include <eikapp.h>
#include <eikenv.h>
#include <eikdoc.h>
#include <eikcmds.hrh>
#include <eikwsel.h>
#include <eikedwin.h>
#include <coemain.h>
#include <eikon.rsg>
#include <eikdial.hrh>

// as in the SHELL

class CDialSettingsDialog : public CEikDialog
	{
public:
	CDialSettingsDialog();
private:
	virtual void PostLayoutDynInitL();
	virtual void HandleControlStateChangeL(TInt aControlId);
	virtual TBool OkToExitL(TInt aKeyCode);
private:
	void SetTimeControlState(TInt aControlId, TTimeIntervalMicroSeconds32 aTime);
	TTimeIntervalMicroSeconds32 TimeControlState(TInt aControlId) const;
private:
	TInt iStringLength;
	};

const TUid KProteaV01DialSettingsUID={268435814};

CDialSettingsDialog::CDialSettingsDialog()
	{
	__DECLARE_NAME(_S("CDialSettingsDialog"));
	}

void CDialSettingsDialog::PostLayoutDynInitL()
	{
	TEikDialSettings dialSettings;
	TBool readAreaCodeFromResourceFile = ETrue;
	CDictionaryStore* iniFile=CDictionaryFileStore::SystemLC(iEikonEnv->FsSession());
	if (iniFile->IsPresentL(KProteaV01DialSettingsUID))
		{
		RDictionaryReadStream stream;
		stream.OpenLC(*iniFile,KProteaV01DialSettingsUID);
		TRAPD(err, stream >> dialSettings);
		if (err == KErrNone)
			readAreaCodeFromResourceFile=EFalse;
		CleanupStack::PopAndDestroy(); // stream
		}
	CleanupStack::PopAndDestroy(); //iniFile

	if (readAreaCodeFromResourceFile)
		{
		TBuf<1> includeAreaCode;
		iEikonEnv->ReadResource(includeAreaCode, R_DIAL_INCLUDE_AREA_CODE);
		if (includeAreaCode[0]=='0')
			dialSettings.SetIncludeAreaCode(EFalse);
		else if (includeAreaCode[0]=='1')
			dialSettings.SetIncludeAreaCode(ETrue);
		}

	// set prefix for dialling out
	TDialString string;
	dialSettings.GetDialOutString(string);
	SetEdwinTextL(EDialSettingsDlgDialOutCode, &string);

	if (dialSettings.IncludeAreaCode())
		SetCheckBoxState(EDialSettingsDlgIncludeAreaCode, CEikButtonBase::ESet);

	// get default country
	TWorldId id;
	RWorldServer wld;
	wld.Connect();
	wld.DefaultCountry(id);
	wld.Close();
	SWorldSelectorState state;
	state.iSearch=EWithinWorld; //??
	state.iCountry=id.Country();
	state.iCity=id.City();
	((CEikWorldSelector*)Control(EDialSettingsDlgDefaultCountry))->Controller()->SetStateL(state);

	// set the tone, delay and pause times
	TTimeIntervalMicroSeconds32 toneTime;
	TTimeIntervalMicroSeconds32 delayTime;
	TTimeIntervalMicroSeconds32 pauseTime;
	dialSettings.GetSoundTimes(toneTime, delayTime, pauseTime);
	
	SetTimeControlState(EDialSettingsDlgToneTime,  toneTime);
	SetTimeControlState(EDialSettingsDlgDelayTime, delayTime);
	SetTimeControlState(EDialSettingsDlgPauseTime, pauseTime);
	}

void CDialSettingsDialog::HandleControlStateChangeL(TInt aControlId)
	{
	if (aControlId != EDialSettingsDlgDialOutCode)
		return;

	TDialString number;
	GetEdwinText(number, EDialSettingsDlgDialOutCode);
	TInt numberLength=number.Length();
	if (numberLength==0 || numberLength<iStringLength)
		return;

	TInt cursorPos=((CEikEdwin *)Control(EDialSettingsDlgDialOutCode))->CursorPos();
	if (cursorPos==0)
		return;

	TChar lastChar=number[cursorPos-1];
	if (lastChar.IsDigit()  || lastChar==',')
		iStringLength = numberLength;
	else
		{
		number.Delete(cursorPos-1, 1);
		SetEdwinTextL(EDialSettingsDlgDialOutCode, &number);
		((CEikEdwin *)Control(EDialSettingsDlgDialOutCode))->SetCursorPosL(cursorPos-1, EFalse);
		iEikonEnv->InfoMsg(R_DIAL_UNDIALLABLE_CHAR); // defined for eikdial too !!
		}
	}

TBool CDialSettingsDialog::OkToExitL(TInt /*aKeyCode*/)
	{
	// get the default city
	SWorldSelectorState state;
	((CEikWorldSelector*)Control(EDialSettingsDlgDefaultCountry))->Controller()->GetState(state);
	TWorldId id;
	RWorldServer wld;
	wld.Connect();
	wld.FindCountry(id, state.iCountry); // ??
	wld.SetDefaultCountry(id);
	wld.Close();

	TEikDialSettings dialSettings;

	// get the dial out prefix
	TDialString string;
	GetEdwinText(string, EDialSettingsDlgDialOutCode);
	dialSettings.SetDialOutString(string);

	dialSettings.SetIncludeAreaCode(!!CheckBoxState(EDialSettingsDlgIncludeAreaCode));

	// get the time, delay and pause times
	TTimeIntervalMicroSeconds32 toneTime;
	TTimeIntervalMicroSeconds32 delayTime;
	TTimeIntervalMicroSeconds32 pauseTime;
	toneTime  = TimeControlState(EDialSettingsDlgToneTime);
	delayTime = TimeControlState(EDialSettingsDlgDelayTime);
	pauseTime = TimeControlState(EDialSettingsDlgPauseTime);
	dialSettings.SetSoundTimes(toneTime, delayTime, pauseTime);

	// write the results out to system.ini
	CDictionaryStore* iniFile=CDictionaryFileStore::SystemLC(iEikonEnv->FsSession());
	RDictionaryWriteStream stream;
	stream.AssignLC(*iniFile,KProteaV01DialSettingsUID);
	stream << dialSettings;
	stream.CommitL();
	CleanupStack::PopAndDestroy(); // stream
	iniFile->CommitL();
	CleanupStack::PopAndDestroy(); // iniFile

	return ETrue;
	}

void CDialSettingsDialog::SetTimeControlState(TInt aControlId,
											  TTimeIntervalMicroSeconds32 aTime)
// note times are saved as microseconds but displayed as 1/32 of a second
	{
	TInt value=(aTime.Int()*32)/1000000;
	value=value>0   ? value : 1;
	value=value<101 ? value : 100;
	SetNumberEditorValue(aControlId,  value);
	}

TTimeIntervalMicroSeconds32 CDialSettingsDialog::TimeControlState(TInt aControlId) const
// note times are saved as microseconds but displayed as 1/32 of a second
	{
	return NumberEditorValue(aControlId)*1000000/32;
	}

//
// class CSetHomeCountryDialog
// for test purposes only
//

class CSetHomeDialog : public CEikDialog
	{
	virtual void PostLayoutDynInitL();
	virtual TBool OkToExitL(TInt aKeycode);
	};

void CSetHomeDialog::PostLayoutDynInitL()
	{
	TWorldId id;
	RWorldServer wld;
	wld.Connect();
	wld.Home(id);
	wld.Close();

	SWorldSelectorState state;
	state.iCountry = id.Country();
	state.iCity    = id.City();
	state.iSearch  = id.Select();

	((CEikWorldSelector*)Control(EHomeCity))->Controller()->SetStateL(state);
	((CEikWorldSelector*)Control(EHomeCountry))->Controller()->SetStateL(state);
	}

TBool CSetHomeDialog::OkToExitL(TInt /*aKeycode*/)
	{
	SWorldSelectorState state;
	((CEikWorldSelector*)Control(EHomeCountry))->Controller()->GetState(state);
	((CEikWorldSelector*)Control(EHomeCity))->Controller()->GetState(state);

	TWorldId id;
	RWorldServer wld;
	wld.Connect();
	wld.Find(id, state.iCity, state.iCountry);
	wld.SetHome(id);
	wld.Close();

	return ETrue;
	}


//
// class CUserDialDialog
//

class CUserDialDialog : public CEikDialog
	{
public:
	CUserDialDialog(TDes& aString);
private:
	virtual TBool OkToExitL(TInt aButtonId);
private:
	TDes& iString;
	};

CUserDialDialog::CUserDialDialog(TDes& aString) : iString(aString)
	{
	}

TBool CUserDialDialog::OkToExitL(TInt /*aButtonId*/)
	{
	GetEdwinText(iString, EUserDialEdwin);
	return ETrue;
	}

// CAgendaDialDialog - should be same as in the Agenda
class CAgendaDialDialog : public CEikDialDialog
	{
public:
	IMPORT_C CAgendaDialDialog(const TDesC& aPhoneNumber);
private:
	virtual void PreLayoutDynInitL();
	virtual void PostLayoutDynInitL();
private:
	TInt iStartPos;
	const TDesC& iPhoneNumber;
	};

EXPORT_C CAgendaDialDialog::CAgendaDialDialog(const TDesC& aPhoneNumber) : iPhoneNumber(aPhoneNumber)
	{
	__DECLARE_NAME(_S("CAgendaDialDialog"));
	}

void CAgendaDialDialog::PreLayoutDynInitL()
	{
	ConstructL();

	for (TInt line=1; line<EMaxNoDialogLines; line++)
		DeleteLine(line+EDialDlgEdwin1);

	TBuf<EDialDialogMaxLabelLength> label; // from Agenda !
	IsDiallable(iPhoneNumber, iStartPos);
	if (iStartPos)
		{ // if its 0 leave phone number prompt
		TInt labelLength=Min(iStartPos, EDialDialogMaxLabelLength);
		label.Copy(iPhoneNumber.Ptr(), labelLength);
		SetControlCaptionL(EDialDlgEdwin1, label);
		}
	}

void CAgendaDialDialog::PostLayoutDynInitL()
	{
	SetPhoneNumberL(EDialDlgEdwin1, iPhoneNumber, iStartPos);
	}


// class CDataDialDialog - same as given to data
class CDataDialDialog : public CEikDialDialog
	{
public:
	IMPORT_C CDataDialDialog(MDesCArray* aPhoneNumber, MDesCArray* aLabel);
private:
	virtual void PreLayoutDynInitL();
	virtual void PostLayoutDynInitL();
private:
	MDesCArray* iPhoneNumber;
	MDesCArray* iLabel;
	};

EXPORT_C CDataDialDialog::CDataDialDialog(MDesCArray* aPhoneNumber, MDesCArray* aLabel)
: iPhoneNumber(aPhoneNumber), iLabel(aLabel)
	{
	__DECLARE_NAME(_S("CDataDialDialog"));
	}

void CDataDialDialog::PreLayoutDynInitL()
	{
	ConstructL();

	TInt noLabels=iLabel->MdcaCount();
	for (TInt line=0; line<EMaxNoDialogLines; line++)
		{
		if (line<noLabels)
			{
			TBuf<EDialDialogMaxLabelLength> label;
			if (iLabel->MdcaPoint(line).Length())
				{
				TInt length=Min(iLabel->MdcaPoint(line).Length(), EDialDialogMaxLabelLength);
				label.Copy(iLabel->MdcaPoint(line).Ptr(), length);
				SetControlCaptionL(line+EDialDlgEdwin1, label);
				}
			}
		else
			DeleteLine(line+EDialDlgEdwin1);
		}
	}

void CDataDialDialog::PostLayoutDynInitL()
	{
	TInt noLines=iPhoneNumber->MdcaCount();
//	__ASSERT_ALWAYS(noLines>0 && noLines<EMaxNoLines, Panic(EDialPanicBadArray));

	for (TInt line=0; line<noLines; line++)
		SetPhoneNumberL(line+EDialDlgEdwin1, iPhoneNumber->MdcaPoint(line));
	}

//
// class CEmptyControl
//

class CEmptyControl : public CCoeControl
    {
public:
    void ConstructL(const TRect& aRect);
    };

void CEmptyControl::ConstructL(const TRect& aRect)
    {
    CreateWindowL();
	SetRectL(aRect);
	SetBlank();
	ActivateL();
    }


//
// class CSimpleAppUi
//

class CSimpleAppUi : public CEikAppUi
    {
public:
    void ConstructL();
	~CSimpleAppUi();
private: // framework
    virtual void HandleCommandL(TInt aCommand);
private: // menu commands
    void CmdAgendaDialDialogL();
    void CmdDataDialDialogL();
    void CmdMoreDataDialDialogL();
    void CmdFreeDialDialogL();
	void CmdUserDialDialogL();
	void CmdDialSettingsDialogL();
	void CmdSetHomeCountryDialogL();
private:
    CEmptyControl* iEmptyControl;
    };

CSimpleAppUi::~CSimpleAppUi()
	{
	delete iEmptyControl;
	}

void CSimpleAppUi::ConstructL()
    {
    BaseConstructL();
    iEmptyControl=new(ELeave) CEmptyControl;
    iEmptyControl->ConstructL(ClientRect());
    }

void CSimpleAppUi::HandleCommandL(TInt aCommand)
    {
    switch (aCommand)
        {
    case EEikCmdExit:
        CBaActiveScheduler::Exit();
        break;
    case EDialCmdAgendaDial:
        CmdAgendaDialDialogL();
        break;
    case EDialCmdDataDial:
        CmdDataDialDialogL();
        break;
    case EDialCmdMore:
        CmdMoreDataDialDialogL();
        break;
    case EDialCmdFreeDial:
        CmdFreeDialDialogL();
        break;
	case EDialCmdSettings:
		CmdDialSettingsDialogL();
		break;
	case EDialCmdHome:
		CmdSetHomeCountryDialogL();
		break;
	case EDialCmdUser:
		CmdUserDialDialogL();
		break;
        }
    }

void CSimpleAppUi::CmdUserDialDialogL()
	{
	TBuf<200> string;
	CUserDialDialog* dlg1 = new(ELeave) CUserDialDialog(string);
	if (!dlg1->ExecuteLD(R_USER_DIAL_DIALOG))
		{
		iEikonEnv->InfoMsg(R_DIAL_NOTHING_TO_DIAL);
		return;
		}
	TInt temp;
	if (!CEikDialDialog::IsDiallable(string, temp))
		{
		iEikonEnv->InfoMsg(R_DIAL_NOTHING_TO_DIAL);
		return;
		}

	CAgendaDialDialog* dlg2=new(ELeave) CAgendaDialDialog(string);
	dlg2->ExecuteLD(R_DIAL_DIALOG);
	}

void CSimpleAppUi::CmdAgendaDialDialogL()
	{
	TBuf<100> agendaString(_L("Phone Kevin at Symbian (0171-208-1982)"));

	CAgendaDialDialog* dlg=new(ELeave) CAgendaDialDialog(agendaString);
	dlg->ExecuteLD(R_DIAL_DIALOG);
	}

void CSimpleAppUi::CmdDataDialDialogL()
	{
	CDesCArray* labels=new(ELeave) CDesCArrayFlat(2);
	CDesCArray* numbers=new(ELeave) CDesCArrayFlat(2);
	CleanupStack::PushL(labels);
	CleanupStack::PushL(numbers);
	labels->AppendL(_L("0171"));
	numbers->AppendL(_L("0171-208-1800"));
	labels->AppendL(_L("+44(171)"));
	numbers->AppendL(_L("+44(171)2081800"));
	labels->AppendL(_L("208"));
	numbers->AppendL(_L("208-1800"));
	labels->AppendL(_L("+44(0)171 Title thats too long for label"));
	numbers->AppendL(_L("+44(0)171-208-1234"));
	labels->AppendL(_L("0171 Phone number that's too long"));
	numbers->AppendL(_L("017100001000020000300004000050000600007000080000900009"));

	CDataDialDialog* dlg=new(ELeave) CDataDialDialog(numbers, labels);
	dlg->ExecuteLD(R_DIAL_DIALOG);

	CleanupStack::PopAndDestroy(2); //arrays
	}

void CSimpleAppUi::CmdMoreDataDialDialogL()
	{
	CDesCArray* labels=new(ELeave) CDesCArrayFlat(2);
	CDesCArray* numbers=new(ELeave) CDesCArrayFlat(2);
	CleanupStack::PushL(labels);
	CleanupStack::PushL(numbers);
	labels->AppendL(_L("0044 (0)"));
	numbers->AppendL(_L("0044 (0) 171-208-1800"));
	labels->AppendL(_L("+44 (0) "));
	numbers->AppendL(_L("+44 (0) 171-208-1800"));
	labels->AppendL(_L("+44 (171)"));
	numbers->AppendL(_L("+44 (171) 208-1800"));
	labels->AppendL(_L("+44 )0("));
	numbers->AppendL(_L("+44 )0( 171 208-1800"));
	labels->AppendL(_L("+44.171"));
	numbers->AppendL(_L("+44.171.208.1800"));

	CDataDialDialog* dlg=new(ELeave) CDataDialDialog(numbers, labels);
	dlg->ExecuteLD(R_DIAL_DIALOG);

	CleanupStack::PopAndDestroy(2); //arays
	}

void CSimpleAppUi::CmdFreeDialDialogL()
	{
	CEikFreeDialDialog* dlg=new(ELeave) CEikFreeDialDialog;
	dlg->ExecuteLD(R_FREE_DIAL_DIALOG);
	}

void CSimpleAppUi::CmdDialSettingsDialogL()
	{
	CDialSettingsDialog* dlg=new(ELeave) CDialSettingsDialog;
	dlg->ExecuteLD(R_DIAL_SETTINGS_DIALOG);
	}

void CSimpleAppUi::CmdSetHomeCountryDialogL()
	{
	CEikDialog* dlg=new(ELeave) CSetHomeDialog;
	dlg->ExecuteLD(R_SET_HOME_CITY_DIALOG);
	}

class CSimpleDocument : public CEikDocument
	{
public:
	CSimpleDocument(CEikApplication& aApp) : CEikDocument(aApp) { }
private: // from CApaDocument
	CEikAppUi* CreateAppUiL();
	};

CEikAppUi* CSimpleDocument::CreateAppUiL()
	{
    return(new(ELeave) CSimpleAppUi);
	}

//
// class CSimpleApplication
//

class CSimpleApplication : public CEikApplication
	{
private: // from CApaApplication
	CApaDocument* CreateDocumentL();
	TUid AppDllUid() const;
	};

const TUid KUidTDialApp={240};

TUid CSimpleApplication::AppDllUid() const
	{
	return(KUidTDialApp);
	}

CApaDocument* CSimpleApplication::CreateDocumentL()
	{
	return(new(ELeave) CSimpleDocument(*this));
	}

//
// EXPORTed functions
//

EXPORT_C CApaApplication* NewApplication()
	{
	return(new CSimpleApplication);
	}

GLDEF_C TInt E32Dll(TDllReason)
	{
	return(KErrNone);
	}
