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.xml
import java.io # type: ignore
import java.lang # type: ignore


class LSHVectorFactory(java.lang.Object):

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

    def __init__(self):
        ...

    def buildVector(self, feature: jpype.JArray[jpype.JInt]) -> LSHVector:
        """
        Generate an LSHVector from a feature set, individual features are integer hashes.
        The integers MUST already be sorted.
        The same integer can occur more than once in the array (term frequency (TF) > 1).
        The factory decides internally how to create weights based on term frequency and any
        knowledge of Inverse Document Frequency (IDF)
        
        :param jpype.JArray[jpype.JInt] feature: is the sorted array of integer features
        :return: the newly minted LSHVector
        :rtype: LSHVector
        """

    def buildZeroVector(self) -> LSHVector:
        """
        Generate vector with all coefficients zero.
        
        :return: the zero vector
        :rtype: LSHVector
        """

    def calculateSignificance(self, data: VectorCompare) -> float:
        """
        Given comparison data generated by the LSHVector.compare() method,
        calculate the significance of any similarity between the two vectors,
        normalized for this factory's specific weight settings
        
        :param VectorCompare data: is the comparison object produced when comparing two LSHVectors
        :return: the significance score
        :rtype: float
        """

    def getSelfSignificance(self, vector: LSHVector) -> float:
        """
        Calculate a vector's significance as compared to itself, normalized for this factory's specific weight settings
        
        :param LSHVector vector: is the LSHVector
        :return: the vector's significance score
        :rtype: float
        """

    def getSettings(self) -> int:
        """
        
        
        :return: settings ID used to generate factory's current weights
        :rtype: int
        """

    def getSignificanceAddend(self) -> float:
        """
        
        
        :return: the weighttable's significance addend for this factory
        :rtype: float
        """

    def getSignificanceScale(self) -> float:
        """
        
        
        :return: the weighttable's significance scale for this factory
        :rtype: float
        """

    def isLoaded(self) -> bool:
        """
        
        
        :return: true if this factory has weights and lookup loaded
        :rtype: bool
        """

    def readWeights(self, parser: ghidra.xml.XmlPullParser):
        """
        Read both the weights and the lookup hashes from an XML stream
        
        :param ghidra.xml.XmlPullParser parser: is the XML parser
        :raises SAXException:
        """

    def restoreVectorFromSql(self, sql: typing.Union[java.lang.String, str]) -> LSHVector:
        """
        Generate an LSHVector based on string returned from SQL query
        Factory generates weights based on term frequency info in the string and its internal IDF knowledge
        
        :param java.lang.String or str sql: is the column data string returned by an SQL query
        :return: the newly minted LSHVector
        :rtype: LSHVector
        :raises IOException:
        """

    def restoreVectorFromXml(self, parser: ghidra.xml.XmlPullParser) -> LSHVector:
        """
        Generate an LSHVector based on XML tag seen by pull parser.
        Factory generates weights based on term frequency info in the XML tag and its internal IDF knowledge
        
        :param ghidra.xml.XmlPullParser parser: is the XML parser
        :return: the newly minted LSHVector
        :rtype: LSHVector
        """

    def set(self, wFactory: WeightFactory, iLookup: IDFLookup, settings: typing.Union[jpype.JInt, int]):
        """
        Load the factory with weights and the feature map
        
        :param WeightFactory wFactory: is the weight table of IDF and TF weights
        :param IDFLookup iLookup: is the map from features int the weight table
        :param jpype.JInt or int settings: is an integer id for this particular weighting scheme
        """

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

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

    @property
    def selfSignificance(self) -> jpype.JDouble:
        ...

    @property
    def significanceScale(self) -> jpype.JDouble:
        ...

    @property
    def significanceAddend(self) -> jpype.JDouble:
        ...


