from __future__ import annotations
import collections.abc
import datetime
import typing
from warnings import deprecated # type: ignore

import jpype # type: ignore
import jpype.protocol # type: ignore

import ghidra.app.util.bin
import ghidra.app.util.bin.format.dwarf
import ghidra.app.util.bin.format.dwarf.attribs
import java.io # type: ignore
import java.lang # type: ignore
import java.util # type: ignore


class DWARFLineProgramState(java.lang.Object):

    class_: typing.ClassVar[java.lang.Class]
    address: jpype.JLong
    """
    The program-counter value corresponding to a machine instruction
    generated by the compiler.
    """

    file: jpype.JInt
    """
    An unsigned integer indicating the identity of the source file
    corresponding to a machine instruction.
    """

    line: jpype.JInt
    """
    An unsigned integer indicating a source line number. Lines are
    numbered beginning at 1. The compiler may emit the value 0 in cases
    where an instruction cannot be attributed to any source line.
    """

    column: jpype.JInt
    """
    An unsigned integer indicating a column number within a source line.
    Columns are numbered beginning at 1. The value 0 is reserved to
    indicate that a statement begins at the ??left edge?? of the line.
    """

    isStatement: jpype.JBoolean
    """
    A boolean indicating that the current instruction is the beginning of a
    statement.
    """

    isBasicBlock: jpype.JBoolean
    """
    A boolean indicating that the current instruction is the beginning of a
    basic block.
    """

    isEndSequence: jpype.JBoolean
    """
    A boolean indicating that the current address is that of the first byte after
    the end of a sequence of target machine instructions.
    """

    prologueEnd: jpype.JBoolean
    epilogueBegin: jpype.JBoolean
    isa: jpype.JLong
    discriminator: jpype.JLong

    @typing.overload
    def __init__(self, defaultIsStatement: typing.Union[jpype.JBoolean, bool]):
        ...

    @typing.overload
    def __init__(self, other: DWARFLineProgramState):
        ...

    def isSameFileLine(self, other: DWARFLineProgramState) -> bool:
        ...

    @property
    def sameFileLine(self) -> jpype.JBoolean:
        ...


class DWARFLineNumberStandardOpcodes(java.lang.Object):

    class_: typing.ClassVar[java.lang.Class]
    DW_LNS_copy: typing.Final = 1
    DW_LNS_advance_pc: typing.Final = 2
    DW_LNS_advance_line: typing.Final = 3
    DW_LNS_set_file: typing.Final = 4
    DW_LNS_set_column: typing.Final = 5
    DW_LNS_negate_statement: typing.Final = 6
    DW_LNS_set_basic_block: typing.Final = 7
    DW_LNS_const_add_pc: typing.Final = 8
    DW_LNS_fixed_advanced_pc: typing.Final = 9
    DW_LNS_set_prologue_end: typing.Final = 10
    DW_LNS_set_epilog_begin: typing.Final = 11
    DW_LNS_set_isa: typing.Final = 12

    def __init__(self):
        ...

    @staticmethod
    def toString(value: typing.Union[jpype.JInt, int]) -> str:
        ...


class DWARFLineNumberExtendedOpcodes(java.lang.Object):

    class_: typing.ClassVar[java.lang.Class]
    DW_LNE_end_sequence: typing.Final = 1
    DW_LNE_set_address: typing.Final = 2
    DW_LNE_define_file: typing.Final = 3
    DW_LNE_set_discriminator: typing.Final = 4
    DW_LNE_lo_user: typing.Final = 128
    DW_LNE_hi_user: typing.Final = 255

    def __init__(self):
        ...

    @staticmethod
    def toString(value: typing.Union[jpype.JInt, int]) -> str:
        ...


