import clr
clr.AddReference('Soti.Connect.SemanticEngine.Conversions')
from System.Collections.Generic import List

from Soti.Connect.SemanticEngine.Conversions.Interpreters import FirmwareInterpreter
from Soti.Connect.SemanticEngine.Conversions.Interpreters import FirmwareMetadata
import re

_VERSION_RE = r'^[A-Z][0-9]+(?:\.[0-9]+)*$'

print("Loading HoneywellFirmwareInterpreter")

class HoneywellFirmwareInterpreter(FirmwareInterpreter):
    def GetMetadata(self, fileName, fileBytes):
        models = List[str]()
        version = ""
        if len(fileBytes) < 3:
            return FirmwareMetadata(version, models)

        soh = fileBytes[0]
        model_code = chr(fileBytes[2])
        mapping = {
            'C': ['PC45d', 'PC45t'],
            'B': ['PX45', 'PX65'],
            'M': ['RP2f', 'RP4f'],
            'J': ['PM45', 'PM45c'],
            'F': ['PX240S', 'PX240', 'PD45S', 'PD45'],
            'H': ['PX940', 'PX940V'],
            'A': ['PX4ie', 'PX6ie'],
            'P': ['PM43', 'PM43c', 'PM23c'],
            'L': ['PM42'],
            'K': ['PD43', 'PD43c', 'PC43t', 'PC43d', 'PC23d'],
            'T': ['PC42t', 'PC42d'],
            'D': ['PC42E-D', 'PC42E-T', 'PC310T', 'OT820']
        }
        
        read_length = 24 if soh == 0x01 else 15
        start = 3
        end = start + read_length
        if end <= len(fileBytes):
            snippet = fileBytes[start:end]
            raw = bytes(snippet).decode('ascii', errors='ignore').strip('\x00').strip()

        version_candidate = model_code + raw
        if self.ValidateVersion(version_candidate):
            version = version_candidate
            for model in mapping.get(model_code, []):
                    models.Add(model)

        return FirmwareMetadata(version, models)

    def ValidateVersion(self, rawVersion):
        return bool(re.match(_VERSION_RE, rawVersion))

    def CompareVersions(self, deviceStateVersionRaw, firmwareFileVersionRaw):
        device = deviceStateVersionRaw[1:]
        firmware = firmwareFileVersionRaw[1:]

        d_major, d_minor, d_patch = device.split('.')
        f_major, f_minor, f_patch = firmware.split('.')

        d_major, d_minor, d_patch = int(d_major), int(d_minor), int(d_patch)
        f_major, f_minor, f_patch = int(f_major), int(f_minor), int(f_patch)

        if d_major > f_major:
            return 1
        if d_major < f_major:
            return -1
        
        if d_minor > f_minor:
            return 1
        if d_minor < f_minor:
            return -1
        
        if d_patch > f_patch:
            return 1
        if d_patch < f_patch:
            return -1

        return 0
    
plugin = HoneywellFirmwareInterpreter("HoneywellFirmwareInterpreter")

store.Add(plugin)