using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Lomont.Binary.X86
{
    // todo - add HasModRM to this, dynamically create it on load to speed up other processing.
    // todo - for each operand type, run through the decode operand process to ensure all works
    // Items	MNENOMIC	Prefix	0F	Opcode	Secondary	Extension	Dst	Src	Ring	CPUs	REX	Next(s)	Lockable	OpMode	FeatureSet
    
    /// <summary>
    /// Represent an Intel x86 or x64 instruction definition.
    /// </summary>
    sealed public class X86InstructionDefinition
    {
        // todo - label these, export into Instruction for context.
        // direct reads
        // todo - make extension sets, etc, match those exported from CPUID stuff, and then match CPUs to instruction sets 

        /// <summary>
        /// The instruction mnemonic
        /// </summary>
        public X86Mnemonic Mnenomic;
        /// <summary>
        /// null if no prefix, else the prefix.
        /// </summary>
        public byte? Prefix;
        /// <summary>
        /// Does the opcode use the 0F byte?
        /// </summary>
        public byte? OF;
        /// <summary>
        /// The primary opcode byte. Every opcode should have one.
        /// </summary>
        public byte? PrimaryOpcode;
        /// <summary>
        /// The secondary opcode byte if present.
        /// </summary>
        public byte? SecondaryOpcode;
        /// <summary>
        /// Does the instruction depend on the value of the mod field? 
        /// If true, the instruction requires mod value to be 3. If false, cannot have mod value 3.
        /// If not present, then does not matter.
        /// </summary>
        public bool? Mod3;
        /// <summary>
        /// The total length of the opcode (minus any internal REX byte or ModR/M byte).
        /// </summary>
        public int OpcodeLength;
        /// <summary>
        /// The extension 0-7 if present. Stored in bits 5,4,3 of the ModR/M byte
        /// </summary>
        public byte? Extension;
        /// <summary>
        /// The R/M field of the ModR/M byte if needed to decode opcode.
        /// </summary>
        public byte? RM;
        /// <summary>
        /// The instruction set extension adding this instruction.
        /// </summary>
        public string FeatureSet;
        /// <summary>
        /// The destination operand definition string.
        /// </summary>
        public string Dst;
        /// <summary>
        /// The source operand definition string.
        /// </summary>
        public string Src;
        /// <summary>
        /// An optional 3rd operand.
        /// </summary>
        public string Op3;
        /// <summary>
        /// The ring 0-3 needed for this instruction. 
        /// Set to Int32.MinValue if flag dependent.
        /// </summary>
        public int Ring;
        /// <summary>
        /// The range of CPUs this instruction is present on.
        /// TODO - make bitfields? or instruction set flags?
        /// </summary>
        public string Cpus;
        /// <summary>
        /// Does this instruction use a REX byte. TODO - perhaps can be removed
        /// </summary>
        public byte? REX;
        
        /// <summary>
        /// Represent the flow of instructions, through branches, jumps, returns, 
        /// and normal (next only) locations.
        /// </summary>
        public enum BranchType {
            /// <summary>
            /// Unknown outcome of instruction
            /// </summary>
            Unknown,
            /// <summary>
            /// The next address will be the next instruction 
            /// </summary>
            Normal,
            /// <summary>
            /// The next instruction follows an unconditional jump.
            /// </summary>
            Jump,
            /// <summary>
            /// The next address as well as the target of the branch should
            /// be valid instructions.
            /// </summary>
            Split,
            /// <summary>
            /// The instruction performs a return, so there is no next instruction
            /// knowable from this one.
            /// </summary>
            Return
        };
        /// <summary>
        /// The number of instructions possible after this one.
        /// </summary>
        public BranchType Next;

        /// <summary>
        /// Does this instruction allow LOCK?
        /// </summary>
        public bool Lockable;
        
        /// <summary>
        /// Mode needed to run: real, protected, 64 bit, etc. TODO
        /// </summary>
        public string OpModes;

        /// <summary>
        /// Simple method to view the definition.
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return Mnenomic.ToString();
        }

        /// <summary>
        /// Is this instruction documented?
        /// </summary>
        public bool IsDocumented { get; set; }
        
        /// <summary>
        /// Unique index into instruction table
        /// </summary>
        public int Index { get; set; }
    }
}
