""" Defintions of all objects required to communicate with
the W24 Techread API.
"""
from enum import Enum
from typing import Dict, List, Optional, Union

from pydantic import UUID4, BaseModel, Field, HttpUrl, Json
from werk24._version import __version__

from .ask import W24AskType, W24AskUnion


class W24TechreadAction(str, Enum):
    """ List of supported actions by the Techread API
    """
    INITIALIZE = "INITIALIZE"
    READ = "READ"


class W24TechreadCommand(BaseModel):
    """ Command that is sent from the client to the Server
    """
    action: W24TechreadAction
    message: Json


class W24TechreadMessageType(str, Enum):
    """ Message Type of the message that is sent
    from the server to the client in response to
    a request.
    """
    ASK = "ASK"
    ERROR = "ERROR" # !!! DEPRECATED
    PROGRESS = "PROGRESS"
    REJECTION = "REJECTION"


class W24TechreadMessageSubtypeError(str, Enum):
    """ Message Subtype for the MessageType: ERROR

    !!! DEPRECATED
    """
    UNSUPPORTED_DRAWING_FILE_FORMAT = "UNSUPPORTED_DRAWING_FILE_FORMAT"
    INTERNAL = "INTERNAL"
    TIMEOUT = "TIMEOUT"


class W24TechreadMessageSubtypeRejection(str, Enum):
    """ Message Subtype for the MessageType: REJECTION
    """
    COMPLEXITY_EXCEEDED = "COMPLEXITY_EXCEEDED"
    PAPER_SIZE_LIMIT_EXCEEDED = "PAPER_SIZE_LIMIT_EXCEEDED"


class W24TechreadMessageSubtypeProgress(str, Enum):
    """ Message Subtype for the MessageType: PROGRESS
    """
    INITIALIZATION_SUCCESS = "INITIALIZATION_SUCCESS"
    COMPLETED = "COMPLETED"
    STARTED = "STARTED"


W24TechreadMessageSubtypeAsk = W24AskType
""" The MessageType: ASK will return the subtypes
defined in W24AskTypes
"""

W24TechreadMessageSubtype = Union[
    W24TechreadMessageSubtypeError,
    W24TechreadMessageSubtypeProgress,
    W24TechreadMessageSubtypeAsk]
""" Shorthand to summorize all the supported
MessageTypes
"""


class W24TechreadExceptionType(str, Enum):
    """ List of all the error types that can possibly
    be associated to the error type.
    """

    DRAWING_FILE_FORMAT_UNSUPPORTED = "DRAWING_FILE_FORMAT_UNSUPPORTED"
    """ The Drawing was submitted in a file format that is not supproted
    by the API at this stage.
    """

    DRAWING_FILE_SIZE_TOO_LARGE = "DRAWING_FILE_SIZE_TOO_LARGE"
    """ The Drawing file size exceeded the limit
    """

    DRAWING_RESOLUTION_TOO_LOW = "DRAWING_RESOLUTION_TOO_LOW"
    """ The resolution (dots per inch) was too low to be
    processed
    """

    DRAWING_NOISE_TOO_HIGH = "DRAWING_NOISE_TOO_HIGH"
    """ The amount of noise on the drawing was too hight for us
    to understand the drawing
    """

    DRAWING_CONTENT_NOT_UNDERSTOOD = "DRAWING_CONTENT_NOT_UNDERSTOOD"
    """ The file you submitted as drawing might not actually
    be a drawing
    """

    MODEL_FILE_FORMAT_UNSUPPORTED = "MODEL_FILE_FORMAT_UNSUPPORTED"
    """ The Model was submitted in a file format that is not supported
    by the API at this stage.
    """

    MODEL_FILE_SIZE_TOO_LARGE = "MODEL_FILE_SIZE_TOO_LARGE"
    """ The Model fiel size exceeded the limit
    """


class W24TechreadExceptionLevel(str, Enum):
    """ Severity level for the Error

    NOTE: this is defined for downward-compatability.
    The only value that is currently used is ERROR
    """

    ERROR = "ERROR"
    """ Set then whe processing was stopped
    """


class W24TechreadException(BaseModel):
    """ Error message that accompanies the W24TechreadMessage
    if an error occured.
    """

    exception_level: W24TechreadExceptionLevel
    """ Error level indicating the severity of the error
    """

    exception_type: W24TechreadExceptionType
    """ Error Type that allows the API-user to translate
    the message to a user-info.
    """


class W24TechreadMessage(BaseModel):
    """ Message format for messages that are sent
    from the server to the client.
    """
    request_id: UUID4
    """ unique UUID4 that is generated by the
    server to identify the request
    """

    message_type: W24TechreadMessageType
    """ Main Message Type (see W24TechreadMessageType)
    """

    message_subtype: W24TechreadMessageSubtype
    """ Message SubType (see W24TechreadMessageSubtype)
    """

    payload_dict: Optional[Dict] = None
    """ Payload dictionary containing the response
    as dict. The MessageType/Subtype will tell the
    interpreter how to turn the payload back into
    the corresponding object
    """

    payload_url: Optional[HttpUrl] = None
    """ For binary data, the API will return a download
    url which carries the data. This allows us to transfer
    larger images etc.
    """

    payload_bytes: Optional[bytes] = None
    """ Binary reference of the payload. This will only
    become available after the client has downloaded the
    payload_url.
    """

    exceptions: List[W24TechreadException] = []
    """ List of errors that occured during the processing
    """


class W24TechreadRequest(BaseModel):
    """ Definition of a W24DrawingReadRequest containing
    all the asks (i.e., things you want to learn about
    the technical drawing).
    """

    asks: List[W24AskUnion] = []
    """ List of asks """

    development_key: Optional[str] = None
    """ The development_key is used for internal purposes.
    It wil give you access to pre-release versions of our software.
    You will only understand the details if you...
    """

    client_version = __version__
    """ Current version of the client. For backward compatibility,
    this defaults to 'legacy'
    """


class W24PresignedPost(BaseModel):
    """ Details of the presigned post
    """

    fields_: Dict[str, str] = Field(alias='fields', default={})
    """ Dictionary of fields """

    url: HttpUrl
    """ Url to which the request shall be sent """


class W24TechreadInitResponse(BaseModel):
    """ API response to the Initialize request
    """

    drawing_presigned_post: W24PresignedPost
    """ Presigned Post for uploading the drawing """

    model_presigned_post: W24PresignedPost
    """ Presigned Post for uploading the model """
