// 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 fuchsia_syslog as syslog;
use fuchsia_syslog::{fx_log_err, fx_log_info};
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;

// 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(e) = w.on_change_settings(t) {
                    if e.is_closed() {
                        return false;
                    }
                    fx_log_err!("Error call watcher: {:?}", e);
                }
                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(e) => {
                                if e.kind() == io::ErrorKind::NotFound {
                                    responder.send(0, Status::ErrNotSet)
                                } else {
                                    fx_log_err!("reading integer: {:?}", e);
                                    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(e) => {
                                if e.kind() == io::ErrorKind::NotFound {
                                    responder.send("", Status::ErrNotSet)
                                } else {
                                    fx_log_err!("reading string: {:?}", e);
                                    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(e) => {
                                fx_log_err!("setting integer: {:?}", e);
                                responder.send(false)
                            }
                        }
                    }
                    DeviceSettingsManagerRequest::SetString { key, val, responder } => {
                        fx_log_info!("setting string key: {:?}, val: {:?}", key, val);
                        match state.set_key(&key, val.as_bytes(), ValueType::Text) {
                            Ok(r) => responder.send(r),
                            Err(e) => {
                                fx_log_err!("setting string: {:?}", e);
                                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(e) => {
                                fx_log_err!("getting watcher proxy: {:?}", e);
                                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(|e| eprintln!("error running device settings server: {:?}", e)),
    )
    .detach()
}

fn main() {
    if let Err(e) = main_ds() {
        fx_log_err!("{:?}", e);
    }
}

fn main_ds() -> Result<(), Error> {
    syslog::init_with_tags(&["device_settings"])?;
    let mut core = fasync::Executor::new().context("unable to create executor")?;

    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(core.run(fs.collect(), /* threads */ 2))
}

#[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::Executor, DeviceSettingsManagerProxy, TempDir), ()> {
        let exec = fasync::Executor::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(())
        });
    }
}
