//! The `system_transaction` module provides functionality for creating system transactions.

use rialo_s_keypair::Keypair;
use rialo_s_message::{ConfigHashPrefix, Message};
use rialo_s_pubkey::Pubkey;
use rialo_s_signer::Signer;
use rialo_s_system_interface::instruction as system_instruction;
use rialo_s_transaction::Transaction;

/// Create and sign new SystemInstruction::CreateAccount transaction
pub fn create_account(
    from_keypair: &Keypair,
    to_keypair: &Keypair,
    valid_from: i64,
    kelvins: u64,
    space: u64,
    program_id: &Pubkey,
    config_hash_prefix: ConfigHashPrefix,
    occ: bool,
) -> Transaction {
    let from_pubkey = from_keypair.pubkey();
    let to_pubkey = to_keypair.pubkey();
    let instruction =
        system_instruction::create_account(&from_pubkey, &to_pubkey, kelvins, space, program_id);
    let message = Message::new(&[instruction], Some(&from_pubkey), config_hash_prefix, occ);
    Transaction::new(&[from_keypair, to_keypair], message, valid_from)
}

/// Create and sign new SystemInstruction::Allocate transaction
pub fn allocate(
    payer_keypair: &Keypair,
    account_keypair: &Keypair,
    valid_from: i64,
    space: u64,
    config_hash_prefix: ConfigHashPrefix,
    occ: bool,
) -> Transaction {
    let payer_pubkey = payer_keypair.pubkey();
    let account_pubkey = account_keypair.pubkey();
    let instruction = system_instruction::allocate(&account_pubkey, space);
    let message = Message::new(&[instruction], Some(&payer_pubkey), config_hash_prefix, occ);
    Transaction::new(&[payer_keypair, account_keypair], message, valid_from)
}

/// Create and sign new system_instruction::Assign transaction
pub fn assign(
    from_keypair: &Keypair,
    valid_from: i64,
    program_id: &Pubkey,
    config_hash_prefix: ConfigHashPrefix,
    occ: bool,
) -> Transaction {
    let from_pubkey = from_keypair.pubkey();
    let instruction = system_instruction::assign(&from_pubkey, program_id);
    let message = Message::new(&[instruction], Some(&from_pubkey), config_hash_prefix, occ);
    Transaction::new(&[from_keypair], message, valid_from)
}

/// Create and sign new system_instruction::Transfer transaction
pub fn transfer(
    from_keypair: &Keypair,
    to: &Pubkey,
    kelvins: u64,
    valid_from: i64,
    config_hash_prefix: ConfigHashPrefix,
    occ: bool,
) -> Transaction {
    let from_pubkey = from_keypair.pubkey();
    let instruction = system_instruction::transfer(&from_pubkey, to, kelvins);
    let message = Message::new(&[instruction], Some(&from_pubkey), config_hash_prefix, occ);
    Transaction::new(&[from_keypair], message, valid_from)
}
