/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * The contents of this file are subject to the Netscape Public License
 * Version 1.0 (the "NPL"); you may not use this file except in
 * compliance with the NPL.  You may obtain a copy of the NPL at
 * http://www.mozilla.org/NPL/
 *
 * Software distributed under the NPL is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
 * for the specific language governing rights and limitations under the
 * NPL.
 *
 * The Initial Developer of this code under the NPL is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
 * Reserved.
 */

#include "CPrefsDialog.h"

#include "CMenuTable.h"
#ifdef MOZ_MAIL_NEWS
#include "MailNewsAddressBook.h"
#endif

#include "MailNewsMediators.h"
#include "CAssortedMediators.h"

#ifdef MOZ_MAIL_NEWS
#include "CReceiptsMediator.h"
#endif // MOZ_MAIL_NEWS
#include "CSpecialFoldersMediator.h"
#include "CMailNewsMainMediator.h"

#include "MPreference.h"

#include "UStdDialogs.h"
#include "CValidEditField.h"
#include "macutil.h"

#include "dirprefs.h"
#include "addrbook.h"
#include "abdefn.h"
#include "prefapi.h"

#include "UStdDialogs.h"

#include "resgui.h"	// for cmd_AboutPlugins

#include "uapp.h"



CPrefsDialog *CPrefsDialog::sThis = nil;

//-----------------------------------
CPrefsDialog::CPrefsDialog()
//-----------------------------------
:	LCommander(GetTopCommander())
,	mWindow(nil)
,	mTable(nil)
{
	MPreferenceBase::SetWriteOnDestroy(false);
}

//-----------------------------------
CPrefsDialog::~CPrefsDialog()
//-----------------------------------
{
	// all panes are freed by PowerPlant since they are subcommanders of this dialog...
}


//-----------------------------------
void CPrefsDialog::EditPrefs(
	Expand_T expand,
	PrefPaneID::ID pane,
	Selection_T selection)
//-----------------------------------
{
	if (sThis)
	{
		// very suspicious
	}
	else
	{
		sThis = new CPrefsDialog();
	}
	XP_Bool	attachVCard;
	const	char *	const	usePABCPrefName = "mail.attach_vcard";	// fix me
	int	prefResult = PREF_GetBoolPref(usePABCPrefName, &attachVCard);
#ifdef MOZ_MAIL_NEWS
	sThis->mNeedToCheckForVCard = (	prefResult == PREF_NOERROR &&
									false == attachVCard &&
									!PREF_PrefIsLocked(usePABCPrefName));
#endif // MOZ_MAIL_NEWS
	const	char *	const	useInternetConfigPrefName = "browser.mac.use_internet_config";	// fix me
	XP_Bool	useIC;
	prefResult = PREF_GetBoolPref(useInternetConfigPrefName, &useIC);
	CPrefsMediator::UseIC(useIC);
	sThis->DoPrefsWindow(expand, pane, selection);
}

#ifdef MOZ_MAIL_NEWS
//-----------------------------------
void CPrefsDialog::CheckForVCard()
//-----------------------------------
{
	const	char *	const	usePABCPrefName = "mail.attach_vcard";	// fix me
	XP_Bool	attachVCard;
	PREF_GetBoolPref(usePABCPrefName, &attachVCard);
	if (attachVCard)
	{
		char	*email = (char *)FE_UsersMailAddress();
		if (email)
			email = XP_STRDUP(email);
		char	*nameString = (char *)FE_UsersFullName();
		if (nameString)
		{
			nameString = XP_STRDUP(nameString);
		}
		XP_List	*directories = CAddressBookManager::GetDirServerList();
		DIR_Server	*pab;
		DIR_GetPersonalAddressBook(directories, &pab);
		XP_ASSERT(pab);
		if (pab)
		{
			ABID		entryID;
			PersonEntry	person;
			person.Initialize();
			person.pGivenName = nameString;
			person.pEmailAddress = email;
			ABook	*aBook = FE_GetAddressBook(nil);
			AB_GetEntryIDForPerson(pab, aBook, &entryID, &person);
			AB_BreakApartFirstName(aBook, &person);
			if (MSG_MESSAGEIDNONE == entryID)
			{
				LCommander	*super = LCommander::GetTopCommander();

				StStdDialogHandler theHandler(12007, super);
				theHandler.SetInitialDialogPosition(nil);
				LWindow* theDialog = theHandler.GetDialog();

				MessageT theMessage = msg_Cancel;
				if (UStdDialogs::TryToInteract())
				{
					theDialog->Show();
					theMessage = theHandler.WaitUserResponse();
				}
				if (msg_Cancel != theMessage)
				{
					if (true != FE_ShowPropertySheetFor(nil, entryID, &person))
					{
						theMessage = msg_Cancel;
					}
				}
				if (msg_Cancel == theMessage)
				{
					PREF_SetBoolPref(usePABCPrefName, false);
				}
			}
			person.CleanUp();
		}
	}
}
#endif // MOZ_MAIL_NEWS

