// Copyright 2017 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 anyhow::{Context as _, Error};
use fuchsia_async as fasync;
use fuchsia_component::server::ServiceFs;
use futures::{future, io, StreamExt, TryFutureExt, TryStreamExt};
use parking_lot::Mutex;
use std::collections::HashMap;
use std::fs::{self, File};
use std::io::prelude::*;
use std::sync::Arc;
use tracing::{error, info};

// Include the generated FIDL bindings for the `DeviceSetting` service.
use fidl_fuchsia_devicesettings::{
    DeviceSettingsManagerRequest, DeviceSettingsManagerRequestStream, DeviceSettingsWatcherProxy,
    Status, ValueType,
};

type Watchers = Arc<Mutex<HashMap<String, Vec<DeviceSettingsWatcherProxy>>>>;

struct DeviceSettingsManagerServer {
    setting_file_map: HashMap<String, String>,
    watchers: Watchers,
}

impl DeviceSettingsManagerServer {
    fn initialize_keys(&mut self, data_dir: &str, keys: &[&str]) {
        self.setting_file_map = keys
            .iter()
            .map(|k| (k.to_string(), format!("{}/{}", data_dir, k.to_lowercase())))
            .collect();
    }

    fn run_watchers(&mut self, key: &str, t: ValueType) {
        let mut map = self.watchers.lock();
        if let Some(m) = map.get_mut(key) {
            m.retain(|w| {
                if let Err(err) = w.on_change_settings(t) {
                    if err.is_closed() {
                        return false;
                    }
                    error!(?err, "Error call watcher");
                }
                return true;
            });
        }
    }

    fn set_key(&mut self, key: &str, buf: &[u8], t: ValueType) -> io::Result<bool> {
        match self.setting_file_map.get(key) {
            Some(file) => write_to_file(file, buf)?,
            None => return Ok(false),
        };

        self.run_watchers(&key, t);
        Ok(true)
    }
}

static DATA_DIR: &'static str = "/data/device-settings";

fn write_to_file(file: &str, buf: &[u8]) -> io::Result<()> {
    let mut f = File::create(file)?;
    f.write_all(buf)
}

fn read_file(file: &str) -> io::Result<String> {
    let mut f = File::open(file)?;
    let mut contents = String::new();
    if let Err(e) = f.read_to_string(&mut contents) {
        return Err(e);
    }
    Ok(contents)
}

fn spawn_device_settings_server(
    state: DeviceSettingsManagerServer,
    stream: DeviceSettingsManagerRequestStream,
) {
    let state = Arc::new(Mutex::new(state));
    fasync::Task::spawn(
        stream
            .try_for_each(move |req| {
                let state = state.clone();
                let mut state = state.lock();
                future::ready(match req {
                    DeviceSettingsManagerRequest::GetInteger { key, responder } => {
                        let file = if let Some(f) = state.setting_file_map.get(&key) {
                            f
                        } else {
                            return future::ready(responder.send(0, Status::ErrInvalidSetting));
                        };
                        match read_file(file) {
                            Err(err) => {
                                if err.kind() == io::ErrorKind::NotFound {
                                    responder.send(0, Status::ErrNotSet)
                                } else {
                                    error!(?err, "reading integer");
                                    responder.send(0, Status::ErrRead)
                                }
                            }
                            Ok(str) => match str.parse::<i64>() {
                                Err(_e) => responder.send(0, Status::ErrIncorrectType),
                                Ok(i) => responder.send(i, Status::Ok),
                            },
                        }
                    }
                    DeviceSettingsManagerRequest::GetString { key, responder } => {
                        let file = if let Some(f) = state.setting_file_map.get(&key) {
                            f
                        } else {
                            return future::ready(responder.send("", Status::ErrInvalidSetting));
                        };
                        match read_file(file) {
                            Err(err) => {
                                if err.kind() == io::ErrorKind::NotFound {
                                    responder.send("", Status::ErrNotSet)
                                } else {
                                    error!(?err, "reading string");
                                    responder.send("", Status::ErrRead)
                                }
                            }
                            Ok(s) => responder.send(&*s, Status::Ok),
                        }
                    }
                    DeviceSettingsManagerRequest::SetInteger { key, val, responder } => {
                        match state.set_key(&key, val.to_string().as_bytes(), ValueType::Number) {
                            Ok(r) => responder.send(r),
                            Err(err) => {
                                error!(?err, "setting integer");
                                responder.send(false)
                            }
                        }
                    }
                    DeviceSettingsManagerRequest::SetString { key, val, responder } => {
                        info!(?key, ?val, "setting string");
                        match state.set_key(&key, val.as_bytes(), ValueType::Text) {
                            Ok(r) => responder.send(r),
                            Err(err) => {
                                error!(?err, "setting string");
                                responder.send(false)
                            }
                        }
                    }
                    DeviceSettingsManagerRequest::Watch { key, watcher, responder } => {
                        if !state.setting_file_map.contains_key(&key) {
                            return future::ready(responder.send(Status::ErrInvalidSetting));
                        }
                        match watcher.into_proxy() {
                            Err(err) => {
                                error!(?err, "getting watcher proxy");
                                responder.send(Status::ErrUnknown)
                            }
                            Ok(w) => {
                                let mut map = state.watchers.lock();
                                let mv = map.entry(key).or_insert(Vec::new());
                                mv.push(w);
                                responder.send(Status::Ok)
                            }
                        }
                    }
                })
            })
            .map_ok(|_| ())
            .unwrap_or_else(|err| error!(?err, "error running device settings server")),
    )
    .detach()
}

