// Copyright 2019 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::Error,
    fidl::endpoints::create_proxy,
    fidl_fuchsia_factory::MiscFactoryStoreProviderProxy,
    fidl_fuchsia_hwinfo,
    fidl_fuchsia_intl::{LocaleId, RegulatoryDomain},
    fidl_fuchsia_io::{DirectoryMarker, OPEN_RIGHT_READABLE},
    fuchsia_syslog::{self, fx_log_err, fx_log_warn},
    serde::{Deserialize, Serialize},
    std::{fs::File, io, path::Path},
};

// CONFIG AND FACTORY FILE NAMES
const PRODUCT_CONFIG_JSON_FILE: &str = "/config/data/product_config.json";
const BOARD_CONFIG_JSON_FILE: &str = "/config/data/board_config.json";
const DEFAULT_PRODUCT_CONFIG_JSON_FILE: &str = "/config/data/default_product_config.json";
const DEFAULT_BOARD_CONFIG_JSON_FILE: &str = "/config/data/default_board_config.json";
const SERIAL_TXT: &str = "serial.txt";
const LOCALE_LIST_FILE: &str = "locale_list.txt";
const HW_TXT: &str = "hw.txt";
const RETAIL_DEMO_FILE: &str = "demo_device";
// CONFIG KEYS
const SKU_KEY: &str = "config";
const LANGUAGE_KEY: &str = "lang";
const REGULATORY_DOMAIN_KEY: &str = "country";
const BUILD_DATE_KEY: &str = "mfg_date";
const BUILD_NAME_KEY: &str = "build_name";
const COLORWAY_KEY: &str = "color";
const DISPLAY_KEY: &str = "display";
const MEMORY_KEY: &str = "memory";
const NAND_STORAGE_KEY: &str = "nand";
const EMMC_STORAGE_KEY: &str = "emmc";
const MICROPHONE_KEY: &str = "mic";
const AUDIO_AMPLIFIER_KEY: &str = "amp";

