from marshmallow import ValidationError, validate, validates_schema

from project.api import marshmallow
from project.api.fields import NumericStr
from project.api.schemas import SQLAlchemyBaseSchema
from project.models import Location


class LocationModelSchema(SQLAlchemyBaseSchema):
    class Meta:
        model = Location
        load_instance = True


class LocationBaseSchemaMixin(object):
    street = marshmallow.auto_field()
    postalCode = marshmallow.auto_field(validate=validate.Length(max=10))
    city = marshmallow.auto_field()
    state = marshmallow.auto_field()
    country = marshmallow.auto_field()
    latitude = NumericStr(
        validate=validate.Range(-90, 90, min_inclusive=False, max_inclusive=False),
        metadata={"description": "Latitude between (-90, 90)"},
        allow_none=True,
    )
    longitude = NumericStr(
        validate=validate.Range(-180, 180, min_inclusive=False, max_inclusive=False),
        metadata={"description": "Longitude between (-180, 180)"},
        allow_none=True,
    )

    @validates_schema
    def validate_location(self, data, **kwargs):
        lat_set = "latitude" in data and data["latitude"] is not None
        lon_set = "longitude" in data and data["longitude"] is not None

        if lat_set and not lon_set:
            raise ValidationError("If latitude is given, longitude is required.")

        if lon_set and not lat_set:
            raise ValidationError("If longitude is given, latitude is required.")


class LocationSchema(LocationModelSchema, LocationBaseSchemaMixin):
    pass


class LocationDumpSchema(LocationSchema):
    pass


class LocationSearchItemSchema(LocationSchema):
    pass


class LocationPostRequestSchema(LocationModelSchema, LocationBaseSchemaMixin):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.make_post_schema()


class LocationPatchRequestSchema(LocationModelSchema, LocationBaseSchemaMixin):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.make_patch_schema()
