use p101_is::instruction::*;
use crate::alu::{SplitRegister, MemoryRegister};
use crate::alu::Memory;

use rust_decimal::Decimal;

pub struct MemoryBuilder {
    memory: Memory,
}

impl MemoryBuilder {
    pub fn new() -> MemoryBuilder {
        MemoryBuilder {
            memory: Memory::new(),
        }
    }

    pub fn with_p1(mut self, p1: [Option<Instruction>; 24]) -> MemoryBuilder {
        self.memory.p1 = p1;
        self
    }

    pub fn with_p2(mut self, p2: [Option<Instruction>; 24]) -> MemoryBuilder {
        self.memory.p2 = p2;
        self
    }

    pub fn with_m(mut self, value: Decimal) -> MemoryBuilder {
        match self.memory.m.write(value) {
            Ok(_) => self,
            Err(e) => panic!("{}", e),
        }
    }

    pub fn with_a(mut self, value: Decimal) -> MemoryBuilder {
        match self.memory.a.write(value) {
            Ok(_) => self,
            Err(e) => panic!("{}", e),
        }
    }

    pub fn with_r(mut self, value: Decimal) -> MemoryBuilder {
        match self.memory.r.write(value) {
            Ok(_) => self,
            Err(e) => panic!("{}", e),
        }
    }

    pub fn with_b(mut self, value: SplitRegister) -> MemoryBuilder {
        self.memory.b = value;
        self
    }

    pub fn with_c(mut self, value: SplitRegister) -> MemoryBuilder {
        self.memory.c = value;
        self
    }

    pub fn with_d(mut self, value: MemoryRegister) -> MemoryBuilder {
        self.memory.d = value;
        self
    }

    pub fn with_e(mut self, value: MemoryRegister) -> MemoryBuilder {
        self.memory.e = value;
        self
    }

    pub fn with_f(mut self, value: MemoryRegister) -> MemoryBuilder {
        self.memory.f = value;
        self
    }

    pub fn with_precision(mut self, p: u32) -> MemoryBuilder {
        self.memory.precision = p;
        self
    }

    pub fn with_ip(mut self, ip: usize) -> MemoryBuilder {
        self.memory.ip = ip;
        self
    }

    pub fn build(self) -> Memory {
        self.memory
    }
}