class DWARFLineProgramExecutor(java.io.Closeable):
    """
    Handles executing, step-by-step, the address-to-sourcefile mapping instructions found at the
    end of a DWARFLine structure.
    """

    class_: typing.ClassVar[java.lang.Class]

    def __init__(self, reader: ghidra.app.util.bin.BinaryReader, streamEnd: typing.Union[jpype.JLong, int], pointerSize: typing.Union[jpype.JInt, int], opcodeBase: typing.Union[jpype.JInt, int], lineBase: typing.Union[jpype.JInt, int], lineRange: typing.Union[jpype.JInt, int], minInstrLen: typing.Union[jpype.JInt, int], defaultIsStatement: typing.Union[jpype.JBoolean, bool]):
        ...

    def allRows(self) -> java.util.List[DWARFLineProgramState]:
        ...

    def currentState(self) -> DWARFLineProgramState:
        ...

    def hasNext(self) -> bool:
        ...

    def nextRow(self) -> DWARFLineProgramState:
        ...

    def step(self) -> DWARFLineProgramInstruction:
        """
        Read the next instruction and executes it
        
        :return: 
        :rtype: DWARFLineProgramInstruction
        :raises IOException: if an i/o error occurs
        """


class DWARFLineContentType(java.lang.Enum[DWARFLineContentType]):
    """
    Represents an identifier of a value in a DWARFLine/DWARFFile object.
     
    
    Similar to the :obj:`DWARFAttribute` enum, both are identifiers of an attribute value 
    that is serialized by a DWARFForm.
     
    
    Users of this enum should be tolerant of unknown values.
    """

    class Def(ghidra.app.util.bin.format.dwarf.attribs.DWARFAttributeDef[DWARFLineContentType]):
        """
        Defines a :obj:`DWARFLineContentType` attribute value.
        """

        class_: typing.ClassVar[java.lang.Class]

        def __init__(self, attributeId: DWARFLineContentType, rawAttributeId: typing.Union[jpype.JInt, int], attributeForm: ghidra.app.util.bin.format.dwarf.attribs.DWARFForm, implicitValue: typing.Union[jpype.JLong, int]):
            ...

        def getId(self) -> DWARFLineContentType:
            ...

        @staticmethod
        def read(reader: ghidra.app.util.bin.BinaryReader) -> DWARFLineContentType.Def:
            """
            Reads a :obj:`DWARFLineContentType.Def` instance from the :obj:`reader <BinaryReader>`.
             
            
            Returns a null if its a end-of-list marker.
            
            :param ghidra.app.util.bin.BinaryReader reader: :obj:`BinaryReader` stream
            :return: :obj:`DWARFLineContentType.Def`, or null if stream was at a end-of-list marker
            (which isn't really a thing for line content defs, but is a thing for attribute defs)
            :rtype: DWARFLineContentType.Def
            :raises IOException: if error reading
            """

        @property
        def id(self) -> DWARFLineContentType:
            ...


    class_: typing.ClassVar[java.lang.Class]
    DW_LNCT_path: typing.Final[DWARFLineContentType]
    DW_LNCT_directory_index: typing.Final[DWARFLineContentType]
    DW_LNCT_timestamp: typing.Final[DWARFLineContentType]
    DW_LNCT_size: typing.Final[DWARFLineContentType]
    DW_LNCT_MD5: typing.Final[DWARFLineContentType]
    DW_LNCT_lo_user: typing.Final[DWARFLineContentType]
    DW_LNCT_hi_user: typing.Final[DWARFLineContentType]
    DW_LNCT_UNKNOWN: typing.Final[DWARFLineContentType]

    @staticmethod
    def of(id: typing.Union[jpype.JInt, int]) -> DWARFLineContentType:
        ...

    @staticmethod
    def valueOf(name: typing.Union[java.lang.String, str]) -> DWARFLineContentType:
        ...

    @staticmethod
    def values() -> jpype.JArray[DWARFLineContentType]:
        ...


class DWARFLineProgramInstruction(java.lang.Record):

    class_: typing.ClassVar[java.lang.Class]

    def __init__(self, offset: typing.Union[jpype.JLong, int], instr: typing.Union[java.lang.String, str], operands: java.util.List[java.lang.Number], row: DWARFLineProgramState):
        ...

    def equals(self, o: java.lang.Object) -> bool:
        ...

    def getDesc(self) -> str:
        ...

    def hashCode(self) -> int:
        ...

    def instr(self) -> str:
        ...

    def offset(self) -> int:
        ...

    def operands(self) -> java.util.List[java.lang.Number]:
        ...

    def row(self) -> DWARFLineProgramState:
        ...

    def toString(self) -> str:
        ...

    @property
    def desc(self) -> java.lang.String:
        ...


