use cid::Cid;
use fvm_shared::ActorID;
use fvm_shared::address::Address;
use fvm_shared::econ::TokenAmount;

use super::{Engine, Machine, MachineContext, Manifest};
use crate::kernel::Result;
use crate::state_tree::{ActorState, StateTree};

type Type = MachineContext;

impl<M: Machine> Machine for Box<M> {
    type Blockstore = M::Blockstore;
    type Externs = M::Externs;

    #[inline(always)]
    fn engine(&self) -> &Engine {
        (**self).engine()
    }

    #[inline(always)]
    fn blockstore(&self) -> &Self::Blockstore {
        (**self).blockstore()
    }

    #[inline(always)]
    fn context(&self) -> &Type {
        (**self).context()
    }

    #[inline(always)]
    fn externs(&self) -> &Self::Externs {
        (**self).externs()
    }

    #[inline(always)]
    fn builtin_actors(&self) -> &Manifest {
        (**self).builtin_actors()
    }

    #[inline(always)]
    fn state_tree(&self) -> &StateTree<Self::Blockstore> {
        (**self).state_tree()
    }

    #[inline(always)]
    fn state_tree_mut(&mut self) -> &mut StateTree<Self::Blockstore> {
        (**self).state_tree_mut()
    }

    #[inline(always)]
    fn create_actor(&mut self, addr: &Address, act: ActorState) -> Result<ActorID> {
        (**self).create_actor(addr, act)
    }

    #[inline(always)]
    fn transfer(&mut self, from: ActorID, to: ActorID, value: &TokenAmount) -> Result<()> {
        (**self).transfer(from, to, value)
    }

    #[inline(always)]
    fn into_store(self) -> Self::Blockstore {
        (*self).into_store()
    }

    #[inline(always)]
    fn flush(&mut self) -> Result<Cid> {
        (**self).flush()
    }

    #[inline(always)]
    fn machine_id(&self) -> &str {
        (**self).machine_id()
    }
}