// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use account_common::{FidlLocalPersonaId, LocalAccountId, LocalPersonaId};
use crate::account_handler::AccountHandler;
use crate::persona::Persona;
use failure::Error;
use fidl::encoding::OutOfLine;
use fidl::endpoints::{ClientEnd, ServerEnd};
use fidl_fuchsia_auth::{AuthChangeGranularity, AuthState, ServiceProviderAccount};
use fidl_fuchsia_auth_account::{
    AccountRequest, AccountRequestStream, AuthListenerMarker, PersonaMarker, Status,
};
use fuchsia_async as fasync;
use futures::prelude::*;
use log::{error, warn};
use std::sync::Arc;

/// Information about the Account that this AccountHandler instance is responsible for.
///
/// This state is only available once the Handler has been initialized to a particular account via
/// the AccountHandlerControl channel.
pub struct Account {
    /// A device-local identifier for this account.
    _id: LocalAccountId,

    /// The default persona for this account.
    default_persona: Arc<Persona>,

    // TODO(jsankey): Once the system and API surface can support more than a single persona, add
    // additional state here to store these personae. This will most likely be a hashmap from
    // LocalPersonaId to Persona struct, and changing default_persona from a struct to an ID.
}

impl Account {
    /// Constructs a new Account.
    pub fn new(account_id: LocalAccountId) -> Account {
        let persona_id = LocalPersonaId::new(rand::random::<u64>());
        Self {
            _id: account_id.clone(),
            default_persona: Arc::new(Persona::new(persona_id, account_id)),
        }
    }

    /// Asynchronously handles the supplied stream of `AccountRequest` messages.
    pub async fn handle_requests_from_stream(
        &self, mut stream: AccountRequestStream,
    ) -> Result<(), Error> {
        while let Some(req) = await!(stream.try_next())? {
            self.handle_request(req)?;
        }
        Ok(())
    }

    /// Dispatches an `AccountRequest` message to the appropriate handler method
    /// based on its type.
    pub fn handle_request(&self, req: AccountRequest) -> Result<(), fidl::Error> {
        match req {
            AccountRequest::GetAuthState { responder } => {
                let mut response = self.get_auth_state();
                responder.send(response.0, response.1.as_mut().map(OutOfLine))?;
            }
            AccountRequest::RegisterAuthListener {
                listener,
                initial_state,
                granularity,
                responder,
            } => {
                let response = self.register_auth_listener(listener, initial_state, granularity);
                responder.send(response)?;
            }
            AccountRequest::GetPersonaIds { responder } => {
                let mut response = self.get_persona_ids();
                responder.send(&mut response.iter_mut())?;
            }
            AccountRequest::GetDefaultPersona { persona, responder } => {
                let mut response = self.get_default_persona(persona);
                responder.send(response.0, response.1.as_mut().map(OutOfLine))?;
            }
            AccountRequest::GetPersona {
                id,
                persona,
                responder,
            } => {
                let response = self.get_persona(id.into(), persona);
                responder.send(response)?;
            }
            AccountRequest::GetRecoveryAccount { responder } => {
                let mut response = self.get_recovery_account();
                responder.send(response.0, response.1.as_mut().map(OutOfLine))?;
            }
            AccountRequest::SetRecoveryAccount { account, responder } => {
                let response = self.set_recovery_account(account);
                responder.send(response)?;
            }
        }
        Ok(())
    }

    fn get_auth_state(&self) -> (Status, Option<AuthState>) {
        // TODO(jsankey): Return real authentication state once authenticators exist to create it.
        (Status::Ok, Some(AccountHandler::DEFAULT_AUTH_STATE))
    }

    fn register_auth_listener(
        &self, _listener: ClientEnd<AuthListenerMarker>, _initial_state: bool,
        _granularity: AuthChangeGranularity,
    ) -> Status {
        // TODO(jsankey): Implement this method.
        warn!("RegisterAuthListener not yet implemented");
        Status::InternalError
    }

