namespace X86Disassembler.X86.Handlers;
/// 
/// Handler for Group 3 instructions (TEST, NOT, NEG, MUL, IMUL, DIV, IDIV)
/// 
public class Group3Handler : InstructionHandler
{
    /// 
    /// Initializes a new instance of the Group3Handler class
    /// 
    /// The buffer containing the code to decode
    /// The instruction decoder that owns this handler
    /// The length of the buffer
    public Group3Handler(byte[] codeBuffer, InstructionDecoder decoder, int length) 
        : base(codeBuffer, decoder, length)
    {
    }
    
    /// 
    /// Checks if this handler can decode the given opcode
    /// 
    /// The opcode to check
    /// True if this handler can decode the opcode
    public override bool CanHandle(byte opcode)
    {
        return OpcodeMap.IsGroup3Opcode(opcode);
    }
    
    /// 
    /// Decodes a Group 3 instruction
    /// 
    /// The opcode of the instruction
    /// The instruction object to populate
    /// True if the instruction was successfully decoded
    public override bool Decode(byte opcode, Instruction instruction)
    {
        int position = Decoder.GetPosition();
        
        if (position >= Length)
        {
            return false;
        }
        
        // Read the ModR/M byte
        var (mod, reg, rm, destOperand) = ModRMDecoder.ReadModRM();
        
        // Determine the operation based on reg field
        instruction.Mnemonic = OpcodeMap.Group3Operations[reg];
        
        // For TEST instruction (reg = 0), we need to read an immediate value
        if (reg == 0) // TEST
        {
            position = Decoder.GetPosition();
            string immOperand;
            
            switch (opcode)
            {
                case 0xF6: // 8-bit TEST
                    if (position < Length)
                    {
                        byte imm8 = CodeBuffer[position];
                        Decoder.SetPosition(position + 1);
                        immOperand = $"0x{imm8:X2}";
                    }
                    else
                    {
                        immOperand = "???";
                    }
                    break;
                    
                case 0xF7: // 32-bit TEST
                    if (position + 3 < Length)
                    {
                        uint imm32 = BitConverter.ToUInt32(CodeBuffer, position);
                        Decoder.SetPosition(position + 4);
                        immOperand = $"0x{imm32:X8}";
                    }
                    else
                    {
                        immOperand = "???";
                    }
                    break;
                    
                default:
                    return false;
            }
            
            // Set the operands
            instruction.Operands = $"{destOperand}, {immOperand}";
        }
        else
        {
            // For other Group 3 instructions (NOT, NEG, MUL, etc.), there's only one operand
            instruction.Operands = destOperand;
        }
        
        return true;
    }
}