#!/usr/bin/python3.8
"""
@brief      Binary Uploader Module
@details
This module will be used to upload binaries to the OBC via a communication port, given
a supplied binary. The binary will be sent via the specified communication interface.
It will be possible to encode the data (for example using DLE encoding)
"""
import time
import tkinter as tk
from tkinter import filedialog
from collections import deque

from tmtc_core.comIF.obsw_com_interface import CommunicationInterface
from tc.obsw_tc_service23_sdcard import FileTransferHelper, generate_generic_folder_structure
import config.obsw_config as g
from tmtc_core.tc.obsw_pus_tc_base import PusTelecommand
from tmtc_core.utility.obsw_tmtc_printer import TmTcPrinter, DisplayMode
from tmtc_core.utility.obsw_logger import get_logger

LOGGER = get_logger()


def perform_file_upload(com_if: CommunicationInterface, tmtc_printer: TmTcPrinter):
    # TODO: prompt whether this is a binary upload or a normal file upload. Or use op code
    #       two different commands to achieve the same.
    print("Please select file to upload")
    root = tk.Tk()
    root.withdraw()
    root.wm_attributes('-topmost', 1)

    # TODO: implement command line version which just parses the _bin folder, displays the options
    #       and asks for a selection.
    file_path = filedialog.askopenfilename(parent=root)
    print("File select: " + str(file_path))
    calc_hamming_code = input("Calculate and send hamming code? [y/n]: ")
    if calc_hamming_code in ['y', 'yes', 1]:
        calc_hamming_code = True
        print("Hamming code will be calculated and sent in tail packet")
    else:
        calc_hamming_code = False
        print("Hamming code will not be calculated")

    iobc_prompt = input("iOBC? [y/n]: ")
    if iobc_prompt in ['y', 'yes', 1]:
        iobc_prompt = True
    else:
        iobc_prompt = False

    bootloader_prompt = input("Bootloader (0) or Software Image (1)? [0/1]: ")
    if bootloader_prompt == 0:
        bootloader_prompt = True
    else:
        bootloader_prompt = False

    if bootloader_prompt:
        file_name = "bl.bin"
    else:
        file_name = "obsw_up.bin"

    if iobc_prompt:
        if bootloader_prompt:
            repository_name = "BIN/IOBC/BL"
        else:
            repository_name = "BIN/IOBC/OBSW"
    else:
        if bootloader_prompt:
            repository_name = "BIN/AT91/BL"
        else:
            repository_name = "BIN/AT91/OBSW"

    # Right now, the size of PUS packets is limited to 1500 bytes which also limits the app
    # data length.
    frame_length = g.G_MAX_APP_DATA_LENGTH

    if calc_hamming_code:
        # now we calculate the hamming code
        pass

    # Read file as binary file
    if file_path != ():
        with open(file_path, 'rb') as file:
            data_to_read = bytearray(file.read())
    else:
        LOGGER.info("Specified path invalid..")

    print("Generating folder structure..")
    tc_queue = deque()

    # Delete existing binary file first, otherwise data might be appended to otherwise
    # valid file which already exists.
    file_transfer_helper = FileTransferHelper(
        tc_queue=tc_queue, max_size_of_app_data=frame_length, target_repository=repository_name,
        target_filename=file_name)

    init_ssc = 0
    tmtc_printer.set_display_mode(DisplayMode.SHORT)
    file_transfer_helper.set_data_from_file(file_path)
    file_transfer_helper.set_to_delete_old_file()
    file_transfer_helper.generate_packets(init_ssc)
    print_string = str(file_transfer_helper.queue_size()) + " packets generated.."
    LOGGER.info(print_string)

    idx = 1
    while tc_queue:
        (tc_packet, tc_info) = tc_queue.pop()
        if not isinstance(tc_packet, str):
            print_string = "Sending packet " + str(idx)
            idx += 1
            LOGGER.info(print_string)
            print("Sending packet with length " + str(len(tc_packet)) + " ..")
            com_if.send_telecommand(tc_packet, tc_info)
        elif tc_packet == "print":
            LOGGER.info(tc_info)

        time.sleep(0.5)
        tm_list = com_if.receive_telemetry()
        for tm_packet in tm_list:
            # gotta configure tm listener for this to work..
            tmtc_printer.print_telemetry(tm_packet)
    LOGGER.info("All binary packets sent!")