""" Command Line Interface for W24 Techread
"""
import argparse
import io
import logging
import sys
from typing import List

from dotenv import load_dotenv
from werk24.exceptions import RequestTooLargeException
from werk24.models.ask import (W24AskCanvasThumbnail, W24AskPageThumbnail,
                               W24AskSectionalThumbnail, W24AskSheetThumbnail,
                               W24AskVariantGDTs, W24AskVariantMeasures)
from werk24.models.techread import (W24TechreadMessageSubtypeError,
                                    W24TechreadMessageSubtypeProgress,
                                    W24TechreadMessageType)
from werk24.techread_client import Hook, LicenseError, W24TechreadClient

# load the environment variables
load_dotenv(".werk24")

# set the log level to info for the test setting
# We recommend using logging.WARNING for production
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s',  # noqa
    datefmt='%Y-%m-%d %H:%M:%S')

# get the local logger
logger = logging.getLogger(__name__)  # pylint:disable = invalid-name


def _get_drawing(
        file_path: str
) -> bytes:
    """ Obtain the bytes content of the test drawing
    """
    # get the content
    with open(file_path, "rb") as filehandle:
        return filehandle.read()


def _debug_show_image(
        log_text: str,
        image_bytes: bytes
) -> None:

    # Import the PIL at runtime to make sure that
    # you can still use the client without the need
    # to install Pillow
    try:
        from PIL import Image  # pylint: disable=import-outside-toplevel
    except ImportError:
        logger.warning(
            "Viewing image-like responses, requires the installation"
            " of the PIL package: pip install pillow. Image skipped.")
        return

    # otherwise print the text
    logger.info(log_text)

    # and show the image
    image = Image.open(io.BytesIO(image_bytes))
    image.show(title=log_text)


async def main(
    args: argparse.Namespace
) -> None:
    """ Run the Techread command with the CLI arguments

    Arguments:
        args {argparse.Namespace} -- CLI args generated by
            argparse
    """

    # make the hooks from the arguments
    hooks = _make_hooks_from_args(args)

    # make the client. This will automatically
    # fetch the authentication information
    # from the environment variables. We will
    # provide you with separate .env files for
    # the development and production environments
    try:
        client = W24TechreadClient.make_from_env()

    # If a license error occured, let the user know.
    except LicenseError as exception:
        print(f"LICENSE ERROR: {exception}")
        sys.exit()

    async with client as session:

        # get the drawing
        drawing_bytes = _get_drawing(args.input_file)

        # and make the request
        try:
            await session.read_drawing_with_hooks(
                drawing_bytes,
                hooks)

        except RequestTooLargeException:
            message = "Request was too large to be processed. " \
                + "Please check the documentation for current limits."
            logger.error(message)


def _make_hooks_from_args(
        args: argparse.Namespace
) -> List[Hook]:

    # tell the api what asks you are interested in,
    # and define what to do when you receive the result
    hooks = []

    # add the hook to get the information that the techread
    # process was started

    # add the hook for the page thumbnail
    if args.ask_page_thumbnail:
        hooks += [Hook(
            ask=W24AskPageThumbnail(),
            function=lambda msg: _debug_show_image(
                "Page Thumbnail received",
                msg.payload_bytes))]

    # add the hook for the sheet thumbnail
    if args.ask_sheet_thumbnail:
        hooks += [Hook(
            ask=W24AskSheetThumbnail(),
            function=lambda msg: _debug_show_image(
                "Sheet Thumbnail received",
                msg.payload_bytes))]

    # add the hook for the sheet thumbnail
    if args.ask_canvas_thumbnail:
        hooks += [Hook(
            ask=W24AskCanvasThumbnail(),
            function=lambda msg: _debug_show_image(
                "Canvas Thumbnail received",
                msg.payload_bytes))]

    # add the hook for the drawing thumbnail
    if args.ask_sectional_thumbnail:
        hooks += [Hook(
            ask=W24AskSectionalThumbnail(),
            function=lambda msg: _debug_show_image(
                "Drawing thumbnail received",
                msg.payload_bytes))]

    # add the hook for the variant measures
    if args.ask_variant_measures:
        hooks += [Hook(
            ask=W24AskVariantMeasures(),
            function=lambda msg: print(
                "Received Ask Variant Measures\n",
                msg.payload_dict
            ))]

        # add the hook for the variant measures
    if args.ask_variant_gdts:
        hooks += [Hook(
            ask=W24AskVariantGDTs(),
            function=lambda msg: print(
                "Received Ask Variant GDTs\n",
                msg.payload_dict
            ))]

    # add a general hook to deal with internal errors
    hook_error_internal = Hook(
        message_type=W24TechreadMessageType.ERROR,
        message_subtype=W24TechreadMessageSubtypeError.INTERNAL,
        function=lambda msg:
        logger.error("Internal Error %s", msg.payload_dict))
    hooks.append(hook_error_internal)

    # add a gneral hook to deal with PROGRESS messages
    hook_progress_started = Hook(
        message_type=W24TechreadMessageType.PROGRESS,
        message_subtype=W24TechreadMessageSubtypeProgress.STARTED,
        function=lambda msg: logger.info("Techread process started"))
    hooks.append(hook_progress_started)

    return hooks