class DWARFLineException(java.io.IOException):

    class_: typing.ClassVar[java.lang.Class]

    @typing.overload
    def __init__(self):
        ...

    @typing.overload
    def __init__(self, message: typing.Union[java.lang.String, str]):
        ...

    @typing.overload
    def __init__(self, cause: java.lang.Throwable):
        ...

    @typing.overload
    def __init__(self, message: typing.Union[java.lang.String, str], cause: java.lang.Throwable):
        ...


class DWARFLine(java.lang.Object):
    """
    A structure read from .debug_line, contains indexed source filenames as well as a mapping between
    addresses and source filename and linenumbers.
     
    
    TODO: refactor this and other similar classes to derive from DWARFUnitHeader and simplify
    """

    @typing.type_check_only
    class DirectoryEntryFormat(java.lang.Record):

        class_: typing.ClassVar[java.lang.Class]

        def contentTypeCode(self) -> int:
            ...

        def equals(self, o: java.lang.Object) -> bool:
            ...

        def formCode(self) -> int:
            ...

        def hashCode(self) -> int:
            ...

        def toString(self) -> str:
            ...


    class SourceFileInfo(java.lang.Record):

        class_: typing.ClassVar[java.lang.Class]

        def __init__(self, filePath: typing.Union[java.lang.String, str], md5: jpype.JArray[jpype.JByte]):
            ...

        def equals(self, o: java.lang.Object) -> bool:
            ...

        def filePath(self) -> str:
            ...

        def hashCode(self) -> int:
            ...

        def md5(self) -> jpype.JArray[jpype.JByte]:
            ...

        def toString(self) -> str:
            ...


    class SourceFileAddr(java.lang.Record):

        class_: typing.ClassVar[java.lang.Class]

        def __init__(self, address: typing.Union[jpype.JLong, int], fileName: typing.Union[java.lang.String, str], md5: jpype.JArray[jpype.JByte], lineNum: typing.Union[jpype.JInt, int], isEndSequence: typing.Union[jpype.JBoolean, bool]):
            ...

        def address(self) -> int:
            ...

        def equals(self, o: java.lang.Object) -> bool:
            ...

        def fileName(self) -> str:
            ...

        def hashCode(self) -> int:
            ...

        def isEndSequence(self) -> bool:
            ...

        def lineNum(self) -> int:
            ...

        def md5(self) -> jpype.JArray[jpype.JByte]:
            ...

        def toString(self) -> str:
            ...

        @property
        def endSequence(self) -> jpype.JBoolean:
            ...


    class_: typing.ClassVar[java.lang.Class]

    @staticmethod
    def empty() -> DWARFLine:
        """
        Returns a dummy DWARFLine instance that contains no information.
        
        :return: :obj:`DWARFLine` instance with no info
        :rtype: DWARFLine
        """

    def getAllSourceFileAddrInfo(self, cu: ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit, reader: ghidra.app.util.bin.BinaryReader) -> java.util.List[DWARFLine.SourceFileAddr]:
        ...

    def getAllSourceFileInfos(self) -> java.util.List[DWARFLine.SourceFileInfo]:
        ...

    def getDir(self, index: typing.Union[jpype.JInt, int]) -> DWARFFile:
        ...

    def getEndOffset(self) -> int:
        ...

    def getFile(self, index: typing.Union[jpype.JInt, int]) -> DWARFFile:
        """
        Get a file name given a file index.
        
        :param jpype.JInt or int index: index of the file, where index may not be zero based depending on dwarf version
        :return: file :obj:`DWARFFile`
        :rtype: DWARFFile
        :raises IOException: if invalid index
        """

    def getLineProgramexecutor(self, cu: ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit, reader: ghidra.app.util.bin.BinaryReader) -> DWARFLineProgramExecutor:
        ...

    def getStartOffset(self) -> int:
        ...

    @staticmethod
    def read(reader: ghidra.app.util.bin.BinaryReader, defaultIntSize: typing.Union[jpype.JInt, int], cu: ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit) -> DWARFLine:
        ...

    @property
    def endOffset(self) -> jpype.JLong:
        ...

    @property
    def startOffset(self) -> jpype.JLong:
        ...

    @property
    def file(self) -> DWARFFile:
        ...

    @property
    def allSourceFileInfos(self) -> java.util.List[DWARFLine.SourceFileInfo]:
        ...

    @property
    def dir(self) -> DWARFFile:
        ...


