//Nombre maximum de correspondances dans une table des pages
//Cette donnée devra a terme etre recupérée depuis un fichier de configuration
const MaxVirtPages : u64 = 200000;


/* Une table de correspondance propre à un processus
*  Une variable de type TranslationTable devra etre possédée par un objet de type Process
 */
pub struct TranslationTable{
    //capacité de cette table <=> nombre de correspondances possibles
    //A voir si cette donnée doit etre immuable
    pub maxNumPages : u64,

    //la table en question
    //Vec implemente le trait Index, donc un bon choix
    pub pageTable : Vec<PageTableEntry>
}

impl TranslationTable {

    pub fn create() -> TranslationTable {

        let mut tmp_vec : Vec<PageTableEntry> = Vec::new();

        for i in 0..MaxVirtPages {
            tmp_vec.push(PageTableEntry::create());
        }

        TranslationTable{
            maxNumPages : MaxVirtPages,
            pageTable : tmp_vec
        }
    }

    //vpn = virtual page number, c'est un index dans la table des page
    //Assert a mettre dans chacune des fonctions suivantes

    pub fn get_max_num_pages(&self) -> u64{
        return self.maxNumPages;
    }

    pub fn set_physical_page(&mut self, vpn : u64, physical_page : i32){
        self.pageTable[vpn as usize].physical_page = physical_page;
    }

    pub fn get_physical_page(&self, vpn : u64) -> i32{
        self.pageTable[vpn as usize].physical_page
    }

    pub fn set_addr_disk(&mut self, vpn : u64, addr_disk : i32){
        self.pageTable[vpn as usize].addr_disk = addr_disk;
    }

    pub fn get_addr_disk(&self, vpn : u64) -> i32 {
        self.pageTable[vpn as usize].addr_disk
    }

    pub fn set_bit_valid(&mut self, vpn : u64){
        self.pageTable[vpn as usize].valid = true;
    }

    pub fn clear_bit_valid(&mut self, vpn : u64){
        self.pageTable[vpn as usize].valid = false;
    }

    pub fn get_bit_valid(&self, vpn : u64) -> bool{
        self.pageTable[vpn as usize].valid
    }

    pub fn set_bit_io(&mut self, vpn : u64){
        self.pageTable[vpn as usize].io = true;
    }

    pub fn clear_bit_io(&mut self, vpn : u64){
        self.pageTable[vpn as usize].io = false;
    }

    pub fn get_bit_io(&self, vpn : u64) -> bool{
        self.pageTable[vpn as usize].io
    }

    pub fn set_bit_swap(&mut self, vpn : u64){
        self.pageTable[vpn as usize].swap = true;
    }

    pub fn clear_bit_swap(&mut self, vpn : u64){
        self.pageTable[vpn as usize].swap = false;
    }

    pub fn get_bit_swap(&self, vpn : u64) -> bool{
        self.pageTable[vpn as usize].swap
    }

    pub fn set_bit_write(&mut self, vpn : u64){
        self.pageTable[vpn as usize].write_allowed = true;
    }

    pub fn clear_bit_write(&mut self, vpn : u64){
        self.pageTable[vpn as usize].write_allowed = false;
    }

    pub fn get_bit_write(&self, vpn : u64) -> bool{
        self.pageTable[vpn as usize].write_allowed
    }

    pub fn set_bit_read(&mut self, vpn : u64){
        self.pageTable[vpn as usize].read_allowed = true;
    }

    pub fn clear_bit_read(&mut self, vpn : u64){
        self.pageTable[vpn as usize].read_allowed = false;
    }

    pub fn get_bit_read(&self, vpn : u64) -> bool{
        self.pageTable[vpn as usize].read_allowed
    }

    pub fn set_bit_U(&mut self, vpn : u64){
        self.pageTable[vpn as usize].U = true;
    }

    pub fn clear_bit_U(&mut self, vpn : u64){
        self.pageTable[vpn as usize].U = false;
    }

    pub fn get_bit_U(&self, vpn : u64) -> bool{
        self.pageTable[vpn as usize].U
    }

    pub fn set_bit_M(&mut self, vpn : u64){
        self.pageTable[vpn as usize].M = true;
    }

    pub fn clear_bit_M(&mut self, vpn : u64){
        self.pageTable[vpn as usize].M = false;
    }

    pub fn get_bit_M(&self, vpn : u64) -> bool{
        self.pageTable[vpn as usize].M
    }


}



/* Une correspondance + données sur cette correspondance
 */
pub struct PageTableEntry{
    //true <=> la correspondance est valide et la page est présente dans la ram
    valid : bool,

    //true <=> la page a été accédée (lecture/ecriture) récemment
    U : bool,
    
    //true <=> page modifiée mais non sauvegardée sur disque
    M : bool,

    //droits d'accès sur cette page
    read_allowed : bool,
    write_allowed : bool,

    //numero de page physique <=> c'est notre correspondance
    physical_page : i32,

    //true <=> cette page doit etre chargée depuis la swap zone du disque
    swap : bool,

    //a définir plus tard, en relation avec swap
    addr_disk : i32,

    //mis  à 1 par le système quand cette page est impliquée dans une opération d'IO
    io : bool
}

impl PageTableEntry{

    //Default PageTableEntry Constructor
    pub fn create() -> PageTableEntry {
        PageTableEntry {
            valid : false,
            U : false,
            M : false,
            read_allowed : false,
            write_allowed : false,
            physical_page : -1i32,
            swap : false,
            addr_disk : -1i32,
            io : false
        }
    }

}