    fn get_persona_ids(&self) -> Vec<FidlLocalPersonaId> {
        vec![self.default_persona.id().clone().into()]
    }

    fn get_default_persona(
        &self, persona_server_end: ServerEnd<PersonaMarker>,
    ) -> (Status, Option<FidlLocalPersonaId>) {
        let persona_clone = Arc::clone(&self.default_persona);
        match persona_server_end.into_stream() {
            Ok(stream) => {
                fasync::spawn(
                    async move {
                        await!(persona_clone.handle_requests_from_stream(stream))
                            .unwrap_or_else(|e| error!("Error handling Persona channel {:?}", e))
                    },
                );
                (Status::Ok, Some(self.default_persona.id().clone().into()))
            }
            Err(e) => {
                error!("Error opening Persona channel {:?}", e);
                (Status::IoError, None)
            }
        }
    }

    fn get_persona(
        &self, id: LocalPersonaId, persona_server_end: ServerEnd<PersonaMarker>,
    ) -> Status {
        if &id == self.default_persona.id() {
            self.get_default_persona(persona_server_end).0
        } else {
            warn!("Requested persona does not exist {:?}", id);
            Status::NotFound
        }
    }

    fn get_recovery_account(&self) -> (Status, Option<ServiceProviderAccount>) {
        // TODO(jsankey): Implement this method.
        warn!("GetRecoveryAccount not yet implemented");
        (Status::InternalError, None)
    }