class DWARFFile(java.lang.Object):
    """
    DWARFFile is used to store file or directory entries in the DWARFLine.
    """

    class_: typing.ClassVar[java.lang.Class]

    @typing.overload
    def __init__(self, name: typing.Union[java.lang.String, str]):
        ...

    @typing.overload
    def __init__(self, name: typing.Union[java.lang.String, str], directory_index: typing.Union[jpype.JInt, int], modification_time: typing.Union[jpype.JLong, int], length: typing.Union[jpype.JLong, int], md5: jpype.JArray[jpype.JByte]):
        """
        Create a new DWARF file entry with the given parameters.
        
        :param java.lang.String or str name: name of the file
        :param jpype.JInt or int directory_index: index of the directory for this file
        :param jpype.JLong or int modification_time: modification time of the file
        :param jpype.JLong or int length: length of the file
        :param jpype.JArray[jpype.JByte] md5: bytes of md5 hash
        """

    def getDirectoryIndex(self) -> int:
        ...

    def getMD5(self) -> jpype.JArray[jpype.JByte]:
        ...

    def getModificationTime(self) -> int:
        ...

    def getName(self) -> str:
        ...

    def getPathName(self, parentLine: DWARFLine) -> str:
        ...

    @staticmethod
    def readV4(reader: ghidra.app.util.bin.BinaryReader, cu: ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit) -> DWARFFile:
        """
        Reads a DWARFFile entry.
        
        :param ghidra.app.util.bin.BinaryReader reader: BinaryReader
        :param ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit cu: :obj:`DWARFCompilationUnit`
        :return: new DWARFFile, or null if end-of-list was found
        :rtype: DWARFFile
        :raises IOException: if error reading
        """

    @staticmethod
    def readV5(reader: ghidra.app.util.bin.BinaryReader, defs: java.util.List[DWARFLineContentType.Def], dwarfIntSize: typing.Union[jpype.JInt, int], cu: ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit) -> DWARFFile:
        """
        Reads a DWARFFile entry.
        
        :param ghidra.app.util.bin.BinaryReader reader: BinaryReader
        :param java.util.List[DWARFLineContentType.Def] defs: similar to a DIE's attributespec, a list of DWARFForms that define how values
        will be deserialized from the stream
        :param jpype.JInt or int dwarfIntSize: size of serialized dwarf ints (might be different than the CU's dwarfIntSize)
        :param ghidra.app.util.bin.format.dwarf.DWARFCompilationUnit cu: :obj:`DWARFCompilationUnit`
        :return: new DWARFFile
        :rtype: DWARFFile
        :raises IOException: if error reading
        """

    def withName(self, newName: typing.Union[java.lang.String, str]) -> DWARFFile:
        ...

    @property
    def pathName(self) -> java.lang.String:
        ...

    @property
    def modificationTime(self) -> jpype.JLong:
        ...

    @property
    def name(self) -> java.lang.String:
        ...

    @property
    def directoryIndex(self) -> jpype.JInt:
        ...

    @property
    def mD5(self) -> jpype.JArray[jpype.JByte]:
        ...



__all__ = ["DWARFLineProgramState", "DWARFLineNumberStandardOpcodes", "DWARFLineNumberExtendedOpcodes", "DWARFLineProgramExecutor", "DWARFLineContentType", "DWARFLineProgramInstruction", "DWARFLineException", "DWARFLine", "DWARFFile"]
