struct Chip8Registers {

}


impl Chip8Registers {
    pub fn tick(self: &Self) {
        println!("Ticking Registers");
    }
}

pub struct Chip8InstructionParameter {
   pub mask: u16
}

pub struct Chip8Instruction {
    pub id: String,
    pub mask: u16,
    pub pattern: u16,
    pub arguments: Vec<Chip8InstructionParameter>,
    pub description: Box<str>
}

pub fn fill_chip8_instructions() -> [Chip8Instruction; 34] {
    [
        Chip8Instruction {
            id: "SYS".to_string(),
            mask: 0x00,
            pattern: 0x00,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0FFF
                }
            ],
            description: "Execute method at address referenced by parameter".into()
        },
        Chip8Instruction {
            id: "CLR".to_string(),
            mask: 0x00E0,
            pattern: 0x00E0,
            arguments: vec![],
            description: "Clear the Screen".into()
 },
        Chip8Instruction {
            id: "RET".to_string(),
            mask: 0x00EE,
            pattern: 0x00EE,
            arguments: vec![],
            description: "Return from Subroutine".into()
        },
        Chip8Instruction {
            id: "JMP".to_string(),
            mask: 0x1FFF,
            pattern: 0x1000,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0fff
                }
            ],
            description: "Jump to specified location".into()
        },
        Chip8Instruction {
            id: "SEQ".to_string(),
            mask: 0x3FFF,
            pattern: 0x3000,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00ff
                }
            ],
            description: "Skip next instruction if Register does equal parameter".into()
        },
        Chip8Instruction {
            id: "SNE".to_string(),
            mask: 0x4FFF,
            pattern: 0x4000,
            arguments: vec! [
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00ff
                }
            ],
            description: "Skip next instruction if Register doesn't equal parameter".into()
        },
        Chip8Instruction {
            id: "SREQ".to_string(),
            mask: 0x5FF0,
            pattern: 0x5000,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00f0
                }
            ],
            description: "TBD".into()
        },
        Chip8Instruction {
            id: "STO".to_string(),
            mask: 0x6FFF,
            pattern: 0x6000,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00ff
                }
            ],
            description: "Store value into register".into()
        },
        Chip8Instruction {
            id: "ADD".to_string(),
            mask: 0x7FFF,
            pattern: 0x7000,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00ff
                }
            ],
            description: "Add value in register 0x0f00 with value 0x00ff".into()
        },
        Chip8Instruction {
            id: "CPY".to_string(),
            mask: 0x8FF0,
            pattern: 0x8000,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00f0
                }
            ],
            description: "Copy value between Register X and Y".into()
        },
        Chip8Instruction {
            id: "OR".to_string(),
            mask: 0x8FF1,
            pattern: 0x8001,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00f0
                }
            ],
            description: "Logical OR of registers placing result in first register".into()
        },
        Chip8Instruction {
            id: "AND".to_string(),
            mask: 0x8FF2,
            pattern: 0x8002,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00f0
                }
            ],
            description: "Logical AND of registers placing result in first register".into()
        },
        Chip8Instruction {
            id: "XOR".to_string(),
            mask: 0x8FF3,
            pattern: 0x8003,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00f0
                }
            ],
            description: "Logical XOR of registers placing result in first register".into()
        },
        Chip8Instruction {
            id: "ADC".to_string(),
            mask: 0x8FF4,
            pattern: 0x8004,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00f0
                }
            ],
            description: "Add 2 Registers with carry flag".into()
        },
        Chip8Instruction {
            id: "SUBC".to_string(),
            mask: 0x8FF5,
            pattern: 0x8005,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00f0
                }
            ],
            description: "Subtract 2 Registers with carry flag".into()
        },
        Chip8Instruction {
            id: "RSR".to_string(),
            mask: 0x8FF6,
            pattern: 0x8006,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00f0
                }
            ],
            description: "Register Shifted Right".into()
        },
        Chip8Instruction {
            id: "SUBC".to_string(),
            mask: 0x8FF7,
            pattern: 0x8007,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00f0
                }
            ],
            description: "Subtract 2 Regiters with Carry".into()
        },
        Chip8Instruction {
            id: "RSL".to_string(),
            mask: 0x8FFE,
            pattern: 0x800E,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00f0
                }
            ],
            description: "Register Shifted Left".into()
        },
        Chip8Instruction {
            id: "SRNE".to_string(),
            mask: 0x9FF0,
            pattern: 0x9000,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00f0
                }
            ],
            description: "Skip next instruction if registers not equal".into()
        },
        Chip8Instruction {
            id: "LDI".to_string(),
            mask: 0xAFFF,
            pattern: 0xA000,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0fff
                }
            ],
            description: "Load Data from Memory Address".into()
        },
        Chip8Instruction {
            id: "JMPI".to_string(),
            mask: 0xBFFF,
            pattern: 0xB000,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0fff
                }
            ],
            description: "Jump to Memory Address".into()
        },
        Chip8Instruction {
            id: "RNG".to_string(),
            mask: 0xCFFF,
            pattern: 0xC000,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00ff
                }
          ],
            description: "Random number Generator".into()
        },
        Chip8Instruction {
            id: "SPR".to_string(),
            mask: 0xDFFF,
            pattern: 0xD000,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                },
                Chip8InstructionParameter {
                    mask: 0x00f0
                },
                Chip8InstructionParameter {
                    mask: 0x000f
                }
                
            ],
            description: "TBD".into()
        },
        Chip8Instruction {
            id: "JNK".to_string(),
            mask: 0xEF9E,
            pattern: 0xE09E,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                }
            ],
            description: "Jump over next instruction if Key Pressed".into()
        },
        Chip8Instruction {
            id: "JKP".to_string(),
            mask: 0xEFA1,
            pattern: 0xE0A1,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                }
            ],
            description: "Jump over next instruction if Key Not Pressed".into()
        },
        Chip8Instruction {
            id: "SDT".to_string(),
            mask: 0xFF07,
            pattern: 0xF007,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0F00
                }
            ],
            description: "TBD".into()
        },
        Chip8Instruction {
            id: "WKP".to_string(),
            mask: 0xFF0A,
            pattern: 0xF00A,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                }
            ],
            description: "Wait for a Key to be pressed".into()
        },
        Chip8Instruction {
            id: "LDT".to_string(),
            mask: 0xFF15,
            pattern: 0xF015,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                }
            ],
            description: "Load Data Timer".into()
        },
        Chip8Instruction {
            id: "LST".to_string(),
            mask: 0xFF18,
            pattern: 0xF018,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                }
            ],
            description: "Load Sound Timer".into()
        },
        Chip8Instruction {
            id: "ADDI".to_string(),
            mask: 0xFF1E,
            pattern: 0xF01E,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                }
            ],
            description: "Add register with value at I".into()
        },
        Chip8Instruction {
            id: "SETI".to_string(),
            mask: 0xFF29,
            pattern: 0xF029,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                }
            ],
            description: "TBD".into()
        },
        Chip8Instruction{
            id: "BCD".to_string(),
            mask: 0xFF33,
            pattern: 0xF033,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                }
            ],
            description: "Binary Coded Decimal of register".into()
        },
        Chip8Instruction{
            id: "MSTO".to_string(),
            mask: 0xFF55,
            pattern: 0xF055,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                }
            ],
            description: "Store value in register X at offset I".into()
        },
        Chip8Instruction {
            id: "MLOAD".to_string(),
            mask: 0xFF65,
            pattern: 0xF065,
            arguments: vec![
                Chip8InstructionParameter {
                    mask: 0x0f00
                }
            ],
            description: "Load value into register X at offset I".into()
        }
    ]
}


struct Chip8System {

}

impl Chip8System {
    
}

trait CpuInstruction {
    fn execute(input: Chip8System) -> Chip8System;
}