class IDFLookup(java.lang.Object):

    class IDFEntry(java.lang.Object):

        class_: typing.ClassVar[java.lang.Class]
        hash: jpype.JInt
        count: jpype.JInt

        def __init__(self):
            ...


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

    def __init__(self):
        ...

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

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

    def getCount(self, hash: typing.Union[jpype.JInt, int]) -> int:
        ...

    def getRawCount(self, pos: typing.Union[jpype.JInt, int]) -> int:
        ...

    def getRawHash(self, pos: typing.Union[jpype.JInt, int]) -> int:
        ...

    def restoreXml(self, parser: ghidra.xml.XmlPullParser):
        ...

    def saveXml(self, fwrite: java.io.Writer):
        ...

    def set(self, hashCountPair: jpype.JArray[jpype.JInt]):
        """
        Set from an array of hash/count pairs.  Every even index is a hash, every odd index is a count
        
        :param jpype.JArray[jpype.JInt] hashCountPair: is the pair array
        """

    def toArray(self) -> jpype.JArray[jpype.JInt]:
        """
        Collapse IDFLookup into an int array, suitable for storage
        
        :return: int[]
        :rtype: jpype.JArray[jpype.JInt]
        """

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

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

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

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


class LSHCosineVectorAccum(LSHCosineVector):
    """
    A cosine vector where we can accumulate the (feature,weight) pairs over time
    using the addHash method.   Once either the getLength or compare methods is
    called the vector becomes "finalized" and acts as an ordinary LSHCosineVector
    """

    class Entry(java.lang.Comparable[LSHCosineVectorAccum.Entry]):

        class_: typing.ClassVar[java.lang.Class]
        hash: typing.Final[jpype.JInt]
        weight: typing.Final[jpype.JDouble]

        def __init__(self, hash: typing.Union[jpype.JInt, int], weight: typing.Union[jpype.JDouble, float]):
            ...

        def compareTo(self, o: LSHCosineVectorAccum.Entry) -> int:
            """
            Comparison must be UNSIGNED!!
            """


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

    def __init__(self):
        ...

    def addHash(self, h: typing.Union[jpype.JInt, int], w: typing.Union[jpype.JDouble, float]):
        ...

    def doFinalize(self):
        ...


class LSHVector(java.lang.Object):

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

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

    def compare(self, op2: LSHVector, data: VectorCompare) -> float:
        ...

    def compareCounts(self, op2: LSHVector, data: VectorCompare):
        ...

    def compareDetail(self, op2: LSHVector, buf: java.lang.StringBuilder) -> float:
        ...

    def getEntries(self) -> jpype.JArray[HashEntry]:
        ...

    def getEntry(self, i: typing.Union[jpype.JInt, int]) -> HashEntry:
        ...

    def getLength(self) -> float:
        ...

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

    def restoreBase64(self, input: java.io.Reader, buffer: jpype.JArray[jpype.JChar], wfactory: WeightFactory, idflookup: IDFLookup, decode: jpype.JArray[jpype.JInt]):
        ...

    def restoreSQL(self, sql: typing.Union[java.lang.String, str], weightFactory: WeightFactory, idfLookup: IDFLookup):
        ...

    def restoreXml(self, parser: ghidra.xml.XmlPullParser, weightFactory: WeightFactory, idfLookup: IDFLookup):
        ...

    def saveBase64(self, buffer: java.lang.StringBuilder, encoder: jpype.JArray[jpype.JChar]):
        ...

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

    def saveXml(self, fwrite: java.io.Writer):
        ...

    @property
    def entry(self) -> HashEntry:
        ...

    @property
    def entries(self) -> jpype.JArray[HashEntry]:
        ...

    @property
    def length(self) -> jpype.JDouble:
        ...