#[fuchsia::main(threads = 2, logging_tags = ["device_settings"])]
async fn main() {
    if let Err(err) = main_ds().await {
        error!(?err, "Error running main");
    }
}

async fn main_ds() -> Result<(), Error> {
    let watchers = Arc::new(Mutex::new(HashMap::new()));
    // Attempt to create data directory
    fs::create_dir_all(DATA_DIR).context("creating directory")?;

    let mut fs = ServiceFs::new();
    fs.dir("svc").add_fidl_service(move |stream| {
        let mut d = DeviceSettingsManagerServer {
            setting_file_map: HashMap::new(),
            watchers: watchers.clone(),
        };

        d.initialize_keys(
            DATA_DIR,
            &["TestSetting", "Display.Brightness", "Audio", "FactoryReset"],
        );

        spawn_device_settings_server(d, stream)
    });
    fs.take_and_serve_directory_handle()?;

    Ok(fs.collect().await)
}

#[cfg(test)]
mod tests {
    use super::*;

    use fidl_fuchsia_devicesettings::{DeviceSettingsManagerMarker, DeviceSettingsManagerProxy};
    use futures::prelude::*;
    use tempfile::TempDir;

    fn async_test<F, Fut>(keys: &[&str], f: F)
    where
        F: FnOnce(DeviceSettingsManagerProxy) -> Fut,
        Fut: Future<Output = Result<(), fidl::Error>>,
    {
        let (mut exec, device_settings, _t) = setup(keys).expect("Setup should not have failed");

        let test_fut = f(device_settings);

        exec.run_singlethreaded(test_fut).expect("executor run failed");
    }

    fn setup(
        keys: &[&str],
    ) -> Result<(fasync::LocalExecutor, DeviceSettingsManagerProxy, TempDir), ()> {
        let exec = fasync::LocalExecutor::new().unwrap();
        let mut device_settings = DeviceSettingsManagerServer {
            setting_file_map: HashMap::new(),
            watchers: Arc::new(Mutex::new(HashMap::new())),
        };
        let tmp_dir = TempDir::new().unwrap();

        device_settings.initialize_keys(tmp_dir.path().to_str().unwrap(), keys);

        let (proxy, stream) =
            fidl::endpoints::create_proxy_and_stream::<DeviceSettingsManagerMarker>().unwrap();
        spawn_device_settings_server(device_settings, stream);

        // return tmp_dir to keep it in scope
        return Ok((exec, proxy, tmp_dir));
    }

    #[test]
    fn test_int() {
        async_test(&["TestKey"], |device_settings| async move {
            let response = device_settings.set_integer("TestKey", 18).await?;
            assert!(response, "set_integer failed");
            let response = device_settings.get_integer("TestKey").await?;
            assert_eq!(response, (18, Status::Ok));
            Ok(())
        });
    }

    #[test]
    fn test_string() {
        async_test(&["TestKey"], |device_settings| async move {
            let response = device_settings.set_string("TestKey", "mystring").await?;
            assert!(response, "set_string failed");
            let response = device_settings.get_string("TestKey").await?;
            assert_eq!(response, ("mystring".to_string(), Status::Ok));
            Ok(())
        });
    }

    #[test]
    fn test_invalid_key() {
        async_test(&[], |device_settings| async move {
            let response = device_settings.get_string("TestKey").await?;
            assert_eq!(response, ("".to_string(), Status::ErrInvalidSetting));
            let response = device_settings.get_integer("TestKey").await?;
            assert_eq!(response, (0, Status::ErrInvalidSetting));
            Ok(())
        });
    }

    #[test]
    fn test_incorrect_type() {
        async_test(&["TestKey"], |device_settings| async move {
            let response = device_settings.set_string("TestKey", "mystring").await?;
            assert!(response, "set_string failed");
            let response = device_settings.get_integer("TestKey").await?;
            assert_eq!(response, (0, Status::ErrIncorrectType));
            Ok(())
        });
    }

    #[test]
    fn test_not_set_err() {
        async_test(&["TestKey"], |device_settings| async move {
            let response = device_settings.get_integer("TestKey").await?;
            assert_eq!(response, (0, Status::ErrNotSet));
            let response = device_settings.get_string("TestKey").await?;
            assert_eq!(response, ("".to_string(), Status::ErrNotSet));
            Ok(())
        });
    }

    #[test]
    fn test_multiple_keys() {
        async_test(&["TestKey1", "TestKey2"], |device_settings| async move {
            let response = device_settings.set_integer("TestKey1", 18).await?;
            assert!(response, "set_integer failed");
            let response = device_settings.set_string("TestKey2", "mystring").await?;
            assert!(response, "set_string failed");
            let response = device_settings.get_integer("TestKey1").await?;
            assert_eq!(response, (18, Status::Ok));
            let response = device_settings.get_string("TestKey2").await?;
            assert_eq!(response, ("mystring".to_string(), Status::Ok));
            Ok(())
        });
    }
}
