use frame_support::pallet_prelude::Get;
use sp_staking::{EraIndex, SessionIndex};
use sp_std::vec::Vec;
pub trait EraInfoProvider {
    type AccountId;
    fn active_era() -> Option<EraIndex>;
    fn current_era() -> Option<EraIndex>;
    fn era_start_session_index(era: EraIndex) -> Option<SessionIndex>;
    fn sessions_per_era() -> SessionIndex;
    fn elected_validators(era: EraIndex) -> Vec<Self::AccountId>;
}
impl<T> EraInfoProvider for pallet_staking::Pallet<T>
where
    T: pallet_staking::Config,
{
    type AccountId = T::AccountId;
    fn active_era() -> Option<EraIndex> {
        pallet_staking::ActiveEra::<T>::get().map(|ae| ae.index)
    }
    fn current_era() -> Option<EraIndex> {
        pallet_staking::CurrentEra::<T>::get()
    }
    fn era_start_session_index(era: EraIndex) -> Option<SessionIndex> {
        pallet_staking::ErasStartSessionIndex::<T>::get(era)
    }
    fn sessions_per_era() -> SessionIndex {
        T::SessionsPerEra::get()
    }
    fn elected_validators(era: EraIndex) -> Vec<Self::AccountId> {
        pallet_staking::ErasStakers::<T>::iter_key_prefix(era).collect()
    }
}
pub trait ValidatorRewardsHandler {
    type AccountId;
    fn validator_totals(era: EraIndex) -> Vec<(Self::AccountId, u128)>;
    fn add_rewards(rewards: impl IntoIterator<Item = (Self::AccountId, u32)>);
}
impl<T> ValidatorRewardsHandler for pallet_staking::Pallet<T>
where
    T: pallet_staking::Config,
    <T as pallet_staking::Config>::CurrencyBalance: Into<u128>,
{
    type AccountId = T::AccountId;
    fn validator_totals(era: EraIndex) -> Vec<(Self::AccountId, u128)> {
        pallet_staking::ErasStakers::<T>::iter_prefix(era)
            .map(|(validator, exposure)| (validator, exposure.total.into()))
            .collect()
    }
    fn add_rewards(rewards: impl IntoIterator<Item = (Self::AccountId, u32)>) {
        pallet_staking::Pallet::<T>::reward_by_ids(rewards);
    }
}
pub trait ValidatorExtractor {
    type AccountId;
    fn remove_validator(who: &Self::AccountId);
}
impl<T> ValidatorExtractor for pallet_staking::Pallet<T>
where
    T: pallet_staking::Config,
{
    type AccountId = T::AccountId;
    fn remove_validator(who: &Self::AccountId) {
        pallet_staking::Pallet::<T>::do_remove_validator(who);
    }
}