//-----------------------------------
void CPrefsDialog::DoPrefsWindow(
	Expand_T expand,
	PrefPaneID::ID pane,
	Selection_T selection)
//-----------------------------------
{
	if (!mWindow)
	{
		mCurrentMediator = nil;
		mWindow = LWindow::CreateWindow(PrefPaneID::eWindowPPob, this);
		if (mWindow)
		{
			UReanimator::LinkListenerToControls(	this,
													mWindow,
													PrefPaneID::eWindowPPob);
			mTable = (CMenuTable *)mWindow->FindPaneByID(eTableView);
			XP_ASSERT(mTable);
			mPanel = (LView *)mWindow->FindPaneByID(ePanelView);
			XP_ASSERT(mPanel);
			CPrefsMediator::SetStatics(mPanel, mWindow, selection);

			mTable->AddListener(this);
			
			PrefPaneID::ID panel = pane;
			if ( ! pane )
				panel = (PrefPaneID::ID)expand;
		
			// Find the row 
			TableIndexT wideOpenRow = mTable->FindMessage( panel );
			
			// Now have to collapse the all the rows except appearence
			// This is icky
			mTable->CollapseRow( mTable->FindMessage ( PrefPaneID::eBrowser_Main  ) );
			#ifdef MOZ_MAIL_NEWS
			mTable->CollapseRow( mTable->FindMessage ( PrefPaneID::eMailNews_Main ) );
			#endif // MOZ_MAIL_NEWS
			#ifdef EDITOR
			mTable->CollapseRow( mTable->FindMessage ( PrefPaneID::eEditor_Main ) );
			#endif // EDITOR
			#ifdef MOZ_OFFLINE
			mTable->CollapseRow( mTable->FindMessage ( PrefPaneID::eOffline_Main ) );
			#endif // MOZ_OFFLINE
			mTable->CollapseRow( mTable->FindMessage ( PrefPaneID::eAdvanced_Main ) );	
		
			
			mTable->UnselectAllCells();
			STableCell initialCell( 1, 1 );
			
			if (PrefPaneID::eNoPaneSpecified != panel)
			{	
				// Reveal the selection
				mTable->RevealRow( wideOpenRow );
				if ( pane == 0 )
					mTable->DeepExpandRow( wideOpenRow );
				
				initialCell.row =
					mTable->GetExposedIndex( wideOpenRow );
				
			}
			
			mTable->SelectCell(initialCell);
			// really should scroll selected category into view
			LCommander::SetUpdateCommandStatus(true);
			
			CStr255 windowTitle;
			GetUserWindowTitle(6, windowTitle);
			mWindow->SetDescriptor(windowTitle);
			
			mWindow->Show();
		}
	}
}

