// 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.

// #![deny(warnings)]

#![feature(async_await, await_macro, try_from, futures_api)]

use failure::{Error, ResultExt};
use fidl::endpoints::RequestStream;
use fidl::endpoints::ServiceMarker;
use fuchsia_app::server::ServicesServer;
use fuchsia_async as fasync;
use fuchsia_syslog::{fx_log_err, fx_log_info};
use futures::{TryFutureExt, TryStreamExt};
use parking_lot::Mutex;
use std::convert::{TryFrom, TryInto};
use std::env;
use std::path::PathBuf;
use std::process;
use std::sync::Arc;

mod accessor;
mod instance;
mod store;

use fidl_fuchsia_stash::{SecureStoreMarker, StoreMarker, StoreRequest, StoreRequestStream};

struct StashSettings {
    backing_file: String,
    secure_mode: bool,
}

impl Default for StashSettings {
    fn default() -> StashSettings {
        StashSettings {
            backing_file: "/data/stash.store".to_string(),
            secure_mode: false,
        }
    }
}

impl TryFrom<env::Args> for StashSettings {
    type Error = ();
    fn try_from(mut args: env::Args) -> Result<StashSettings, ()> {
        // ignore arg[0]
        let _ = args.next();
        let mut res = StashSettings::default();
        while let Some(flag) = args.next() {
            match flag.as_str() {
                "--backing_file" => {
                    if let Some(f) = args.next() {
                        res.backing_file = f;
                    } else {
                        return Err(());
                    }
                }
                "--secure" => res.secure_mode = true,
                _ => return Err(()),
            }
        }
        return Ok(res);
    }
}

fn main() -> Result<(), Error> {
    fuchsia_syslog::init_with_tags(&["stash"])?;

    let r_opts: Result<StashSettings, ()> = env::args().try_into();

    match r_opts {
        Err(_) => {
            print_help();
            process::exit(1);
        }
        Ok(opts) => {
            let mut executor = fasync::Executor::new().context("Error creating executor")?;
            let store_manager = Arc::new(Mutex::new(store::StoreManager::new(PathBuf::from(
                &opts.backing_file,
            ))?));

            let marker = if opts.secure_mode {
                SecureStoreMarker::NAME
            } else {
                StoreMarker::NAME
            };

            let fut = ServicesServer::new()
                .add_service((marker, move |chan| {
                    stash_server(
                        store_manager.clone(),
                        !opts.secure_mode,
                        chan,
                    )
                })).start()
                .context("Error starting stash server")?;
            executor
                .run_singlethreaded(fut)
                .context("failed to execute stash service future")?;
        }
    }
    Ok(())
}

fn print_help() {
    println!(
        r"stash
garnet service for storing key/value pairs

USAGE:
    stash [FLAGS]

FLAGS:
        --secure                Disables support for handling raw bytes. This flag Should be used
                                when running in critical path of verified boot.
        --backing_file <FILE>   location of backing file for the store"
    )
}

fn stash_server(
    store_manager: Arc<Mutex<store::StoreManager>>,
    enable_bytes: bool,
    chan: fasync::Channel,
) {
    fasync::spawn(async move {
        fx_log_info!("new connection");
        let mut state = instance::Instance {
            client_name: None,
            enable_bytes: enable_bytes,
            store_manager: store_manager,
        };

        let mut stream = StoreRequestStream::from_channel(chan);
        while let Some(req) = await!(stream.try_next()).context("error running stash server")? {
            match req {
                StoreRequest::Identify {
                    name,
                    control_handle,
                } => {
                    if let Err(e) = state.identify(name.clone()) {
                        control_handle.shutdown();
                        return Err(e);
                    }
                    fx_log_info!("identified new client: {}", name);
                }
                StoreRequest::CreateAccessor {
                    read_only,
                    control_handle,
                    accessor_request,
                } => {
                    if let Err(e) = state.create_accessor(read_only, accessor_request) {
                        control_handle.shutdown();
                        return Err(e);
                    }
                    fx_log_info!("created new accessor");
                }
            }
        }
        Ok(())
    }.unwrap_or_else(|e: failure::Error| fx_log_err!("couldn't run stash service: {:?}", e)));
}
