use super::*;
impl<N: Network> Process<N> {
    #[inline]
    pub fn execute<A: circuit::Aleo<Network = N>>(
        &self,
        authorization: Authorization<N>,
    ) -> Result<(Response<N>, Trace<N>)> {
        let timer = timer!("Process::execute");
        let request = authorization.peek_next()?;
        let locator = Locator::new(*request.program_id(), *request.function_name());
        #[cfg(feature = "aleo-cli")]
        println!("{}", format!(" • Executing '{locator}'...",).dimmed());
        let trace = Arc::new(RwLock::new(Trace::new()));
        let call_stack = CallStack::execute(authorization, trace.clone())?;
        lap!(timer, "Initialize call stack");
        let stack = self.get_stack(request.program_id())?;
        let response = stack.execute_function::<A>(call_stack, None)?;
        lap!(timer, "Execute the function");
        let trace = Arc::try_unwrap(trace).unwrap().into_inner();
        ensure!(!trace.transitions().is_empty(), "Execution of '{locator}' is empty");
        finish!(timer);
        Ok((response, trace))
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    use console::types::Address;
    type CurrentNetwork = console::network::Testnet3;
    type CurrentAleo = circuit::AleoV0;
    #[test]
    fn test_execute_fee_private() {
        let rng = &mut TestRng::default();
        let process = Process::<CurrentNetwork>::load().unwrap();
        let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
        let owner = Address::try_from(private_key).unwrap();
        let base_fee_in_microcredits = rng.gen_range(0..u64::MAX / 2);
        let priority_fee_in_microcredits = rng.gen_range(0..u64::MAX / 2);
        let total_fee = base_fee_in_microcredits.saturating_add(priority_fee_in_microcredits);
        let credits = Record::<CurrentNetwork, Plaintext<_>>::from_str(&format!(
            "{{ owner: {owner}.private, microcredits: {total_fee}u64.private, _nonce: 0group.public }}"
        ))
        .unwrap();
        let deployment_or_execution_id = Field::rand(rng);
        let authorization = process
            .authorize_fee_private::<CurrentAleo, _>(
                &private_key,
                credits,
                base_fee_in_microcredits,
                priority_fee_in_microcredits,
                deployment_or_execution_id,
                rng,
            )
            .unwrap();
        assert!(authorization.is_fee_private(), "Authorization must be for a call to 'credits.aleo/fee_private'");
        let (response, trace) = process.execute::<CurrentAleo>(authorization).unwrap();
        assert_eq!(response.outputs().len(), 1, "Execution of 'credits.aleo/fee_private' must contain 1 output");
        assert_eq!(response.output_ids().len(), 1, "Execution of 'credits.aleo/fee_private' must contain 1 output ID");
        assert_eq!(trace.transitions().len(), 1, "Execution of 'credits.aleo/fee_private' must contain 1 transition");
        let transition = trace.transitions()[0].clone();
        assert!(transition.is_fee_private(), "Transition must be for 'credits.aleo/fee_private'");
    }
    #[test]
    fn test_execute_fee_public() {
        let rng = &mut TestRng::default();
        let process = Process::<CurrentNetwork>::load().unwrap();
        let private_key = PrivateKey::new(rng).unwrap();
        let base_fee_in_microcredits = rng.gen_range(0..u64::MAX / 2);
        let priority_fee_in_microcredits = rng.gen_range(0..u64::MAX / 2);
        let deployment_or_execution_id = Field::rand(rng);
        let authorization = process
            .authorize_fee_public::<CurrentAleo, _>(
                &private_key,
                base_fee_in_microcredits,
                priority_fee_in_microcredits,
                deployment_or_execution_id,
                rng,
            )
            .unwrap();
        assert!(authorization.is_fee_public(), "Authorization must be for a call to 'credits.aleo/fee_public'");
        let (response, trace) = process.execute::<CurrentAleo>(authorization).unwrap();
        assert_eq!(response.outputs().len(), 1, "Execution of 'credits.aleo/fee_public' must contain 1 output");
        assert_eq!(response.output_ids().len(), 1, "Execution of 'credits.aleo/fee_public' must contain 1 output ID");
        assert_eq!(trace.transitions().len(), 1, "Execution of 'credits.aleo/fee_public' must contain 1 transition");
        let transition = trace.transitions()[0].clone();
        assert!(transition.is_fee_public(), "Transition must be for 'credits.aleo/fee_public'");
    }
}