use borsh::BorshSerialize;
use borsh::BorshDeserialize;
use solana_program::pubkey::Pubkey;
use solana_program::account_info::AccountInfo;
use solana_program::clock::Epoch;
use solana_program::entrypoint::ProgramResult;
use solana_program::msg;
use std::mem;

fn process_instruction(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    _instruction_data: &[u8],
    ) -> ProgramResult {

    let account = &accounts[0];

    println!("program_id: {}", program_id);
    println!("owner: {}", account.owner);

    msg!("hello");

    let mut greeting_account = GreetingAccount::try_from_slice(&account.data.borrow())?;
    greeting_account.counter += 1;
    greeting_account.serialize(&mut &mut account.data.borrow_mut()[..])?;

    Ok(())
}

#[derive(BorshSerialize, BorshDeserialize, Debug)]
pub struct GreetingAccount {
    pub counter: u32,
}

fn main() -> nothing::Probably<()> {
    let program_id = Pubkey::default();
    let key = Pubkey::default();
    let mut lamports = 0;
    let mut data = vec![0; mem::size_of::<u32>()];
    let owner = Pubkey::default();
    let epoch = Epoch::default();
    println!("default Pubkey: {}", key);
    println!("default epoch: {}", epoch);
    let account = AccountInfo::new(
        &key,
        false,
        true,
        &mut lamports,
        &mut data,
        &owner,
        false,
        Epoch::default(),
        );
    println!("default account: {:?}", account);
    let instruction_data: Vec<u8> = Vec::new();

    let accounts = vec![account];

    process_instruction(&program_id, &accounts, &instruction_data).unwrap();
    println!("{:?}", &accounts[0].data);

    process_instruction(&program_id, &accounts, &instruction_data).unwrap();
    println!("{:?}", &accounts[0].data);

    process_instruction(&program_id, &accounts, &instruction_data).unwrap();
    println!("{:?}", &accounts[0].data);

    ().into()
}