/// <summary>
        /// <para>Adds a sales agent from an api key and account id.</para>
        /// </summary>
        /// <param name="apiId">A valid eve api id (keyID).</param>
        /// <param name="apiKey">A valid eve api key (vCode).</param>
        /// <param name="accountId">The id of the account for which a sales agent should be added.</param>
        /// <returns>Returns a validation result object.</returns>
        internal IValidationResult AddSalesAgent(int apiId, string apiKey, int accountId)
        {
            IValidationResult validationResult = new ValidationResult();

            // Check the remaining sales agent licences for the account.
            if (this.GetRemainingSalesAgentLicences(accountId) <= 0)
            {
                validationResult.AddError("SalesAgent.Licences", "You have exceeded the number of sales agent licences available with your account subscription plan.");
            }
            else
            {
                // Fetch details about the Api Key from Eve Data.
                IEveDataApiKey apiKeyInfo = this.eveDataSource.GetApiKeyInfo(apiId, apiKey);

                if (apiKeyInfo != null)
                {
                    // Validate the api key.
                    validationResult = this.doctrineShipsValidation.ApiKey(apiKeyInfo);
                    if (validationResult.IsValid == true)
                    {
                        // Use the api key info to populate a new sales agent object.
                        SalesAgent newSalesAgent = new SalesAgent();

                        // If this is a character or account key use the character details, if a corp key use the corp details.
                        if (apiKeyInfo.Type == EveDataApiKeyType.Character || apiKeyInfo.Type == EveDataApiKeyType.Account)
                        {
                            // If this is an account key, the first character in the list will be used.
                            newSalesAgent.SalesAgentId = apiKeyInfo.Characters.FirstOrDefault().CharacterId;
                            newSalesAgent.Name = apiKeyInfo.Characters.FirstOrDefault().CharacterName;
                            newSalesAgent.ImageUrl = eveDataSource.GetCharacterPortraitUrl(newSalesAgent.SalesAgentId);
                            newSalesAgent.IsCorp = false;
                        }
                        else if (apiKeyInfo.Type == EveDataApiKeyType.Corporation)
                        {
                            newSalesAgent.SalesAgentId = apiKeyInfo.Characters.FirstOrDefault().CorporationId;
                            newSalesAgent.Name = apiKeyInfo.Characters.FirstOrDefault().CorporationName;
                            newSalesAgent.ImageUrl = eveDataSource.GetCorporationLogoUrl(newSalesAgent.SalesAgentId);
                            newSalesAgent.IsCorp = true;
                        }

                        // Populate the remaining properties.
                        newSalesAgent.AccountId = accountId;
                        newSalesAgent.ApiId = apiId;
                        newSalesAgent.ApiKey = apiKey;
                        newSalesAgent.IsActive = true;
                        newSalesAgent.LastForce = DateTime.UtcNow;
                        newSalesAgent.LastContractRefresh = DateTime.UtcNow;

                        // Validate the new sales agent.
                        validationResult = this.doctrineShipsValidation.SalesAgent(newSalesAgent);
                        if (validationResult.IsValid == true)
                        {
                            // Add the new sales agent and log the event.
                            this.doctrineShipsRepository.CreateSalesAgent(newSalesAgent);
                            this.doctrineShipsRepository.Save();
                            logger.LogMessage("Sales Agent '" + newSalesAgent.Name + "' Successfully Added For Account Id: " + newSalesAgent.AccountId, 2, "Message", MethodBase.GetCurrentMethod().Name);
                        }
                    }
                }
                else
                {
                    validationResult.AddError("ApiKey.Valid", "An invalid api key was entered or the eve api is currently unavailable.");
                }
            }

            return validationResult;
        }
        /// <summary>
        /// Updates a ship fit for a particular account.
        /// </summary>
        /// <param name="shipFit">A partially populated ship fit object to be updated.</param>
        /// <returns>Returns a validation result object.</returns>
        internal IValidationResult UpdateShipFit(ShipFit shipFit)
        {
            IValidationResult validationResult = new ValidationResult();

            var existingShipFit = this.doctrineShipsRepository.GetShipFit(shipFit.ShipFitId);

            if (existingShipFit != null)
            {
                if (existingShipFit.AccountId != shipFit.AccountId)
                {
                    validationResult.AddError("ShipFit.Permission", "The ship fit being modified does not belong to the requesting account.");
                }
                else
                {
                    // Map the updates to the existing ship fit.
                    existingShipFit.Name = shipFit.Name;
                    existingShipFit.Role = shipFit.Role;
                    existingShipFit.Notes = shipFit.Notes;

                    // Validate the ship fit updates.
                    validationResult = this.doctrineShipsValidation.ShipFit(existingShipFit);
                    if (validationResult.IsValid == true)
                    {
                        // Update the existing record, save and log.
                        this.doctrineShipsRepository.UpdateShipFit(existingShipFit);
                        this.doctrineShipsRepository.Save();
                        logger.LogMessage("Ship Fit '" + existingShipFit.Name + "' Successfully Updated For Account Id: " + existingShipFit.AccountId, 2, "Message", MethodBase.GetCurrentMethod().Name);
                    }
                }
            }

            return validationResult;
        }
        /// <summary>
        /// Updates a notification recipient for a particular account.
        /// </summary>
        /// <param name="notificationRecipient">A partially populated notification recipient object to be updated.</param>
        /// <returns>Returns a validation result object.</returns>
        internal IValidationResult UpdateNotificationRecipient(NotificationRecipient notificationRecipient)
        {
            IValidationResult validationResult = new ValidationResult();

            var existingNotificationRecipient = this.doctrineShipsRepository.GetNotificationRecipient(notificationRecipient.NotificationRecipientId);

            if (existingNotificationRecipient != null)
            {
                if (existingNotificationRecipient.AccountId != notificationRecipient.AccountId)
                {
                    validationResult.AddError("NotificationRecipient.Permission", "The notification recipient being modified does not belong to the requesting account.");
                }
                else
                {
                    // Map the updates to the existing notification recipient.
                    existingNotificationRecipient.AlertIntervalHours = notificationRecipient.AlertIntervalHours;
                    existingNotificationRecipient.ReceivesAlerts = notificationRecipient.ReceivesAlerts;
                    existingNotificationRecipient.ReceivesDailySummary = notificationRecipient.ReceivesDailySummary;

                    // Validate the notification recipient updates.
                    validationResult = this.doctrineShipsValidation.NotificationRecipient(existingNotificationRecipient);
                    if (validationResult.IsValid == true)
                    {
                        // Update the existing record, save and log.
                        this.doctrineShipsRepository.UpdateNotificationRecipient(existingNotificationRecipient);
                        this.doctrineShipsRepository.Save();
                        logger.LogMessage("Notification Recipient '" + existingNotificationRecipient.Description + "' Successfully Updated For Account Id: " + existingNotificationRecipient.AccountId, 2, "Message", MethodBase.GetCurrentMethod().Name);
                    }
                }
            }

            return validationResult;
        }
        /// <summary>
        /// Deletes an account and all access codes, ship fits, sales agents and their contracts.
        /// </summary>
        /// <param name="accountId">The account Id being deleted.</param>
        /// <returns>Returns a validation result object.</returns>
        public IValidationResult DeleteAccount(int accountId)
        {
            IValidationResult validationResult = new ValidationResult();

            // Delete all account ship fits, components and related contracts.
            var accountShipFits = ShipFitManager.GetShipFitList(accountId);
            foreach (var shipFit in accountShipFits)
            {
                if (ShipFitManager.DeleteShipFit(accountId, shipFit.ShipFitId) == false)
                {
                    validationResult.AddError(shipFit.ShipFitId.ToString(), "Error while deleting ship fit: " + shipFit.ShipFitId.ToString());
                }
            }

            // Delete all account sales agents.
            var accountSalesAgents = SalesAgentManager.GetSalesAgents(accountId);
            foreach (var salesAgent in accountSalesAgents)
            {
                if (SalesAgentManager.DeleteSalesAgent(accountId, salesAgent.SalesAgentId) == false)
                {
                    validationResult.AddError(salesAgent.SalesAgentId.ToString(), "Error while deleting sales agent: " + salesAgent.SalesAgentId.ToString());
                }
            }
                
            // Delete all account access codes.
            var accountAccessCodes = AccountManager.GetAccessCodes(accountId);
            foreach (var accessCode in accountAccessCodes)
            {
                if (AccountManager.DeleteAccessCode(accountId, accessCode.AccessCodeId) == false)
                {
                    validationResult.AddError(accessCode.AccessCodeId.ToString(), "Error while deleting access code: " + accessCode.AccessCodeId.ToString());
                }
            }

            // Delete all notification recipients.
            var accountNotificationRecipients = AccountManager.GetNotificationRecipients(accountId);
            foreach (var notificationRecipient in accountNotificationRecipients)
            {
                if (AccountManager.DeleteNotificationRecipient(accountId, notificationRecipient.NotificationRecipientId) == false)
                {
                    validationResult.AddError(notificationRecipient.NotificationRecipientId.ToString(), "Error while deleting notification recipient: " + notificationRecipient.NotificationRecipientId.ToString());
                }
            }

            // Delete the account.
            if (AccountManager.DeleteAccount(accountId) == false)
            {
                validationResult.AddError(accountId.ToString(), "Error while deleting account: " + accountId.ToString());
            }

            try
            {
                // Delete the account setting profile.
                var settingProfile = this.GetAccountSettingProfile(accountId);
                if (AccountManager.DeleteSettingProfile(accountId, settingProfile.SettingProfileId) == false)
                {
                    validationResult.AddError(settingProfile.SettingProfileId.ToString(), "Error while deleting setting profile: " + settingProfile.SettingProfileId.ToString());
                }
            }
            catch (System.ArgumentException e)
            {
                // The setting profile did not exist. Add an error to the validation result object.
                validationResult.AddError("SettingProfile.Exists" + accountId.ToString(), "The setting profile did not exist for account id: " + accountId.ToString());
            }
            catch (Exception)
            {
                throw;
            }

            return validationResult;
        }
        /// <summary>
        /// Updates the subscription plan for an account.
        /// </summary>
        /// <param name="accountId">The account Id being changed.</param>
        /// <param name="subscriptionPlanId">The id of the new subscription plan.</param>
        /// <returns>Returns a validation result object.</returns>
        internal IValidationResult UpdateAccountSubscriptionPlan(int accountId, int subscriptionPlanId)
        {
            IValidationResult validationResult = new ValidationResult();

            Account account = this.doctrineShipsRepository.GetAccount(accountId);

            if (account != null)
            {
                // Change the subscription plan of the account and validate.
                account.SubscriptionPlanId = subscriptionPlanId;

                validationResult = this.doctrineShipsValidation.Account(account);
                if (validationResult.IsValid == true)
                {
                    // Update the account and log the event.
                    this.doctrineShipsRepository.UpdateAccount(account);
                    this.doctrineShipsRepository.Save();
                    logger.LogMessage("Subscription Plan Successfully Changed For Account: '" + account.Description + "'.", 2, "Message", MethodBase.GetCurrentMethod().Name);
                }
            }
            else
            {
                validationResult.AddError("AccountId.Null", "The account does not exist in the database.");
            }

            return validationResult;
        }