// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

use std::any::Any;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

use anyhow::Result;

use serde_annotate::{serialize, Annotate, Base};

use structopt::StructOpt;

use opentitanlib::app::command::CommandDispatch;
use opentitanlib::app::TransportWrapper;
use opentitanlib::otp::alert_handler::AlertRegs;
use opentitanlib::otp::lc_state::LcStateVal;
use opentitanlib::otp::otp_img::{OtpImg, OtpImgItem, OtpImgPartition, OtpImgValue};

/// Generate CRC magic value for alert_handler configuration.
#[derive(Debug, StructOpt)]
pub struct AlertDigest {
    #[structopt(help = "OTP memory map file containing alert_handler config in HJSON format")]
    alert_cfg: PathBuf,
    #[structopt(
        long,
        help = "Output file to write the new OTP overlay to instead of printing"
    )]
    output: Option<PathBuf>,
    #[structopt(
        long,
        default_value = "OWNER_SW_CFG",
        help = "Override switch to specify a custom partition"
    )]
    partition: String,
}

impl CommandDispatch for AlertDigest {
    fn run(
        &self,
        _context: &dyn Any,
        _transport: &TransportWrapper,
    ) -> Result<Option<Box<dyn Annotate>>> {
        // From kErrorOk in ROM.
        const ERROR_OK: u32 = 0x739;

        // Life cycle states to generate digests for.
        let lc_states = [
            ("OWNER_SW_CFG_ROM_ALERT_DIGEST_PROD", LcStateVal::Prod),
            (
                "OWNER_SW_CFG_ROM_ALERT_DIGEST_PROD_END",
                LcStateVal::ProdEnd,
            ),
            ("OWNER_SW_CFG_ROM_ALERT_DIGEST_DEV", LcStateVal::Dev),
            ("OWNER_SW_CFG_ROM_ALERT_DIGEST_RMA", LcStateVal::Rma),
        ];

        // Read in the OTP img description.
        let otp = OtpImg::from_file(&self.alert_cfg)?;

        let mut items = Vec::<OtpImgItem>::new();

        for lc_state in lc_states {
            // Create model for alert_handler register states.
            let alert = AlertRegs::try_new(lc_state.1, &otp)?;

            // Use alert_handler registers states to construct CRC32 checksum.
            let crc32 = alert.crc32();

            // Match digest format expected by ROM.
            let digest = crc32 ^ lc_state.1 as u32 ^ ERROR_OK;

            items.push(OtpImgItem {
                name: lc_state.0.to_owned(),
                value: OtpImgValue::Word(digest as u64),
            });
        }

        // Construct OTP image overlay.
        let img_out = OtpImg {
            seed: None,
            partitions: vec![OtpImgPartition {
                name: self.partition.clone(),
                items: Some(items),
            }],
        };

        if let Some(output) = &self.output {
            let mut file = File::create(&output)?;
            file.write_all(
                serialize(&img_out)?
                    .to_json()
                    .bases(&[Base::Hex])
                    .to_string()
                    .as_bytes(),
            )?;
            Ok(None)
        } else {
            Ok(Some(Box::new(img_out)))
        }
    }
}

#[derive(Debug, StructOpt, CommandDispatch)]
/// OTP related commands.
pub enum Otp {
    AlertDigest(AlertDigest),
}