async fn read_factory_file(
    path: &str,
    proxy_handle: &MiscFactoryStoreProviderProxy,
) -> Result<String, Error> {
    let (dir_proxy, dir_server_end) = create_proxy::<DirectoryMarker>()?;
    proxy_handle.get_factory_store(dir_server_end)?;
    let file_proxy = io_util::open_file(&dir_proxy, &Path::new(path), OPEN_RIGHT_READABLE)?;
    let result = io_util::read_file(&file_proxy).await?.trim().to_owned();
    return Ok(result);
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DeviceInfo {
    pub serial_number: Option<String>,
    pub is_retail_demo: bool,
    pub retail_sku: Option<String>,
}

impl DeviceInfo {
    pub async fn load(proxy_handle: &MiscFactoryStoreProviderProxy) -> Self {
        let mut device_info =
            DeviceInfo { serial_number: None, is_retail_demo: false, retail_sku: None };
        device_info.serial_number = match read_factory_file(SERIAL_TXT, proxy_handle).await {
            Ok(content) => Some(content),
            Err(err) => {
                fx_log_err!("Failed to read factory file {}: {}", SERIAL_TXT.to_string(), err);
                None
            }
        };
        if let Ok(content) = read_factory_file(RETAIL_DEMO_FILE, proxy_handle).await {
            device_info.is_retail_demo = true;
            device_info.retail_sku = Some(content)
        };
        device_info
    }
}

impl Into<fidl_fuchsia_hwinfo::DeviceInfo> for DeviceInfo {
    fn into(self) -> fidl_fuchsia_hwinfo::DeviceInfo {
        fidl_fuchsia_hwinfo::DeviceInfo {
            serial_number: self.serial_number,
            is_retail_demo: Some(self.is_retail_demo),
            retail_sku: self.retail_sku,
            ..fidl_fuchsia_hwinfo::DeviceInfo::EMPTY
        }
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct BoardInfo {
    pub name: Option<String>,
    pub revision: Option<String>,
}

impl BoardInfo {
    fn read_config(path: &str) -> Result<Self, Error> {
        let board_info: BoardInfo = serde_json::from_reader(io::BufReader::new(File::open(path)?))?;
        Ok(board_info)
    }

    pub fn load() -> Self {
        let board_info = BoardInfo::read_config(BOARD_CONFIG_JSON_FILE).unwrap_or_else(|err| {
            fx_log_err!("Failed to read board_config.json due to {}", err);
            BoardInfo::read_config(DEFAULT_BOARD_CONFIG_JSON_FILE).unwrap_or_else(|err| {
                fx_log_err!("Failed to read default_board_config.json due to {}", err);
                BoardInfo { name: None, revision: None }
            })
        });
        board_info
    }
}

impl Into<fidl_fuchsia_hwinfo::BoardInfo> for BoardInfo {
    fn into(self) -> fidl_fuchsia_hwinfo::BoardInfo {
        fidl_fuchsia_hwinfo::BoardInfo {
            name: self.name,
            revision: self.revision,
            ..fidl_fuchsia_hwinfo::BoardInfo::EMPTY
        }
    }
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ConfigFile {
    pub name: String,
    pub model: String,
    pub manufacturer: String,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ProductInfo {
    pub sku: Option<String>,
    pub language: Option<String>,
    pub country_code: Option<String>,
    pub locales: Vec<String>,
    pub name: Option<String>,
    pub model: Option<String>,
    pub manufacturer: Option<String>,
    pub build_date: Option<String>,
    pub build_name: Option<String>,
    pub colorway: Option<String>,
    pub display: Option<String>,
    pub memory: Option<String>,
    pub nand_storage: Option<String>,
    pub emmc_storage: Option<String>,
    pub microphone: Option<String>,
    pub audio_amplifier: Option<String>,
}

impl ProductInfo {
    fn new() -> Self {
        ProductInfo {
            sku: None,
            language: None,
            country_code: None,
            locales: Vec::new(),
            name: None,
            model: None,
            manufacturer: None,
            build_date: None,
            build_name: None,
            colorway: None,
            display: None,
            memory: None,
            nand_storage: None,
            emmc_storage: None,
            microphone: None,
            audio_amplifier: None,
        }
    }

    fn load_from_config_data(&mut self, path: &str) -> Result<(), Error> {
        let config_map: ConfigFile =
            serde_json::from_reader(io::BufReader::new(File::open(path)?))?;
        self.name = Some(config_map.name);
        self.model = Some(config_map.model);
        self.manufacturer = Some(config_map.manufacturer);
        Ok(())
    }

    async fn load_from_hw_file(
        &mut self,
        path: &str,
        proxy_handle: &MiscFactoryStoreProviderProxy,
    ) -> Result<(), Error> {
        let file_content = read_factory_file(path, proxy_handle).await?;
        for config in file_content.lines() {
            let pair: Vec<_> = config.splitn(2, "=").collect();
            let key = pair[0];
            let value = pair[1];
            match key {
                SKU_KEY => {
                    self.sku = Some(value.to_owned());
                }
                LANGUAGE_KEY => {
                    self.language = Some(value.to_owned());
                }
                REGULATORY_DOMAIN_KEY => {
                    self.country_code = Some(value.to_owned());
                }
                BUILD_DATE_KEY => {
                    self.build_date = Some(value.to_owned());
                }
                BUILD_NAME_KEY => {
                    self.build_name = Some(value.to_owned());
                }
                COLORWAY_KEY => {
                    self.colorway = Some(value.to_owned());
                }
                DISPLAY_KEY => {
                    self.display = Some(value.to_owned());
                }
                MEMORY_KEY => {
                    self.memory = Some(value.to_owned());
                }
                NAND_STORAGE_KEY => {
                    self.nand_storage = Some(value.to_owned());
                }
                EMMC_STORAGE_KEY => {
                    self.emmc_storage = Some(value.to_owned());
                }
                MICROPHONE_KEY => {
                    self.microphone = Some(value.to_owned());
                }
                AUDIO_AMPLIFIER_KEY => {
                    self.audio_amplifier = Some(value.to_owned());
                }
                _ => {
                    fx_log_warn!("hw.txt dictionary values {} - {}", key, value.to_owned());
                }
            }
            fx_log_warn!("hw.txt line: {}", config);
        }
        Ok(())
    }

    async fn load_from_locale_list(
        &mut self,
        path: &str,
        proxy_handle: &MiscFactoryStoreProviderProxy,
    ) -> Result<(), Error> {
        let file_content = read_factory_file(path, proxy_handle).await?;
        self.locales = Vec::new();
        for line in file_content.lines() {
            self.locales.push(line.trim().to_owned());
        }
        Ok(())
    }

    pub async fn load(proxy_handle: &MiscFactoryStoreProviderProxy) -> Self {
        let mut product_info = ProductInfo::new();
        if let Err(err) = product_info.load_from_config_data(PRODUCT_CONFIG_JSON_FILE) {
            fx_log_err!("Failed to load product_config.json due to {}", err);
            if let Err(err) = product_info.load_from_config_data(DEFAULT_PRODUCT_CONFIG_JSON_FILE) {
                fx_log_err!("Failed to load default_product_config.json due to {}", err);
            }
        }
        if let Err(err) = product_info.load_from_hw_file(HW_TXT, proxy_handle).await {
            fx_log_err!("Failed to load hw.txt.txt due to {}", err);
        }
        if let Err(err) = product_info.load_from_locale_list(LOCALE_LIST_FILE, proxy_handle).await {
            fx_log_err!("Failed to load local_list.txt due to {}", err);
        }
        product_info
    }
}

impl Into<fidl_fuchsia_hwinfo::ProductInfo> for ProductInfo {
    fn into(self) -> fidl_fuchsia_hwinfo::ProductInfo {
        let mut locale_list: Vec<LocaleId> = Vec::new();
        for locale in self.locales {
            locale_list.push(LocaleId { id: locale.to_owned() });
        }
        fidl_fuchsia_hwinfo::ProductInfo {
            sku: self.sku,
            language: self.language,
            regulatory_domain: if self.country_code.is_none() {
                None
            } else {
                Some(RegulatoryDomain {
                    country_code: self.country_code,
                    ..RegulatoryDomain::EMPTY
                })
            },
            locale_list: if locale_list.is_empty() { None } else { Some(locale_list) },
            name: self.name,
            model: self.model,
            manufacturer: self.manufacturer,
            build_date: self.build_date,
            build_name: self.build_name,
            colorway: self.colorway,
            display: self.display,
            memory: self.memory,
            nand_storage: self.nand_storage,
            emmc_storage: self.emmc_storage,
            microphone: self.microphone,
            audio_amplifier: self.audio_amplifier,
            ..fidl_fuchsia_hwinfo::ProductInfo::EMPTY
        }
    }
}
