#!/usr/bin/env python3
# Copyright(c) 2022 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
import os
import sys
import logging
import time
import argparse
import socket
import struct
import hashlib
from urllib.parse import urlparse

RET = 0
HOST = None
PORT = 0
PORT_LOG = 9999
PORT_REQ = PORT_LOG + 1
BUF_SIZE = 4096

# Define the command and its
# possible max size
CMD_LOG_START = "start_log"
CMD_DOWNLOAD = "download"
MAX_CMD_SZ = 16

# Define the header format and size for
# transmiting the firmware
PACKET_HEADER_FORMAT_FW = 'I 42s 32s'

logging.basicConfig()
log = logging.getLogger("cavs-client")
log.setLevel(logging.INFO)

class cavstool_client():
    def __init__(self, host, port, args):
        self.host = host
        self.port = port
        self.args = args
        self.sock = None
        self.cmd = None

    def send_cmd(self, cmd):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            self.sock = sock
            self.cmd = cmd
            self.sock.connect((self.host, self.port))
            self.sock.sendall(cmd.encode("utf-8"))
            log.info(f"Sent:     {cmd}")
            ack = str(self.sock.recv(MAX_CMD_SZ), "utf-8")
            log.info(f"Receive: {ack}")

            if ack == CMD_LOG_START:
                self.monitor_log()
            elif ack == CMD_DOWNLOAD:
                self.run()
            else:
                log.error(f"Receive incorrect msg:{ack} expect:{cmd}")

    def uploading(self, filename):
        # Send the FW to server
        fname = os.path.basename(filename)
        fsize = os.path.getsize(filename)

        md5_tx = hashlib.md5(open(filename,'rb').read()).hexdigest()

        # Pack the header and the expecting packed size is 78 bytes.
        # The header by convention includes:
        # size(4), filename(42), MD5(32)
        values = (fsize, fname.encode('utf-8'), md5_tx.encode('utf-8'))
        log.info(f'filename:{fname}, size:{fsize}, md5:{md5_tx}')

        s = struct.Struct(PACKET_HEADER_FORMAT_FW)
        header_data = s.pack(*values)
        header_size = s.size
        log.info(f'header size: {header_size}')

        with open(filename,'rb') as f:
            log.info(f'Sending...')

            total = self.sock.send(header_data)
            total += self.sock.sendfile(f)

            log.info(f"Done Sending ({total}).")

            rck = self.sock.recv(MAX_CMD_SZ).decode("utf-8")
            log.info(f"RCK ({rck}).")
            if not rck == "success":
                global RET
                RET = -1
                log.error(f"Firmware uploading failed")

    def run(self):
        filename = str(self.args.fw_file)
        self.uploading(filename)

    def monitor_log(self):
        log.info(f"Start to monitor log output...")
        while True:
            # Receive data from the server and print out
            receive_log = str(self.sock.recv(BUF_SIZE), "utf-8").replace('\x00','')
            if receive_log:
                sys.stdout.write(f"{receive_log}")
                sys.stdout.flush()
                time.sleep(0.1)

    def __del__(self):
        self.sock.close()


def main():
    if args.log_only:
        log.info("Monitor process")

        try:
            client = cavstool_client(HOST, PORT, args)
            client.send_cmd(CMD_LOG_START)
        except KeyboardInterrupt:
            pass

    else:
        log.info("Uploading process")
        client = cavstool_client(HOST, PORT, args)
        client.send_cmd(CMD_DOWNLOAD)

ap = argparse.ArgumentParser(description="DSP loader/logger client tool")
ap.add_argument("-q", "--quiet", action="store_true",
                help="No loader output, just DSP logging")
ap.add_argument("-l", "--log-only", action="store_true",
                help="Don't load firmware, just show log output")
ap.add_argument("-s", "--server-addr", default="localhost",
                help="Specify the adsp server address")
ap.add_argument("-p", "--log-port", type=int,
                help="Specify the PORT that connected to log server")
ap.add_argument("-r", "--req-port", type=int,
                help="Specify the PORT that connected to request server")
ap.add_argument("fw_file", nargs="?", help="Firmware file")
args = ap.parse_args()

if args.quiet:
    log.setLevel(logging.WARN)

if args.log_port:
    PORT_LOG = args.log_port

if args.req_port:
    PORT_REQ = args.req_port

if args.server_addr:
    url = urlparse("//" + args.server_addr)

    if url.hostname:
        HOST = url.hostname

    if url.port:
        PORT = int(url.port)
    else:
        if args.log_only:
            PORT = PORT_LOG
        else:
            PORT = PORT_REQ

log.info(f"REMOTE HOST: {HOST} PORT: {PORT}")

if __name__ == "__main__":
    main()

    sys.exit(RET)
