package ai.decompile.analysis.service.parser;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class TurboDumpParserTest {

  private final TurboDumpParser parser = new TurboDumpParser();

  @Test
  void shouldReturnFormatName() {
    assertEquals("TURBO_DUMP", parser.getFormatName());
  }

  @Test
  void shouldRecognizeTurboDumpContent() {
    assertTrue(parser.canParse("Turbo Dump Version 5.0.13.1\nMSLIBR Index begins at file offset"));
  }

  @Test
  void shouldRejectNonTurboDumpContent() {
    assertFalse(parser.canParse("some random text"));
    assertFalse(parser.canParse(null));
    assertFalse(parser.canParse(""));
  }

  @Test
  void shouldParseConstructor() {
    var content =
        """
        Turbo Dump  Version 5.0.13.1 Copyright (c) 1988, 1997 Borland International
                             Display of File OWLWI.LIB

        000000 MSLIBR Index begins at file offset 7ee00. Index is 521 blocks.
            Library Page size is 32 bytes.

        000020 THEADR  TAppDictionary::TAppDictionary()
        00003E COMENT  Purge: Yes, List: Yes, Class: 160 (0A0h)
            Dynamic link import (IMPDEF)
              Imported by: ordinal
              Internal Name: TAppDictionary::TAppDictionary()
              Module Name: Owl252
              ordinal: 2
        000069 MODEND
        """;

    var symbols = parser.parse(content);

    assertEquals(1, symbols.size());
    var sym = symbols.get(0);
    assertEquals("Owl252", sym.moduleName());
    assertEquals("TAppDictionary", sym.className());
    assertEquals("TAppDictionary::TAppDictionary()", sym.symbolName());
    assertEquals(2, sym.ordinal());
    assertEquals("CONSTRUCTOR", sym.symbolType());
    assertEquals("Core/Application", sym.category());
  }

  @Test
  void shouldParseDestructor() {
    var content =
        """
        Turbo Dump  Version 5.0
                            Display of File OWLWI.LIB
        000000 MSLIBR Index begins at file offset 7ee00.
        000080 THEADR  TAppDictionary::~TAppDictionary()
        00009E COMENT  Purge: Yes, List: Yes, Class: 160 (0A0h)
            Dynamic link import (IMPDEF)
              Imported by: ordinal
              Internal Name: TAppDictionary::~TAppDictionary()
              Module Name: Owl252
              ordinal: 3
        0000C9 MODEND
        """;

    var symbols = parser.parse(content);

    assertEquals(1, symbols.size());
    assertEquals("DESTRUCTOR", symbols.get(0).symbolType());
    assertEquals("TAppDictionary", symbols.get(0).className());
    assertEquals(3, symbols.get(0).ordinal());
  }

  @Test
  void shouldParseMethodWithParameters() {
    var content =
        """
        Turbo Dump  Version 5.0
                            Display of File OWLWI.LIB
        000000 MSLIBR Index begins at file offset 7ee00.
        0000E0 THEADR  TDC::SelectObject(const TPen*)
        0000F0 COMENT  Purge: Yes, List: Yes, Class: 160 (0A0h)
            Dynamic link import (IMPDEF)
              Imported by: ordinal
              Internal Name: TDC::SelectObject(const TPen*)
              Module Name: Owl252
              ordinal: 178
        000120 MODEND
        """;

    var symbols = parser.parse(content);

    assertEquals(1, symbols.size());
    assertEquals("METHOD", symbols.get(0).symbolType());
    assertEquals("TDC", symbols.get(0).className());
    assertEquals("const TPen*", symbols.get(0).parameters());
    assertEquals(178, symbols.get(0).ordinal());
    assertEquals("Graphics/DC", symbols.get(0).category());
  }

  @Test
  void shouldParseMethodWithoutParameters() {
    var content =
        """
        Turbo Dump  Version 5.0
                            Display of File OWLWI.LIB
        000000 MSLIBR Index begins at file offset 7ee00.
        0001E0 THEADR  TBitSet::IsEmpty()
        0001F0 COMENT  Purge: Yes, List: Yes, Class: 160 (0A0h)
            Dynamic link import (IMPDEF)
              Imported by: ordinal
              Internal Name: TBitSet::IsEmpty()
              Module Name: Owl252
              ordinal: 47
        000220 MODEND
        """;

    var symbols = parser.parse(content);

    assertEquals(1, symbols.size());
    assertEquals("METHOD", symbols.get(0).symbolType());
    assertNull(symbols.get(0).parameters());
    assertEquals("TBitSet", symbols.get(0).className());
    assertEquals("Core/DataTypes", symbols.get(0).category());
  }

  @Test
  void shouldParseFreeFunction() {
    var content =
        """
        Turbo Dump  Version 5.0
                            Display of File OWLWI.LIB
        000000 MSLIBR Index begins at file offset 7ee00.
        000360 THEADR  NColors(unsigned short)
        000370 COMENT  Purge: Yes, List: Yes, Class: 160 (0A0h)
            Dynamic link import (IMPDEF)
              Imported by: ordinal
              Internal Name: NColors(unsigned short)
              Module Name: Owl252
              ordinal: 123
        000390 MODEND
        """;

    var symbols = parser.parse(content);

    assertEquals(1, symbols.size());
    assertEquals("FUNCTION", symbols.get(0).symbolType());
    assertNull(symbols.get(0).className());
    assertEquals("unsigned short", symbols.get(0).parameters());
    assertEquals("Graphics/Utility", symbols.get(0).category());
  }

  @Test
  void shouldParseMultipleEntries() {
    var content =
        """
        Turbo Dump  Version 5.0
                            Display of File OWLWI.LIB
        000000 MSLIBR Index begins at file offset 7ee00.

        000020 THEADR  TAppDictionary::TAppDictionary()
        00003E COMENT  Purge: Yes, List: Yes, Class: 160 (0A0h)
            Dynamic link import (IMPDEF)
              Imported by: ordinal
              Internal Name: TAppDictionary::TAppDictionary()
              Module Name: Owl252
              ordinal: 2
        000069 MODEND

        ===============

        000080 THEADR  TBitmap::Width() const
        00009E COMENT  Purge: Yes, List: Yes, Class: 160 (0A0h)
            Dynamic link import (IMPDEF)
              Imported by: ordinal
              Internal Name: TBitmap::Width() const
              Module Name: Owl252
              ordinal: 23
        0000C9 MODEND

        ===============

        0000E0 THEADR  TButtonGadget::Paint(TDC*)
        0000FE COMENT  Purge: Yes, List: Yes, Class: 160 (0A0h)
            Dynamic link import (IMPDEF)
              Imported by: ordinal
              Internal Name: TButtonGadget::Paint(TDC*)
              Module Name: Owl252
              ordinal: 75
        00012D MODEND
        """;

    var symbols = parser.parse(content);

    assertEquals(3, symbols.size());
    assertEquals("CONSTRUCTOR", symbols.get(0).symbolType());
    assertEquals("METHOD", symbols.get(1).symbolType());
    assertEquals("METHOD", symbols.get(2).symbolType());
    assertEquals(75, symbols.get(2).ordinal());
    assertEquals("TButtonGadget", symbols.get(2).className());
    assertEquals("TDC*", symbols.get(2).parameters());
  }

  @Test
  void shouldIgnoreNonImportedEntries() {
    var content =
        """
        Turbo Dump  Version 5.0
                            Display of File OWLWI.LIB
        000000 MSLIBR Index begins at file offset 7ee00.

        000020 THEADR  SomeDataVariable
        000030 COMENT  Purge: Yes, List: Yes, Class: 160 (0A0h)
            Not a dynamic link import
        000050 MODEND

        ===============

        000060 THEADR  TBrush::TBrush(TColor)
        00007E COMENT  Purge: Yes, List: Yes, Class: 160 (0A0h)
            Dynamic link import (IMPDEF)
              Imported by: ordinal
              Internal Name: TBrush::TBrush(TColor)
              Module Name: Owl252
              ordinal: 53
        0000B0 MODEND
        """;

    var symbols = parser.parse(content);

    assertEquals(1, symbols.size());
    assertEquals(53, symbols.get(0).ordinal());
  }

  @Test
  void shouldReturnEmptyForBlankInput() {
    assertTrue(parser.parse("").isEmpty());
    assertTrue(parser.parse(null).isEmpty());
  }

  @Test
  void shouldParseClassPrefixCategoryTFrameWindow() {
    var content =
        """
        Turbo Dump  Version 5.0
                            Display of File OWLWI.LIB
        000000 MSLIBR Index begins at file offset 7ee00.
        000020 THEADR  TFrameWindow::TFrameWindow()
        00003E COMENT  Purge: Yes, List: Yes, Class: 160 (0A0h)
            Dynamic link import (IMPDEF)
              Imported by: ordinal
              Internal Name: TFrameWindow::TFrameWindow()
              Module Name: Owl252
              ordinal: 200
        000069 MODEND
        """;

    var symbols = parser.parse(content);

    assertEquals("UI/Window", symbols.get(0).category());
  }

  @Test
  void shouldParseClassPrefixCategoryTDialog() {
    var content =
        """
        Turbo Dump  Version 5.0
                            Display of File OWLWI.LIB
        000000 MSLIBR Index begins at file offset 7ee00.
        000020 THEADR  TChooseColorDialog::DoExecute()
        00003E COMENT  Purge: Yes, List: Yes, Class: 160 (0A0h)
            Dynamic link import (IMPDEF)
              Imported by: ordinal
              Internal Name: TChooseColorDialog::DoExecute()
              Module Name: Owl252
              ordinal: 100
        000069 MODEND
        """;

    var symbols = parser.parse(content);

    assertEquals("UI/Dialog", symbols.get(0).category());
  }
}