//-----------------------------------
void CPrefsDialog::LoadICDependent()
//-----------------------------------
{
	sThis->GetMediator(PrefPaneID::eBrowser_Main)->LoadPanes();			// home page
		// we don't actually load the eMailNews_Identity manager because it will always
		// alreay be loaded
//	sThis->GetMediator(eMailNews_Identity)->LoadPanes();		// User Name
																// User Email
																// Organization
#ifdef MOZ_MAIL_NEWS
	sThis->GetMediator(PrefPaneID::eMailNews_MailServer)->LoadPanes();	// POP ID
																// POP host
																// SMTP host
	sThis->GetMediator(PrefPaneID::eMailNews_NewsServer)->LoadPanes();	// News host
#endif // MOZ_MAIL_NEWS
} // CPrefsDialog::LoadICDependent



//-----------------------------------
CPrefsMediator* CPrefsDialog::FindMediator(ResIDT paneID)
//-----------------------------------
{
	LArrayIterator iterator(mPanels, LArrayIterator::from_Start);
	CPrefsMediator* prefManager;
	while (iterator.Next(&prefManager))
	{
		if ( prefManager->GetMainPaneID() == paneID )
			return prefManager;	
	}	
	return nil;	
} // CPrefsDialog::FindMediator

//-----------------------------------
CPrefsMediator* CPrefsDialog::GetMediator(ResIDT inPaneID)
//-----------------------------------
{
	if (inPaneID == PrefPaneID::eNoPaneSpecified)
		return nil;
	CPrefsMediator* result = FindMediator(inPaneID);
	if (result)
		return result;

	// The pane ID of the pane is equal to the class ID of the corresponding mediator
	// Currently, we don't read in any resource data for a mediator, there are no resources,
	// so the LStream* parameter is nil.  We just use the factory feature of the registrar.
	// Later, we may decide to use UReanimator::ObjectsFromStream();
	result = (CPrefsMediator*)URegistrar::CreateObject(inPaneID, nil);
	if (!result)
	{
		// There's no special mediator with this class ID.  So give them a default mediator.
		result = new CPrefsMediator(inPaneID);
	}
	mPanels.InsertItemsAt(1,LArray::index_Last, &result, sizeof( result ) );
	AddListener(result);
	return result;
} // CPrefsDialog::GetMediator

//-----------------------------------
void CPrefsDialog::FindCommandStatus(
	CommandT	inCommand,
	Boolean		&outEnabled,
	Boolean&	/* outUsesMark */,
	Char16&		/* outMark */,
	Str255		/* outName */)
//-----------------------------------
{
	// Don't enable any commands except cmd_About, and cmd_AboutPlugins
	// which will keep the Apple menu enabled. This function purposely
	// does not call the inherited FindCommandStatus, thereby suppressing
	// commands that are handled by SuperCommanders. Only those
	// commands enabled by SubCommanders will be active.
	//
	// This is usually what you want for a moveable modal dialog.
	// Commands such as "New", "Open" and "Quit" that are handled
	// by the Applcation are disabled, but items within the dialog
	// can enable commands. For example, an EditField would enable
	// items in the "Edit" menu.
		
	outEnabled = false;
	if ((cmd_About == inCommand) || (cmd_AboutPlugins == inCommand))
	{
		outEnabled = true;
	}
}

//-----------------------------------
Boolean CPrefsDialog::AllowTargetSwitch(LCommander *inNewTarget)
//-----------------------------------
{
	CValidEditField	*target = dynamic_cast<CValidEditField*>(LCommander::GetTarget());
	if (target)
		return target->AllowTargetSwitch(inNewTarget);
	return LCommander::AllowTargetSwitch(inNewTarget);
}

//-----------------------------------
void CPrefsDialog::ListenToMessage(
							MessageT		inMessage,
							void			*/*ioParam*/)