    fn set_recovery_account(&self, _account: ServiceProviderAccount) -> Status {
        // TODO(jsankey): Implement this method.
        warn!("SetRecoveryAccount not yet implemented");
        Status::InternalError
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use fidl::endpoints::RequestStream;
    use fidl_fuchsia_auth_account::{AccountProxy, AccountRequestStream, PersonaProxy};
    use fuchsia_async as fasync;
    use fuchsia_zircon as zx;

    const TEST_ACCOUNT_ID: u64 = 111111;

    fn create_test_object() -> Account {
        Account::new(LocalAccountId::new(TEST_ACCOUNT_ID))
    }

    fn request_stream_test<TestFn, Fut>(test_object: Account, test_fn: TestFn)
    where
        TestFn: FnOnce(AccountProxy) -> Fut,
        Fut: Future<Output = Result<(), Error>>,
    {
        let mut executor = fasync::Executor::new().expect("Failed to create executor");
        let (server_chan, client_chan) = zx::Channel::create().expect("Failed to create channel");
        let proxy = AccountProxy::new(fasync::Channel::from_channel(client_chan).unwrap());
        let request_stream =
            AccountRequestStream::from_channel(fasync::Channel::from_channel(server_chan).unwrap());

        fasync::spawn(
            async move {
                await!(test_object.handle_requests_from_stream(request_stream))
                    .unwrap_or_else(|err| panic!("Fatal error handling test request: {:?}", err))
            },
        );

        executor
            .run_singlethreaded(test_fn(proxy))
            .expect("Executor run failed.")
    }

    #[test]
    fn test_random_persona_id() {
        // Generating two accounts with the same accountID should lead to two different persona IDs
        let account_1 = Account::new(LocalAccountId::new(TEST_ACCOUNT_ID));
        let account_2 = Account::new(LocalAccountId::new(TEST_ACCOUNT_ID));
        assert_ne!(
            account_1.default_persona.id(),
            account_2.default_persona.id()
        );
    }

    #[test]
    fn test_get_auth_state() {
        request_stream_test(create_test_object(), async move |proxy| {
            assert_eq!(
                await!(proxy.get_auth_state())?,
                (
                    Status::Ok,
                    Some(Box::new(AccountHandler::DEFAULT_AUTH_STATE))
                )
            );
            Ok(())
        });
    }

    #[test]
    fn test_register_auth_listener() {
        request_stream_test(create_test_object(), async move |proxy| {
            let (_server_chan, client_chan) = zx::Channel::create().unwrap();
            let listener = ClientEnd::new(client_chan);
            assert_eq!(
                await!(proxy.register_auth_listener(
                    listener,
                    true, /* include initial state */
                    &mut AuthChangeGranularity {
                        summary_changes: true
                    }
                ))?,
                Status::InternalError
            );
            Ok(())
        });
    }

    #[test]
    fn test_get_persona_ids() {
        // Note: Persona ID is random. Record the persona_id before starting the test.
        let account = create_test_object();
        let persona_id = &account.default_persona.id().clone();

        request_stream_test(account, async move |proxy| {
            let response = await!(proxy.get_persona_ids())?;
            assert_eq!(response.len(), 1);
            assert_eq!(&LocalPersonaId::new(response[0].id), persona_id);
            Ok(())
        });
    }

    #[test]
    fn test_get_default_persona() {
        // Note: Persona ID is random. Record the persona_id before starting the test.
        let account = create_test_object();
        let persona_id = &account.default_persona.id().clone();

        request_stream_test(account, async move |account_proxy| {
            let (server_chan, client_chan) = zx::Channel::create().unwrap();
            let response = await!(account_proxy.get_default_persona(ServerEnd::new(server_chan)))?;
            assert_eq!(response.0, Status::Ok);
            assert_eq!(&LocalPersonaId::from(*response.1.unwrap()), persona_id);

            // The persona channel should now be usable.
            let persona_proxy =
                PersonaProxy::new(fasync::Channel::from_channel(client_chan).unwrap());
            assert_eq!(
                await!(persona_proxy.get_auth_state())?,
                (
                    Status::Ok,
                    Some(Box::new(AccountHandler::DEFAULT_AUTH_STATE))
                )
            );

            Ok(())
        });
    }

    #[test]
    fn test_get_persona_by_correct_id() {
        let account = create_test_object();
        let persona_id = account.default_persona.id().clone();

        request_stream_test(account, async move |account_proxy| {
            let (server_chan, client_chan) = zx::Channel::create().unwrap();
            assert_eq!(
                await!(account_proxy.get_persona(
                    &mut FidlLocalPersonaId::from(persona_id),
                    ServerEnd::new(server_chan)
                ))?,
                Status::Ok
            );

            // The persona channel should now be usable.
            let persona_proxy =
                PersonaProxy::new(fasync::Channel::from_channel(client_chan).unwrap());
            assert_eq!(
                await!(persona_proxy.get_auth_state())?,
                (
                    Status::Ok,
                    Some(Box::new(AccountHandler::DEFAULT_AUTH_STATE))
                )
            );

            Ok(())
        });
    }

    #[test]
    fn test_get_persona_by_incorrect_id() {
        let account = create_test_object();
        // Note: This fixed value has a 1 - 2^64 probability of not matching the randomly chosen
        // one.
        let wrong_id = LocalPersonaId::new(13);

        request_stream_test(account, async move |proxy| {
            let (server_chan, _) = zx::Channel::create().unwrap();
            assert_eq!(
                await!(proxy.get_persona(&mut wrong_id.into(), ServerEnd::new(server_chan)))?,
                Status::NotFound
            );

            Ok(())
        });
    }

    #[test]
    fn test_set_recovery_account() {
        let mut service_provider_account = ServiceProviderAccount {
            identity_provider_domain: "google.com".to_string(),
            user_profile_id: "test_obfuscated_gaia_id".to_string(),
        };

        request_stream_test(create_test_object(), async move |proxy| {
            assert_eq!(
                await!(proxy.set_recovery_account(&mut service_provider_account))?,
                Status::InternalError
            );
            Ok(())
        });
    }

    #[test]
    fn test_get_recovery_account() {
        let expectation = (Status::InternalError, None);
        request_stream_test(create_test_object(), async move |proxy| {
            assert_eq!(await!(proxy.get_recovery_account())?, expectation);
            Ok(())
        });
    }
}