class WeightFactory(java.lang.Object):

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

    def __init__(self):
        ...

    def getAddend(self) -> float:
        """
        
        
        :return: the final score addend
        :rtype: float
        """

    def getCoeff(self, i: typing.Union[jpype.JShort, int], t: typing.Union[jpype.JShort, int]) -> float:
        """
        Given an IDF position and a TF count, build the feature coefficient
        
        :param jpype.JShort or int i: is the IDF position
        :param jpype.JShort or int t: is the TF count
        :return: the feature coefficient
        :rtype: float
        """

    def getDiffNorm0(self) -> float:
        """
        
        
        :return: the first feature drop penalty parameter
        :rtype: float
        """

    def getDiffNorm1(self) -> float:
        """
        
        
        :return: the second feature drop penalty parameter
        :rtype: float
        """

    def getFlipNorm0(self) -> float:
        """
        
        
        :return: the first feature flip penalty parameter
        :rtype: float
        """

    def getFlipNorm1(self) -> float:
        """
        
        
        :return: the second feature flip penalty parameter
        :rtype: float
        """

    def getIDFSize(self) -> int:
        """
        
        
        :return: number of weights in the IDF portion of the table
        :rtype: int
        """

    def getIDFWeight(self, val: typing.Union[jpype.JShort, int]) -> float:
        """
        
        
        :param jpype.JShort or int val: 
        :return: the IDF weight at the given position
        :rtype: float
        """

    def getScale(self) -> float:
        """
        
        
        :return: the final score scaling factor
        :rtype: float
        """

    def getSize(self) -> int:
        """
        
        
        :return: number of floating-point entries needed to serialize the factory
        :rtype: int
        """

    def getTFSize(self) -> int:
        """
        
        
        :return: number of weights in the TF portion of the table
        :rtype: int
        """

    def getTFWeight(self, val: typing.Union[jpype.JShort, int]) -> float:
        """
        
        
        :param jpype.JShort or int val: is the term count (-1)
        :return: the TF weight for the given count
        :rtype: float
        """

    def getWeightNorm(self) -> float:
        """
        
        
        :return: the weight normalization factor
        :rtype: float
        """

    def restoreXml(self, parser: ghidra.xml.XmlPullParser):
        """
        Build (deserialize) this object from an XML stream
        
        :param ghidra.xml.XmlPullParser parser: is the XML parser
        """

    def saveXml(self, fwrite: java.io.Writer):
        """
        Serialize this object as XML to a Writer
        
        :param java.io.Writer fwrite: is the Writer
        :raises IOException:
        """

    def set(self, weightArray: jpype.JArray[jpype.JDouble]):
        """
        Initialize the WeightTable from an array of doubles
        
        :param jpype.JArray[jpype.JDouble] weightArray:
        """

    def setLogarithmicTFWeights(self):
        ...

    def toArray(self) -> jpype.JArray[jpype.JDouble]:
        """
        Condense weight table down to array of doubles
        
        :return: array of doubles
        :rtype: jpype.JArray[jpype.JDouble]
        """

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

    @property
    def diffNorm1(self) -> jpype.JDouble:
        ...

    @property
    def weightNorm(self) -> jpype.JDouble:
        ...

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

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

    @property
    def flipNorm1(self) -> jpype.JDouble:
        ...

    @property
    def tFWeight(self) -> jpype.JDouble:
        ...

    @property
    def iDFWeight(self) -> jpype.JDouble:
        ...

    @property
    def flipNorm0(self) -> jpype.JDouble:
        ...

    @property
    def scale(self) -> jpype.JDouble:
        ...

    @property
    def addend(self) -> jpype.JDouble:
        ...

    @property
    def diffNorm0(self) -> jpype.JDouble:
        ...


