import re
from typing import Optional

from pydantic import BaseModel, validator
from typing_extensions import Literal


class Parameters(BaseModel):
    image_file_b64: Optional[str] = ""
    image_url: Optional[str] = ""
    size: Optional[Literal['preview', 'full', 'auto']] = "preview"
    type: Optional[Literal['auto', 'product', 'person', 'car']] = "auto"  # Not supported at the moment
    format: Optional[Literal['auto', 'jpg', 'png', 'zip']] = "auto"
    roi: str = "0% 0% 100% 100%"
    crop: bool = False
    crop_margin: Optional[str] = "0px"
    scale: Optional[str] = "original"
    position: Optional[str] = "original"
    channels: Optional[Literal['rgba', 'alpha']] = "rgba"
    add_shadow: str = "false"  # Not supported at the moment
    semitransparency: str = "false"  # Not supported at the moment
    bg_color: Optional[str] = ""
    bg_image_url: Optional[str] = ""

    @validator('crop_margin')
    def crop_margin_validator(cls, value):
        if not re.match(r'[0-9]+(px|%)$', value):
            raise ValueError('crop_margin paramter is not valid')  # TODO: Add support of several values
        if '%' in value and (int(value[:-1]) < 0 or int(value[:-1]) > 100):
            raise ValueError('crop_margin mast be in range between 0% and 100%')
        return value

    @validator('scale')
    def scale_validator(cls, value):
        if value != 'original' and (
                not re.match(r'[0-9]+%$', value) or not int(value[:-1]) <= 100 or not int(value[:-1]) >= 10):
            raise ValueError('scale must be original or in between of 10% and 100%')

        if value == 'original':
            return 100

        return int(value[:-1])

    @validator('position')
    def position_validator(cls, value, values):
        if len(value.split(' ')) > 2:
            raise ValueError(
                'Position must be a value from 0 to 100 '
                'for both vertical and horizontal axises or for both axises respectively')

        if value == 'original':
            return 'original'
        elif len(value.split(' ')) == 1:
            return [int(value[:-1]), int(value[:-1])]
        else:
            return [int(value.split(' ')[0][:-1]), int(value.split(' ')[1][:-1])]

    @validator('bg_color')
    def bg_color_validator(cls, value):
        if not re.match(r'(#{0,1}[0-9a-f]{3}){0,2}$', value):
            raise ValueError('bg_color is not in hex')
        if len(value) and value[0] != '#':
            value = '#' + value
        return value
