#!/usr/bin/python3
"""
Sends a request to the specified server in order to download the specified
file.
"""

from os import path, chdir, mkdir
from lib.cli_parse import parse_args_download
from lib.rdt_interface import recvfrom_fixed_addr, sendto_fixed_addr
from lib.rdt_selection import create_rdt
from lib.socket_udp import Socket, SocketTimeout
from lib.logger import logger
import lib.protocol as prt


def create_dir(dirpath: str) -> bool:
    option = None
    while option not in ['y', 'n']:
        option = input(f"Directory '{dirpath}/' not found. "
                       + "Do you want to create it? (y/n): ").lower()
    if option == 'n':
        return False
    return True


def navigate_to_dirpath(filepath: str) -> str:
    paths = filepath.split('/')
    subdirs = paths[:-1]
    dirpath = '/'.join(subdirs)
    filepath = paths[-1]

    # if dirname not exists, ask user if we should create it
    if not path.isdir(dirpath):
        if not create_dir(dirpath):
            return None

    # create subdirs
    for subdir in subdirs:
        if not path.isdir(subdir):
            mkdir(subdir)
        chdir(subdir)

    return filepath


def download_file(logger_level, FILEPATH, ADDR, PORT, FILENAME):
    logger.setLevel(logger_level)

    filepath = navigate_to_dirpath(FILEPATH)
    if filepath is None:
        return 0

    skt = Socket()
    addr = (ADDR, PORT)
    rdt = create_rdt(sendto_fixed_addr(skt, addr), recvfrom_fixed_addr(skt))

    filesize = prt.download_request(rdt, FILENAME)

    logger.info("Downloading file...")

    with open(filepath, 'wb') as f:
        for file_chunk in prt.recv_file(rdt, filesize, True):
            f.write(file_chunk)

    logger.info("File downloaded.")
    return


def main(args):
    download_file(args.level, args.FILEPATH,
                  args.ADDR, args.PORT, args.FILENAME)

    return 0


if __name__ == "__main__":
    args = parse_args_download()
    try:
        main(args)
    except KeyboardInterrupt:
        print()
        logger.fatal("Program was ended by KeyboardInterrupt")
    except SocketTimeout:
        logger.fatal("Socket error: Connection timed-out.")
    except BaseException:
        logger.exception("Unexpected error during execution:")
        exit(1)
