#!/usr/bin/env python

import os
import requests
import argparse
import subprocess

parser = argparse.ArgumentParser(description='Mayer EMI GmbH(c) Update manager.')
parser.add_argument('-t', dest='devType', default="MD850", help='Synthesizer type')
parser.add_argument('-n', dest='synthCurVersion', default="*", help='Synthesizer current version')
parser.add_argument('-s', dest='serialNumber', help='Synthesizer serial number')
parser.add_argument('-r', action='store_true', help='Retrieve update information')
parser.add_argument('-g', dest='getPkgName', help='Download package <name>')
parser.add_argument('-i', dest='installPkgName', help='Synthesizer serial <name>')

class MemiUpdateManager():
    devType = None
    synthCurVersion = None
    serialNumber = None
    urlHost = "https://my.mayer-emi.at"
    urlAPI = "/api/method"
    urlDL = "/files"
    wDir = "/tmp/"
    
    def __init__(self,devType=None, synthCurVersion=None, serialNumber=None) -> None:
        self.devType = devType
        self.synthCurVersion = synthCurVersion
        if serialNumber == None:
            if os.path.exists("/sys/firmware/devicetree/base/serial-number"):
                with open("/sys/firmware/devicetree/base/serial-number") as f:
                    self.serialNumber = f.read(16)
        else:
            self.serialNumber = serialNumber

    def getUpdateInfo(self):
        url = self.urlHost + self.urlAPI + "/getupdateinfo"
        query_parameters = {"t": self.devType, "v": self.synthCurVersion, "s": self.serialNumber}
        response = requests.get(url, params=query_parameters)
        data=response.json()
        filepath = self.wDir + "update.info"

        # Write key-value pairs to the text file
        with open(filepath, 'w') as file:
            for key, value in data.items():
                file.write(f"{key} = {value}\n")

    def getPackage(self, filename):
        url = self.urlHost + self.urlDL + "/" + filename
        filepath = self.wDir + filename
        pfilepath = self.wDir + "update.progress"

        # Streaming, so we can iterate over the response.
        response = requests.get(url, stream=True)

        if response.ok:
          total_size = int(response.headers.get("content-length", 0))
          #print(total_size)
          trans_size = 0
          block_size = 10240

          with open(filepath, "wb") as file, open(pfilepath, 'w') as fprogress:
            for data in response.iter_content(block_size):
              trans_size+=len(data)
              file.write(data)

              progress=f"{(trans_size/total_size*100):.1f}"
              fprogress.seek(0)
              fprogress.write(f"{progress}%")
              fprogress.truncate()  # Ensure the file content is replaced
            fprogress.seek(0)
            fprogress.write(f"COMPLETED")
            fprogress.truncate()  # Ensure the file content is replaced
        else:
          with open(pfilepath, 'w') as fprogress:
            fprogress.seek(0)
            fprogress.write(f"-1")
            fprogress.truncate()  # Ensure the file content is replaced
           

    def installPackage(self, filename):
      filepath = self.wDir + filename
      if os.path.exists(filepath):
        process = subprocess.Popen(["mpkghandler", "-e", filepath],
                                   stdout=subprocess.DEVNULL,  # Redirect output to avoid blocking
                                   stderr=subprocess.DEVNULL,  # Redirect errors to avoid blocking
                                   preexec_fn=os.setpgrp  # Detach from parent process
                                  )

if __name__ == '__main__':
    args = parser.parse_args()
    mum = MemiUpdateManager(args.devType, args.synthCurVersion, args.serialNumber)
    if args.r:
      #print("Would call getUpdateInfo")
      mum.getUpdateInfo()
    if args.getPkgName:
      #print(f"Would call getPackage with {args.getPkgName}")
      mum.getPackage(args.getPkgName)
    if args.installPkgName:
      #print(f"Would call installPackage with {args.installPkgName}")
      mum.installPackage(args.installPkgName)

