
import dataclasses
from datetime import datetime
from pathlib import Path
import re

from pyhidra import __version__


MINIMUM_GHIDRA_VERSION = "10.3"
_APPLICATION_PATTERN = re.compile(r"^application\.(\S+?)=(.*)$")


@dataclasses.dataclass(frozen=True)
class ApplicationInfo:
    """
    Ghidra Application Properties
    """
    name: str
    version: str
    release_name: str
    revision_ghidra: str = ""
    build_date: str = ""
    build_date_short: str = ""
    layout_version: str = ""
    gradle_min: str = ""
    java_min: str = ""
    java_max: str = ""
    java_compiler: str = ""
    gradle_max: str = ""

    @classmethod
    def from_file(cls, file: Path):
        """
        Parses Ghidra's application.properties file from the provided path
        """
        valid_fields = {f.name for f in dataclasses.fields(cls)}
        kwargs = dict()
        for line in file.read_text(encoding="utf8").splitlines():
            match = _APPLICATION_PATTERN.match(line)
            if not match:
                continue
            attr = match.group(1).replace('.', '_').replace('-', '_')
            value = match.group(2)
            if attr in valid_fields:
                kwargs[attr] = value
        return cls(**kwargs)


@dataclasses.dataclass
class ExtensionDetails:
    """
    Python side ExtensionDetails
    """
    name: str
    description: str
    author: str
    createdOn: str = dataclasses.field(default_factory=lambda: str(datetime.now()))
    version: str = None
    plugin_version: str = "0.0.1"

    @classmethod
    def from_file(cls, ext_path: Path):
        valid_fields = {f.name for f in dataclasses.fields(cls)}
        def cast(key, value):
            return cls.__annotations__[key](value)
        lines = ext_path.read_text().splitlines()
        kwargs = {
            key: cast(key, value)
            for key, value in map(lambda l: l.split("="), lines)
            if key in valid_fields
        }
        return cls(**kwargs)

    def __repr__(self):
        return "\n".join(f"{key}={value}" for key, value in dataclasses.asdict(self).items())