class HashEntry(java.lang.Object):

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

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

    @typing.overload
    def __init__(self, h: typing.Union[jpype.JInt, int], tcnt: typing.Union[jpype.JInt, int], weight: typing.Union[jpype.JDouble, float]):
        """
        Create a hash entry with an explicit weight
        
        :param jpype.JInt or int h: is the 32-bit hash
        :param jpype.JInt or int tcnt: is the (optional) term-frequency count  (set to 1 if not using)
        :param jpype.JDouble or float weight: is the weight associated with the hash
        """

    @typing.overload
    def __init__(self, h: typing.Union[jpype.JInt, int], tcnt: typing.Union[jpype.JInt, int], dcnt: typing.Union[jpype.JInt, int], w: WeightFactory):
        """
        Create a hash entry with a weight calculated from its term frequency and idf frequency
        
        :param jpype.JInt or int h: is the 32-bit hash
        :param jpype.JInt or int tcnt: is the term frequency count
        :param jpype.JInt or int dcnt: is the (normalized) idf frequency   (should be generated by an IDFLookup)
        :param WeightFactory w: is the factory used to generate the final weight
        """

    def equals(self, obj: java.lang.Object) -> bool:
        """
        Eclipse-generated equals function.
        
        :param java.lang.Object obj: 
        :return: 
        :rtype: bool
        """

    def getCoeff(self) -> float:
        ...

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

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

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

    def hashCode(self) -> int:
        """
        Eclipse-generated hash function.
        
        :return: 
        :rtype: int
        """

    def restoreBase64(self, buffer: jpype.JArray[jpype.JChar], offset: typing.Union[jpype.JInt, int], decoder: jpype.JArray[jpype.JInt], w: WeightFactory, lookup: IDFLookup) -> bool:
        ...

    def restoreSQL(self, sql: typing.Union[java.lang.String, str], start: typing.Union[jpype.JInt, int], w: WeightFactory, lookup: IDFLookup) -> int:
        ...

    @typing.overload
    def restoreXml(self, parser: ghidra.xml.XmlPullParser, w: WeightFactory):
        ...

    @typing.overload
    def restoreXml(self, parser: ghidra.xml.XmlPullParser, w: WeightFactory, lookup: IDFLookup):
        """
        Restore entry but recalculate the idf
        
        :param ghidra.xml.XmlPullParser parser: // xml state
        :param WeightFactory w: // weight factory to calculate coefficient with
        :param IDFLookup lookup: // lookup object to recalculate idf
        """

    def saveBase64(self, buffer: jpype.JArray[jpype.JChar], offset: typing.Union[jpype.JInt, int], encoder: jpype.JArray[jpype.JChar]):
        ...

    def saveSQL(self, buf: java.lang.StringBuilder):
        ...

    def saveXml(self, fwrite: java.io.Writer):
        ...

    @property
    def tF(self) -> jpype.JShort:
        ...

    @property
    def iDF(self) -> jpype.JShort:
        ...

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

    @property
    def coeff(self) -> jpype.JDouble:
        ...


class VectorCompare(java.lang.Object):
    """
    Class for containing intermediate results of doing the LSHVector compare operation
    """

    class_: typing.ClassVar[java.lang.Class]
    dotproduct: jpype.JDouble
    acount: jpype.JInt
    bcount: jpype.JInt
    intersectcount: jpype.JInt
    min: jpype.JInt
    max: jpype.JInt
    numflip: jpype.JInt
    diff: jpype.JInt

    def __init__(self):
        ...

    def fillOut(self):
        """
        Assume the dotproduct, acount, bcount, and intersectcount are filled in
        Calculate the remaining values: min, max, numflip, and diff
        Assume small vector is produced by flipping and removing hashes from big vector
        Calculate the number of flipped hashes (numflip) from a VectorCompare result
        Calculate the difference in the number of hashes (diff) from a VectorCompare result
        """


class LSHCosineVector(LSHVector):

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

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

    @typing.overload
    def __init__(self, feature: jpype.JArray[jpype.JInt], wfactory: WeightFactory, idflookup: IDFLookup):
        """
        Install a set of features as an int[].   Each integer is a hash.  The integers MUST already be sorted.
        The same integer can occur more than once in the array (term frequency (TF) > 1).
        Weights are determined by TF and Inverse Document Frequency (IDF) of individual features
        
        :param jpype.JArray[jpype.JInt] feature: is the sorted array of integer hashes
        :param WeightFactory wfactory: is the container of weighting information
        :param IDFLookup idflookup: is the container of IDF information
        """

    def equals(self, obj: java.lang.Object) -> bool:
        """
        Eclipse-generated equals method.  Only the hash attribute is necessary.
        
        :param java.lang.Object obj: 
        :return: 
        :rtype: bool
        """

    def hashCode(self) -> int:
        """
        Uses the existing :meth:`calcUniqueHash() <.calcUniqueHash>` method to determine hash value.
        
        :return: 
        :rtype: int
        """

    def setHashEntries(self, entries: jpype.JArray[HashEntry]):
        """
        Install hashes and weights directly.  Length is automatically calculated.
        The entries must already be sorted on the hash
        
        :param jpype.JArray[HashEntry] entries:
        """


class WeightedLSHCosineVectorFactory(LSHVectorFactory):

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

    def __init__(self):
        ...



__all__ = ["LSHVectorFactory", "IDFLookup", "LSHCosineVectorAccum", "LSHVector", "WeightFactory", "HashEntry", "VectorCompare", "LSHCosineVector", "WeightedLSHCosineVectorFactory"]
