from __future__ import annotations

from collections.abc import Mapping
from typing import TYPE_CHECKING, Any, TypeVar, cast

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..models.default_page_enum import DefaultPageEnum
from ..models.theme_enum import ThemeEnum
from ..models.user_preference_nav_text_color_enum import UserPreferenceNavTextColorEnum
from ..types import UNSET, Unset

if TYPE_CHECKING:
    from ..models.food_inherit_field import FoodInheritField
    from ..models.user import User
    from ..models.user_file_view import UserFileView


T = TypeVar("T", bound="UserPreference")


@_attrs_define
class UserPreference:
    """Adds nested create feature

    Attributes:
        user (User): Adds nested create feature
        food_inherit_default (FoodInheritField): Moves `UniqueValidator`'s from the validation stage to the save stage.
            It solves the problem with nested validation for unique fields on update.

            If you want more details, you can read related issues and articles:
            https://github.com/beda-software/drf-writable-nested/issues/1
            http://www.django-rest-framework.org/api-guide/validators/#updating-nested-serializers

            Example of usage:
            ```
                class Child(models.Model):
                field = models.CharField(unique=True)


            class Parent(models.Model):
                child = models.ForeignKey('Child')


            class ChildSerializer(UniqueFieldsMixin, serializers.ModelSerializer):
                class Meta:
                    model = Child


            class ParentSerializer(NestedUpdateMixin, serializers.ModelSerializer):
                child = ChildSerializer()

                class Meta:
                    model = Parent
            ```

            Note: `UniqueFieldsMixin` must be applied only on the serializer
            which has unique fields.

            Note: When you are using both mixins
            (`UniqueFieldsMixin` and `NestedCreateMixin` or `NestedUpdateMixin`)
            you should put `UniqueFieldsMixin` ahead.
        food_children_exist (bool):
        image (None | Unset | UserFileView):
        theme (ThemeEnum | Unset): * `TANDOOR` - Tandoor
            * `BOOTSTRAP` - Bootstrap
            * `DARKLY` - Darkly
            * `FLATLY` - Flatly
            * `SUPERHERO` - Superhero
            * `TANDOOR_DARK` - Tandoor Dark (INCOMPLETE)
        nav_bg_color (str | Unset):
        nav_text_color (UserPreferenceNavTextColorEnum | Unset): * `LIGHT` - Light
            * `DARK` - Dark
        nav_show_logo (bool | Unset):
        default_unit (str | Unset):
        default_page (DefaultPageEnum | Unset): * `SEARCH` - Search
            * `PLAN` - Meal-Plan
            * `BOOKS` - Books
            * `SHOPPING` - Shopping
        use_fractions (bool | Unset):
        use_kj (bool | Unset):
        plan_share (list[User] | None | Unset):
        nav_sticky (bool | Unset):
        ingredient_decimals (int | Unset):
        comments (bool | Unset):
        shopping_auto_sync (int | Unset):
        mealplan_autoadd_shopping (bool | Unset):
        default_delay (float | Unset):
        mealplan_autoinclude_related (bool | Unset):
        mealplan_autoexclude_onhand (bool | Unset):
        shopping_share (list[User] | None | Unset):
        shopping_recent_days (int | Unset):
        csv_delim (str | Unset):
        csv_prefix (str | Unset):
        shopping_update_food_lists (bool | Unset):
        filter_to_supermarket (bool | Unset):
        shopping_add_onhand (bool | Unset):
        left_handed (bool | Unset):
        show_step_ingredients (bool | Unset):
    """

    user: User
    food_inherit_default: FoodInheritField
    food_children_exist: bool
    image: None | Unset | UserFileView = UNSET
    theme: ThemeEnum | Unset = UNSET
    nav_bg_color: str | Unset = UNSET
    nav_text_color: UserPreferenceNavTextColorEnum | Unset = UNSET
    nav_show_logo: bool | Unset = UNSET
    default_unit: str | Unset = UNSET
    default_page: DefaultPageEnum | Unset = UNSET
    use_fractions: bool | Unset = UNSET
    use_kj: bool | Unset = UNSET
    plan_share: list[User] | None | Unset = UNSET
    nav_sticky: bool | Unset = UNSET
    ingredient_decimals: int | Unset = UNSET
    comments: bool | Unset = UNSET
    shopping_auto_sync: int | Unset = UNSET
    mealplan_autoadd_shopping: bool | Unset = UNSET
    default_delay: float | Unset = UNSET
    mealplan_autoinclude_related: bool | Unset = UNSET
    mealplan_autoexclude_onhand: bool | Unset = UNSET
    shopping_share: list[User] | None | Unset = UNSET
    shopping_recent_days: int | Unset = UNSET
    csv_delim: str | Unset = UNSET
    csv_prefix: str | Unset = UNSET
    shopping_update_food_lists: bool | Unset = UNSET
    filter_to_supermarket: bool | Unset = UNSET
    shopping_add_onhand: bool | Unset = UNSET
    left_handed: bool | Unset = UNSET
    show_step_ingredients: bool | Unset = UNSET
    additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

    def to_dict(self) -> dict[str, Any]:
        from ..models.user_file_view import UserFileView

        user = self.user.to_dict()

        food_inherit_default = self.food_inherit_default.to_dict()

        food_children_exist = self.food_children_exist

        image: dict[str, Any] | None | Unset
        if isinstance(self.image, Unset):
            image = UNSET
        elif isinstance(self.image, UserFileView):
            image = self.image.to_dict()
        else:
            image = self.image

        theme: str | Unset = UNSET
        if not isinstance(self.theme, Unset):
            theme = self.theme.value

        nav_bg_color = self.nav_bg_color

        nav_text_color: str | Unset = UNSET
        if not isinstance(self.nav_text_color, Unset):
            nav_text_color = self.nav_text_color.value

        nav_show_logo = self.nav_show_logo

        default_unit = self.default_unit

        default_page: str | Unset = UNSET
        if not isinstance(self.default_page, Unset):
            default_page = self.default_page.value

        use_fractions = self.use_fractions

        use_kj = self.use_kj

        plan_share: list[dict[str, Any]] | None | Unset
        if isinstance(self.plan_share, Unset):
            plan_share = UNSET
        elif isinstance(self.plan_share, list):
            plan_share = []
            for plan_share_type_0_item_data in self.plan_share:
                plan_share_type_0_item = plan_share_type_0_item_data.to_dict()
                plan_share.append(plan_share_type_0_item)

        else:
            plan_share = self.plan_share

        nav_sticky = self.nav_sticky

        ingredient_decimals = self.ingredient_decimals

        comments = self.comments

        shopping_auto_sync = self.shopping_auto_sync

        mealplan_autoadd_shopping = self.mealplan_autoadd_shopping

        default_delay = self.default_delay

        mealplan_autoinclude_related = self.mealplan_autoinclude_related

        mealplan_autoexclude_onhand = self.mealplan_autoexclude_onhand

        shopping_share: list[dict[str, Any]] | None | Unset
        if isinstance(self.shopping_share, Unset):
            shopping_share = UNSET
        elif isinstance(self.shopping_share, list):
            shopping_share = []
            for shopping_share_type_0_item_data in self.shopping_share:
                shopping_share_type_0_item = shopping_share_type_0_item_data.to_dict()
                shopping_share.append(shopping_share_type_0_item)

        else:
            shopping_share = self.shopping_share

        shopping_recent_days = self.shopping_recent_days

        csv_delim = self.csv_delim

        csv_prefix = self.csv_prefix

        shopping_update_food_lists = self.shopping_update_food_lists

        filter_to_supermarket = self.filter_to_supermarket

        shopping_add_onhand = self.shopping_add_onhand

        left_handed = self.left_handed

        show_step_ingredients = self.show_step_ingredients

        field_dict: dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update(
            {
                "user": user,
                "food_inherit_default": food_inherit_default,
                "food_children_exist": food_children_exist,
            }
        )
        if image is not UNSET:
            field_dict["image"] = image
        if theme is not UNSET:
            field_dict["theme"] = theme
        if nav_bg_color is not UNSET:
            field_dict["nav_bg_color"] = nav_bg_color
        if nav_text_color is not UNSET:
            field_dict["nav_text_color"] = nav_text_color
        if nav_show_logo is not UNSET:
            field_dict["nav_show_logo"] = nav_show_logo
        if default_unit is not UNSET:
            field_dict["default_unit"] = default_unit
        if default_page is not UNSET:
            field_dict["default_page"] = default_page
        if use_fractions is not UNSET:
            field_dict["use_fractions"] = use_fractions
        if use_kj is not UNSET:
            field_dict["use_kj"] = use_kj
        if plan_share is not UNSET:
            field_dict["plan_share"] = plan_share
        if nav_sticky is not UNSET:
            field_dict["nav_sticky"] = nav_sticky
        if ingredient_decimals is not UNSET:
            field_dict["ingredient_decimals"] = ingredient_decimals
        if comments is not UNSET:
            field_dict["comments"] = comments
        if shopping_auto_sync is not UNSET:
            field_dict["shopping_auto_sync"] = shopping_auto_sync
        if mealplan_autoadd_shopping is not UNSET:
            field_dict["mealplan_autoadd_shopping"] = mealplan_autoadd_shopping
        if default_delay is not UNSET:
            field_dict["default_delay"] = default_delay
        if mealplan_autoinclude_related is not UNSET:
            field_dict["mealplan_autoinclude_related"] = mealplan_autoinclude_related
        if mealplan_autoexclude_onhand is not UNSET:
            field_dict["mealplan_autoexclude_onhand"] = mealplan_autoexclude_onhand
        if shopping_share is not UNSET:
            field_dict["shopping_share"] = shopping_share
        if shopping_recent_days is not UNSET:
            field_dict["shopping_recent_days"] = shopping_recent_days
        if csv_delim is not UNSET:
            field_dict["csv_delim"] = csv_delim
        if csv_prefix is not UNSET:
            field_dict["csv_prefix"] = csv_prefix
        if shopping_update_food_lists is not UNSET:
            field_dict["shopping_update_food_lists"] = shopping_update_food_lists
        if filter_to_supermarket is not UNSET:
            field_dict["filter_to_supermarket"] = filter_to_supermarket
        if shopping_add_onhand is not UNSET:
            field_dict["shopping_add_onhand"] = shopping_add_onhand
        if left_handed is not UNSET:
            field_dict["left_handed"] = left_handed
        if show_step_ingredients is not UNSET:
            field_dict["show_step_ingredients"] = show_step_ingredients

        return field_dict

    @classmethod
    def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
        from ..models.food_inherit_field import FoodInheritField
        from ..models.user import User
        from ..models.user_file_view import UserFileView

        d = dict(src_dict)
        user = User.from_dict(d.pop("user"))

        food_inherit_default = FoodInheritField.from_dict(d.pop("food_inherit_default"))

        food_children_exist = d.pop("food_children_exist")

        def _parse_image(data: object) -> None | Unset | UserFileView:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            try:
                if not isinstance(data, dict):
                    raise TypeError()
                image_type_1 = UserFileView.from_dict(data)

                return image_type_1
            except (TypeError, ValueError, AttributeError, KeyError):
                pass
            return cast(None | Unset | UserFileView, data)

        image = _parse_image(d.pop("image", UNSET))

        _theme = d.pop("theme", UNSET)
        theme: ThemeEnum | Unset
        if isinstance(_theme, Unset):
            theme = UNSET
        else:
            theme = ThemeEnum(_theme)

        nav_bg_color = d.pop("nav_bg_color", UNSET)

        _nav_text_color = d.pop("nav_text_color", UNSET)
        nav_text_color: UserPreferenceNavTextColorEnum | Unset
        if isinstance(_nav_text_color, Unset):
            nav_text_color = UNSET
        else:
            nav_text_color = UserPreferenceNavTextColorEnum(_nav_text_color)

        nav_show_logo = d.pop("nav_show_logo", UNSET)

        default_unit = d.pop("default_unit", UNSET)

        _default_page = d.pop("default_page", UNSET)
        default_page: DefaultPageEnum | Unset
        if isinstance(_default_page, Unset):
            default_page = UNSET
        else:
            default_page = DefaultPageEnum(_default_page)

        use_fractions = d.pop("use_fractions", UNSET)

        use_kj = d.pop("use_kj", UNSET)

        def _parse_plan_share(data: object) -> list[User] | None | Unset:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            try:
                if not isinstance(data, list):
                    raise TypeError()
                plan_share_type_0 = []
                _plan_share_type_0 = data
                for plan_share_type_0_item_data in _plan_share_type_0:
                    plan_share_type_0_item = User.from_dict(plan_share_type_0_item_data)

                    plan_share_type_0.append(plan_share_type_0_item)

                return plan_share_type_0
            except (TypeError, ValueError, AttributeError, KeyError):
                pass
            return cast(list[User] | None | Unset, data)

        plan_share = _parse_plan_share(d.pop("plan_share", UNSET))

        nav_sticky = d.pop("nav_sticky", UNSET)

        ingredient_decimals = d.pop("ingredient_decimals", UNSET)

        comments = d.pop("comments", UNSET)

        shopping_auto_sync = d.pop("shopping_auto_sync", UNSET)

        mealplan_autoadd_shopping = d.pop("mealplan_autoadd_shopping", UNSET)

        default_delay = d.pop("default_delay", UNSET)

        mealplan_autoinclude_related = d.pop("mealplan_autoinclude_related", UNSET)

        mealplan_autoexclude_onhand = d.pop("mealplan_autoexclude_onhand", UNSET)

        def _parse_shopping_share(data: object) -> list[User] | None | Unset:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            try:
                if not isinstance(data, list):
                    raise TypeError()
                shopping_share_type_0 = []
                _shopping_share_type_0 = data
                for shopping_share_type_0_item_data in _shopping_share_type_0:
                    shopping_share_type_0_item = User.from_dict(shopping_share_type_0_item_data)

                    shopping_share_type_0.append(shopping_share_type_0_item)

                return shopping_share_type_0
            except (TypeError, ValueError, AttributeError, KeyError):
                pass
            return cast(list[User] | None | Unset, data)

        shopping_share = _parse_shopping_share(d.pop("shopping_share", UNSET))

        shopping_recent_days = d.pop("shopping_recent_days", UNSET)

        csv_delim = d.pop("csv_delim", UNSET)

        csv_prefix = d.pop("csv_prefix", UNSET)

        shopping_update_food_lists = d.pop("shopping_update_food_lists", UNSET)

        filter_to_supermarket = d.pop("filter_to_supermarket", UNSET)

        shopping_add_onhand = d.pop("shopping_add_onhand", UNSET)

        left_handed = d.pop("left_handed", UNSET)

        show_step_ingredients = d.pop("show_step_ingredients", UNSET)

        user_preference = cls(
            user=user,
            food_inherit_default=food_inherit_default,
            food_children_exist=food_children_exist,
            image=image,
            theme=theme,
            nav_bg_color=nav_bg_color,
            nav_text_color=nav_text_color,
            nav_show_logo=nav_show_logo,
            default_unit=default_unit,
            default_page=default_page,
            use_fractions=use_fractions,
            use_kj=use_kj,
            plan_share=plan_share,
            nav_sticky=nav_sticky,
            ingredient_decimals=ingredient_decimals,
            comments=comments,
            shopping_auto_sync=shopping_auto_sync,
            mealplan_autoadd_shopping=mealplan_autoadd_shopping,
            default_delay=default_delay,
            mealplan_autoinclude_related=mealplan_autoinclude_related,
            mealplan_autoexclude_onhand=mealplan_autoexclude_onhand,
            shopping_share=shopping_share,
            shopping_recent_days=shopping_recent_days,
            csv_delim=csv_delim,
            csv_prefix=csv_prefix,
            shopping_update_food_lists=shopping_update_food_lists,
            filter_to_supermarket=filter_to_supermarket,
            shopping_add_onhand=shopping_add_onhand,
            left_handed=left_handed,
            show_step_ingredients=show_step_ingredients,
        )

        user_preference.additional_properties = d
        return user_preference

    @property
    def additional_keys(self) -> list[str]:
        return list(self.additional_properties.keys())

    def __getitem__(self, key: str) -> Any:
        return self.additional_properties[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self.additional_properties[key] = value

    def __delitem__(self, key: str) -> None:
        del self.additional_properties[key]

    def __contains__(self, key: str) -> bool:
        return key in self.additional_properties
