use solana_program::pubkey::Pubkey;
use anchor_lang::zero_copy;
use sha2::{Sha256, Digest};

#[zero_copy(unsafe)]
#[repr(packed)]
pub struct OracleSubmission {
    /// The public key of the oracle that submitted this value.
    pub oracle: Pubkey,
    /// The slot at which this value was signed.
    pub slot: u64,
    /// The value that was submitted.
    pub value: i128,
}

#[repr(packed)]
pub struct PullFeedAccountData {
    /// The public key of the authority that can update the feed hash that
    /// this account will use for registering updates.
    pub authority: Pubkey,
    /// SHA-256 hash of the job schema oracles will execute to produce data
    /// for this feed.
    pub feed_hash: [u8; 32],
    /// The slot at which this account was initialized.
    pub initialized_at: i64,
    /// The public key of the queue which oracles must be bound to in order to
    /// submit data to this feed.
    pub queue: Pubkey,
    /// The oracle submissions for this feed.
    pub submissions: [OracleSubmission; 32],
    pub permissions: u64,
    // The allowed variance between all sources of the jobs.
    // This value is part of the feed-hash
    pub max_variance: u64,
    // The minimum number of responses required to submit a response.
    // This value is part of the feed-hash
    pub min_responses: u32,
    pub _ebuf: [u8; 1024],
}

impl PullFeedAccountData {
    pub fn generate_checksum(&self, result: i128, slothash: [u8; 32]) -> [u8; 32] {
        Self::generate_checksum_inner(self.queue, self.feed_hash, result, slothash, self.max_variance, self.min_responses)
    }

    pub fn generate_checksum_inner(
        queue: Pubkey,
        feed_hash: [u8; 32],
        result: i128,
        slothash: [u8; 32],
        max_variance: u64,
        min_responses: u32,
        ) -> [u8; 32] {
        let mut hasher = Sha256::new();
        hasher.update(queue.to_bytes());
        hasher.update(feed_hash);
        hasher.update(result.to_le_bytes());
        hasher.update(slothash);
        hasher.update(max_variance.to_le_bytes());
        hasher.update(min_responses.to_le_bytes());
        hasher.finalize().to_vec().try_into().unwrap()
    }
}

// impl Discriminator for PullFeedAccountData {
    // const DISCRIMINATOR: [u8; 8] = [128, 30, 16, 241, 170, 73, 55,  54 ];
//
    // fn discriminator() -> [u8; 8] {
        // println!("DISCRIMINATOR: {:?}", &Self::DISCRIMINATOR);
        // Self::DISCRIMINATOR.clone()
    // }
// }