//-----------------------------------
{
	switch (inMessage)
	{
		case CMenuTable::msg_SelectionChanged:
			MessageT	theViewID = mTable->GetSelectedMessage();
			CPrefsMediator	*mediator = GetMediator(theViewID);
			if (mediator)
			{
				if (mCurrentMediator)
					mCurrentMediator->StepAside();
				mediator->StepForward(mWindow);
				mCurrentMediator = mediator;
			}
			break;
		case CPrefsMediator::eCommitPrefs:
#ifdef MOZ_MAIL_NEWS
			CMailNewsMailServerMediator	*serverMediator = nil;
			// check if the Mail server pane manager exist
			// if it does get it
			if ( FindMediator( PrefPaneID::eMailNews_MailServer ) )
			{
				serverMediator
					= dynamic_cast<CMailNewsMailServerMediator*>(
						GetMediator(PrefPaneID::eMailNews_MailServer));
			}
#endif // MOZ_MAIL_NEWS
			if (CPrefsMediator::CanSwitch())
			{
#ifdef MOZ_MAIL_NEWS // Is MOZ_MAIL_NEWS the correct symbol to use?
				Boolean forceQuit = false;
				Boolean allowCommit = true;
				// Add code here to check if we should quit or not...
				if (allowCommit)
				{
#endif // MOZ_MAIL_NEWS
					BroadcastMessage(CPrefsMediator::eCommitPrefs, nil);
					Finished();
#ifdef MOZ_MAIL_NEWS
					if (mNeedToCheckForVCard)
					{
						CheckForVCard();
					}
					if (forceQuit)
					{
						CFrontApp* app = dynamic_cast<CFrontApp*>(LCommander::GetTopCommander());
						if (app)
							app->SendAEQuit();
					}	
				}
				else
				{
					// we don't want to quit
					mCurrentMediator->StepAside();
					serverMediator->StepForward(mWindow);
				/* Don't reset the button back
					serverMediator->ResetServerButtons();
				*/
					TableIndexT wideOpenRow = mTable->FindMessage(PrefPaneID::eMailNews_MailServer);
					mTable->RevealRow( wideOpenRow  );
					
					STableCell mailServerCell;
					mTable->IndexToCell( wideOpenRow, mailServerCell );
					mTable->SelectCell( mailServerCell );
				}
#endif // MOZ_MAIL_NEWS
			}
			break;
		case CPrefsMediator::eCancelPrefs:
			BroadcastMessage(CPrefsMediator::eCancelPrefs, nil);
			Finished();
			break;
		case eHelpButtonID:
			if (mCurrentMediator)
				mCurrentMediator->ActivateHelp();
			break;
		default:
			break;
	}
} // CPrefsDialog::ListenToMessage

//-----------------------------------
void CPrefsDialog::Finished()
//-----------------------------------
{
	mWindow->DoClose();
	mWindow = nil;
	sThis = nil;
	if (MPreferenceBase::GetWriteOnDestroy()) // the controls wrote themselves
		PREF_SavePrefFile();
	delete this;
}

//-----------------------------------
void CPrefsDialog::RegisterViewClasses()
//-----------------------------------
{
	// Mediator classes:
	RegisterClass_(CAppearanceMainMediator);
	RegisterClass_(CAppearanceFontsMediator);
	RegisterClass_(CAppearanceColorsMediator);
	RegisterClass_(CBrowserMainMediator);
	RegisterClass_(CBrowserLanguagesMediator);
	RegisterClass_(CBrowserApplicationsMediator);
	RegisterClass_(CAdvancedCacheMediator);
	RegisterClass_(CAdvancedProxiesMediator);
#ifdef MOZ_MAIL_NEWS
	RegisterClass_(CMailNewsIdentityMediator);
	RegisterClass_(CMailNewsMainMediator);
	RegisterClass_(CMailNewsMessagesMediator);
	RegisterClass_(CMailNewsOutgoingMediator);
	RegisterClass_(CMailNewsMailServerMediator);
	RegisterClass_(CMailNewsNewsServerMediator);
	RegisterClass_(CReceiptsMediator);
	RegisterClass_(CMailNewsDirectoryMediator);
#endif // MOZ_MAIL_NEWS
#ifdef EDITOR
	RegisterClass_(CEditorMainMediator);
#endif
#ifdef MOZ_OFFLINE
	RegisterClass_(COfflineNewsMediator);
#endif
#ifdef MOZ_LDAP
	// And a dialog class:
	RegisterClass_(CLDAPServerPropDialog);
#endif
} // CPrefsDialog::RegisterViewClasses
