import unittest

from h8536.lcd_driver import analyze_lcd_driver, lcd_comment_for_instruction
from h8536.model import Instruction


class LcdDriverTest(unittest.TestCase):
    def test_detects_e_clock_lcd_accesses_and_busy_poll_loop(self):
        instructions = {
            0x3F4A: Instruction(
                0x3F4A,
                b"\x15\xF2\x00\x00\x80",
                "MOVFPE.B",
                "@H'F200, R0",
                references=[0xF200],
            ),
            0x3F4F: Instruction(0x3F4F, b"\xA0\xF7", "BTST.B", "#7, R0"),
            0x3F51: Instruction(0x3F51, b"\x26\xF7", "BNE", "loc_3F4A", kind="branch", targets=[0x3F4A]),
            0x3F53: Instruction(0x3F53, b"\x15\xF2\x00\x00\x94", "MOVTPE.B", "R4, @H'F200", references=[0xF200]),
            0x3F58: Instruction(0x3F58, b"\x15\xF2\x01\x00\x94", "MOVTPE.B", "R4, @H'F201", references=[0xF201]),
            0x3F5D: Instruction(0x3F5D, b"\x19", "RTS", kind="return", fallthrough=False),
        }

        analysis = analyze_lcd_driver(instructions)

        self.assertEqual(len(analysis["accesses"]), 3)
        self.assertEqual(analysis["polling_loops"][0]["read_address"], 0x3F4A)
        self.assertEqual(analysis["routines"][0]["role_hint"], "lcd_wait_and_transfer")
        self.assertIn("LCD busy-flag poll", lcd_comment_for_instruction(analysis, 0x3F51))
        self.assertIn("LCD data write", lcd_comment_for_instruction(analysis, 0x3F58))

    def test_regex_fallback_detects_operands_without_references(self):
        instructions = {
            0x0100: Instruction(0x0100, b"", "MOVTPE.B", "R1, @H'F201"),
        }

        analysis = analyze_lcd_driver(instructions)

        self.assertEqual(analysis["accesses"][0]["lcd_address"], 0xF201)
        self.assertEqual(analysis["accesses"][0]["role"], "lcd_data_write")


if __name__ == "__main__":
    unittest.main()
