from assemblyline import odm

REACTIONS_TYPES = {"thumbs_up", "thumbs_down", "love", "smile", "surprised", "party"}


@odm.model(index=True, store=True, description="URI Information Model")
class URIInfo(odm.Model):
    uri: str = odm.Keyword(description="full URI")

    # https://www.rfc-editor.org/rfc/rfc1808.html#section-2.1
    scheme: str = odm.Keyword(description="")
    netloc: str = odm.Keyword(description="")
    path: str = odm.Optional(odm.Keyword(description=""))
    params: str = odm.Optional(odm.Keyword(description=""))
    query: str = odm.Optional(odm.Keyword(description=""))
    fragment: str = odm.Optional(odm.Keyword(description=""))

    # Ease-of-use elements
    username: str = odm.Optional(odm.Keyword(description=""))
    password: str = odm.Optional(odm.Keyword(description=""))
    hostname: str = odm.Keyword(description="")
    port: int = odm.Optional(odm.Integer(description=""))


@odm.model(index=True, store=True, description="File Seen Model")
class Seen(odm.Model):
    count = odm.Integer(default=1, description="How many times have we seen this file?")
    first = odm.Date(default="NOW", description="First seen timestamp")
    last = odm.Date(default="NOW", description="Last seen timestamp")


@odm.model(index=True, store=True, description="Label Categories Model")
class LabelCategories(odm.Model):
    info = odm.List(
        odm.Keyword(),
        description="List of extra informational labels about the file", default=[])
    technique = odm.List(
        odm.Keyword(),
        description="List of labels related to the technique used by the file and the signatures that hits on it.",
        default=[])
    attribution = odm.List(
        odm.Keyword(),
        description="List of labels related to attribution of this file (implant name, actor, campain...)",
        default=[])


@odm.model(index=True, store=False, description="Reaction Model")
class Reaction(odm.Model):
    icon = odm.Enum(values=REACTIONS_TYPES, description="Icon of the user who made the reaction")
    uname = odm.Keyword(description="Username of the user who made the reaction")


@odm.model(index=True, store=False, description="Comment Model")
class Comment(odm.Model):
    cid = odm.UUID(description="Comment ID")
    uname = odm.Keyword(description="Username of the user who made the comment")
    date = odm.Date(store=True, default="NOW", description="Datetime the comment was made on")
    text = odm.Text(description="Text of the comment written by the author")
    reactions = odm.List(odm.Compound(Reaction), default=[], description="List of reactions made on a comment")


@odm.model(index=True, store=True, description="Model of File")
class File(odm.Model):
    archive_ts = odm.Optional(odm.Date(description="Time at which the file was archived", ai=False))
    ascii = odm.Keyword(index=False, store=False,
                        description="Dotted ASCII representation of the first 64 bytes of the file", ai=False)
    classification = odm.Classification(description="Classification of the file")
    comments = odm.List(odm.Compound(Comment), default=[], description="List of comments made on a file")
    entropy = odm.Float(description="Entropy of the file")
    expiry_ts = odm.Optional(odm.Date(store=False), description="Expiry timestamp", ai=False)
    is_section_image = odm.Boolean(
        default=False, description="Is this an image from an Image Result Section?", ai=False)
    is_supplementary = odm.Boolean(default=False, description="Is this a file generated by a service?", ai=False)
    hex = odm.Keyword(index=False, store=False, description="Hex dump of the first 64 bytes of the file", ai=False)
    labels = odm.List(odm.Keyword(copyto="__text__"), description="List of labels of the file", default=[])
    label_categories = odm.Compound(LabelCategories, default={}, description="Categories of label", ai=False)
    md5 = odm.MD5(copyto="__text__", description="MD5 of the file", ai=False)
    magic = odm.Keyword(store=False, description="Output from libmagic related to the file")
    mime = odm.Optional(odm.Keyword(store=False), description="MIME type of the file as identified by libmagic")
    seen = odm.Compound(Seen, default={}, description="Details about when the file was seen", ai=False)
    sha1 = odm.SHA1(copyto="__text__", description="SHA1 hash of the file", ai=False)
    sha256 = odm.SHA256(copyto="__text__", description="SHA256 hash of the file")
    size = odm.Integer(description="Size of the file in bytes")
    ssdeep = odm.SSDeepHash(store=False, description="SSDEEP hash of the file", ai=False)
    type = odm.Keyword(copyto="__text__", description="Type of file as identified by Assemblyline")
    tlsh = odm.Optional(odm.Keyword(copyto="__text__", description="TLSH hash of the file", ai=False))
    from_archive = odm.Boolean(index=False, store=False, default=False,
                               description="Was loaded from the archive", ai=False)
    uri_info = odm.Optional(odm.Compound(URIInfo), description="URI structure to speed up specialty file searching")
