{-
   OpenAPI Petstore
   This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.

   The version of the OpenAPI document: 1.0.0

   NOTE: This file is auto generated by the openapi-generator.
   https://github.com/openapitools/openapi-generator.git

   DO NOT EDIT THIS FILE MANUALLY.

   For more info on generating Elm code, see https://eriktim.github.io/openapi-elm/
-}


module Api.Data exposing
    ( ApiResponse
    , Category
    , Order_, Order_Status(..), orderStatusVariants
    , Pet, PetStatus(..), petStatusVariants
    , Tag
    , User
    , encodeApiResponse
    , encodeCategory
    , encodeOrder
    , encodePet
    , encodeTag
    , encodeUser
    , apiResponseDecoder
    , categoryDecoder
    , orderDecoder
    , petDecoder
    , tagDecoder
    , userDecoder
    )

import Api
import Api.Time exposing (Posix)
import Dict
import Json.Decode
import Json.Encode


-- MODEL


{-| Describes the result of uploading an image resource
-}
type alias ApiResponse =
    { code : Maybe Int
    , type_ : Maybe String
    , message : Maybe String
    }


{-| A category for a pet
-}
type alias Category =
    { id : Maybe Int
    , name : Maybe String
    }


{-| An order for a pets from the pet store
-}
type alias Order_ =
    { id : Maybe Int
    , petId : Maybe Int
    , quantity : Maybe Int
    , shipDate : Maybe Posix
    , status : Maybe Order_Status
    , complete : Maybe Bool
    }


type Order_Status
    = Order_StatusPlaced
    | Order_StatusApproved
    | Order_StatusDelivered


orderStatusVariants : List Order_Status
orderStatusVariants =
    [ Order_StatusPlaced
    , Order_StatusApproved
    , Order_StatusDelivered
    ]


{-| A pet for sale in the pet store
-}
type alias Pet =
    { id : Maybe Int
    , category : Maybe Category
    , name : String
    , photoUrls : List String
    , tags : Maybe ( List Tag )
    , status : Maybe PetStatus
    }


type PetStatus
    = PetStatusAvailable
    | PetStatusPending
    | PetStatusSold


petStatusVariants : List PetStatus
petStatusVariants =
    [ PetStatusAvailable
    , PetStatusPending
    , PetStatusSold
    ]


{-| A tag for a pet
-}
type alias Tag =
    { id : Maybe Int
    , name : Maybe String
    }


{-| A User who is purchasing from the pet store
-}
type alias User =
    { id : Maybe Int
    , username : Maybe String
    , firstName : Maybe String
    , lastName : Maybe String
    , email : Maybe String
    , password : Maybe String
    , phone : Maybe String
    , userStatus : Maybe Int
    }


-- ENCODER


encodeApiResponse : ApiResponse -> Json.Encode.Value
encodeApiResponse =
    encodeObject << encodeApiResponsePairs


encodeApiResponseWithTag : ( String, String ) -> ApiResponse -> Json.Encode.Value
encodeApiResponseWithTag (tagField, tag) model =
    encodeObject (encodeApiResponsePairs model ++ [ encode tagField Json.Encode.string tag ])


encodeApiResponsePairs : ApiResponse -> List EncodedField
encodeApiResponsePairs model =
    let
        pairs =
            [ maybeEncode "code" Json.Encode.int model.code
            , maybeEncode "type" Json.Encode.string model.type_
            , maybeEncode "message" Json.Encode.string model.message
            ]
    in
    pairs


encodeCategory : Category -> Json.Encode.Value
encodeCategory =
    encodeObject << encodeCategoryPairs


encodeCategoryWithTag : ( String, String ) -> Category -> Json.Encode.Value
encodeCategoryWithTag (tagField, tag) model =
    encodeObject (encodeCategoryPairs model ++ [ encode tagField Json.Encode.string tag ])


encodeCategoryPairs : Category -> List EncodedField
encodeCategoryPairs model =
    let
        pairs =
            [ maybeEncode "id" Json.Encode.int model.id
            , maybeEncode "name" Json.Encode.string model.name
            ]
    in
    pairs


encodeOrder : Order_ -> Json.Encode.Value
encodeOrder =
    encodeObject << encodeOrderPairs


encodeOrderWithTag : ( String, String ) -> Order_ -> Json.Encode.Value
encodeOrderWithTag (tagField, tag) model =
    encodeObject (encodeOrderPairs model ++ [ encode tagField Json.Encode.string tag ])


encodeOrderPairs : Order_ -> List EncodedField
encodeOrderPairs model =
    let
        pairs =
            [ maybeEncode "id" Json.Encode.int model.id
            , maybeEncode "petId" Json.Encode.int model.petId
            , maybeEncode "quantity" Json.Encode.int model.quantity
            , maybeEncode "shipDate" Api.Time.encodeDateTime model.shipDate
            , maybeEncode "status" encodeOrderStatus model.status
            , maybeEncode "complete" Json.Encode.bool model.complete
            ]
    in
    pairs

stringFromOrder_Status : Order_Status -> String
stringFromOrder_Status model =
    case model of
        Order_StatusPlaced ->
            "placed"

        Order_StatusApproved ->
            "approved"

        Order_StatusDelivered ->
            "delivered"


encodeOrderStatus : Order_Status -> Json.Encode.Value
encodeOrderStatus =
    Json.Encode.string << stringFromOrder_Status



encodePet : Pet -> Json.Encode.Value
encodePet =
    encodeObject << encodePetPairs


encodePetWithTag : ( String, String ) -> Pet -> Json.Encode.Value
encodePetWithTag (tagField, tag) model =
    encodeObject (encodePetPairs model ++ [ encode tagField Json.Encode.string tag ])


encodePetPairs : Pet -> List EncodedField
encodePetPairs model =
    let
        pairs =
            [ maybeEncode "id" Json.Encode.int model.id
            , maybeEncode "category" encodeCategory model.category
            , encode "name" Json.Encode.string model.name
            , encode "photoUrls" (Json.Encode.list Json.Encode.string) model.photoUrls
            , maybeEncode "tags" (Json.Encode.list encodeTag) model.tags
            , maybeEncode "status" encodePetStatus model.status
            ]
    in
    pairs

stringFromPetStatus : PetStatus -> String
stringFromPetStatus model =
    case model of
        PetStatusAvailable ->
            "available"

        PetStatusPending ->
            "pending"

        PetStatusSold ->
            "sold"


encodePetStatus : PetStatus -> Json.Encode.Value
encodePetStatus =
    Json.Encode.string << stringFromPetStatus



encodeTag : Tag -> Json.Encode.Value
encodeTag =
    encodeObject << encodeTagPairs


encodeTagWithTag : ( String, String ) -> Tag -> Json.Encode.Value
encodeTagWithTag (tagField, tag) model =
    encodeObject (encodeTagPairs model ++ [ encode tagField Json.Encode.string tag ])


encodeTagPairs : Tag -> List EncodedField
encodeTagPairs model =
    let
        pairs =
            [ maybeEncode "id" Json.Encode.int model.id
            , maybeEncode "name" Json.Encode.string model.name
            ]
    in
    pairs


encodeUser : User -> Json.Encode.Value
encodeUser =
    encodeObject << encodeUserPairs


encodeUserWithTag : ( String, String ) -> User -> Json.Encode.Value
encodeUserWithTag (tagField, tag) model =
    encodeObject (encodeUserPairs model ++ [ encode tagField Json.Encode.string tag ])


encodeUserPairs : User -> List EncodedField
encodeUserPairs model =
    let
        pairs =
            [ maybeEncode "id" Json.Encode.int model.id
            , maybeEncode "username" Json.Encode.string model.username
            , maybeEncode "firstName" Json.Encode.string model.firstName
            , maybeEncode "lastName" Json.Encode.string model.lastName
            , maybeEncode "email" Json.Encode.string model.email
            , maybeEncode "password" Json.Encode.string model.password
            , maybeEncode "phone" Json.Encode.string model.phone
            , maybeEncode "userStatus" Json.Encode.int model.userStatus
            ]
    in
    pairs


-- DECODER


apiResponseDecoder : Json.Decode.Decoder ApiResponse
apiResponseDecoder =
    Json.Decode.succeed ApiResponse
        |> maybeDecode "code" Json.Decode.int Nothing
        |> maybeDecode "type" Json.Decode.string Nothing
        |> maybeDecode "message" Json.Decode.string Nothing


categoryDecoder : Json.Decode.Decoder Category
categoryDecoder =
    Json.Decode.succeed Category
        |> maybeDecode "id" Json.Decode.int Nothing
        |> maybeDecode "name" Json.Decode.string Nothing


orderDecoder : Json.Decode.Decoder Order_
orderDecoder =
    Json.Decode.succeed Order_
        |> maybeDecode "id" Json.Decode.int Nothing
        |> maybeDecode "petId" Json.Decode.int Nothing
        |> maybeDecode "quantity" Json.Decode.int Nothing
        |> maybeDecode "shipDate" Api.Time.dateTimeDecoder Nothing
        |> maybeDecode "status" orderStatusDecoder Nothing
        |> maybeDecode "complete" Json.Decode.bool (Just False)


orderStatusDecoder : Json.Decode.Decoder Order_Status
orderStatusDecoder =
    Json.Decode.string
        |> Json.Decode.andThen
            (\value ->
                case value of
                    "placed" ->
                        Json.Decode.succeed Order_StatusPlaced

                    "approved" ->
                        Json.Decode.succeed Order_StatusApproved

                    "delivered" ->
                        Json.Decode.succeed Order_StatusDelivered

                    other ->
                        Json.Decode.fail <| "Unknown type: " ++ other
            )



petDecoder : Json.Decode.Decoder Pet
petDecoder =
    Json.Decode.succeed Pet
        |> maybeDecode "id" Json.Decode.int Nothing
        |> maybeDecode "category" categoryDecoder Nothing
        |> decode "name" Json.Decode.string 
        |> decode "photoUrls" (Json.Decode.list Json.Decode.string) 
        |> maybeDecode "tags" (Json.Decode.list tagDecoder) Nothing
        |> maybeDecode "status" petStatusDecoder Nothing


petStatusDecoder : Json.Decode.Decoder PetStatus
petStatusDecoder =
    Json.Decode.string
        |> Json.Decode.andThen
            (\value ->
                case value of
                    "available" ->
                        Json.Decode.succeed PetStatusAvailable

                    "pending" ->
                        Json.Decode.succeed PetStatusPending

                    "sold" ->
                        Json.Decode.succeed PetStatusSold

                    other ->
                        Json.Decode.fail <| "Unknown type: " ++ other
            )



tagDecoder : Json.Decode.Decoder Tag
tagDecoder =
    Json.Decode.succeed Tag
        |> maybeDecode "id" Json.Decode.int Nothing
        |> maybeDecode "name" Json.Decode.string Nothing


userDecoder : Json.Decode.Decoder User
userDecoder =
    Json.Decode.succeed User
        |> maybeDecode "id" Json.Decode.int Nothing
        |> maybeDecode "username" Json.Decode.string Nothing
        |> maybeDecode "firstName" Json.Decode.string Nothing
        |> maybeDecode "lastName" Json.Decode.string Nothing
        |> maybeDecode "email" Json.Decode.string Nothing
        |> maybeDecode "password" Json.Decode.string Nothing
        |> maybeDecode "phone" Json.Decode.string Nothing
        |> maybeDecode "userStatus" Json.Decode.int Nothing




-- HELPER


type alias EncodedField =
    Maybe ( String, Json.Encode.Value )


encodeObject : List EncodedField -> Json.Encode.Value
encodeObject =
    Json.Encode.object << List.filterMap identity


encode : String -> (a -> Json.Encode.Value) -> a -> EncodedField
encode key encoder value =
    Just ( key, encoder value )


encodeNullable : String -> (a -> Json.Encode.Value) -> Maybe a -> EncodedField
encodeNullable key encoder value =
    Just ( key, Maybe.withDefault Json.Encode.null (Maybe.map encoder value) )


maybeEncode : String -> (a -> Json.Encode.Value) -> Maybe a -> EncodedField
maybeEncode key encoder =
    Maybe.map (Tuple.pair key << encoder)


maybeEncodeNullable : String -> (a -> Json.Encode.Value) -> Maybe a -> EncodedField
maybeEncodeNullable =
    encodeNullable


decode : String -> Json.Decode.Decoder a -> Json.Decode.Decoder (a -> b) -> Json.Decode.Decoder b
decode key decoder =
    decodeChain (Json.Decode.field key decoder)


decodeLazy : (a -> c) -> String -> Json.Decode.Decoder a -> Json.Decode.Decoder (c -> b) -> Json.Decode.Decoder b
decodeLazy f key decoder =
    decodeChainLazy f (Json.Decode.field key decoder)


decodeNullable : String -> Json.Decode.Decoder a -> Json.Decode.Decoder (Maybe a -> b) -> Json.Decode.Decoder b
decodeNullable key decoder =
    decodeChain (maybeField key decoder Nothing)


decodeNullableLazy : (Maybe a -> c) -> String -> Json.Decode.Decoder a -> Json.Decode.Decoder (c -> b) -> Json.Decode.Decoder b
decodeNullableLazy f key decoder =
    decodeChainLazy f (maybeField key decoder Nothing)


maybeDecode : String -> Json.Decode.Decoder a -> Maybe a -> Json.Decode.Decoder (Maybe a -> b) -> Json.Decode.Decoder b
maybeDecode key decoder fallback =
    -- let's be kind to null-values as well
    decodeChain (maybeField key decoder fallback)


maybeDecodeLazy : (Maybe a -> c) -> String -> Json.Decode.Decoder a -> Maybe a -> Json.Decode.Decoder (c -> b) -> Json.Decode.Decoder b
maybeDecodeLazy f key decoder fallback =
    -- let's be kind to null-values as well
    decodeChainLazy f (maybeField key decoder fallback)


maybeDecodeNullable : String -> Json.Decode.Decoder a -> Maybe a -> Json.Decode.Decoder (Maybe a -> b) -> Json.Decode.Decoder b
maybeDecodeNullable key decoder fallback =
    decodeChain (maybeField key decoder fallback)


maybeDecodeNullableLazy : (Maybe a -> c) -> String -> Json.Decode.Decoder a -> Maybe a -> Json.Decode.Decoder (c -> b) -> Json.Decode.Decoder b
maybeDecodeNullableLazy f key decoder fallback =
    decodeChainLazy f (maybeField key decoder fallback)


maybeField : String -> Json.Decode.Decoder a -> Maybe a -> Json.Decode.Decoder (Maybe a)
maybeField key decoder fallback =
    let
        fieldDecoder =
            Json.Decode.field key Json.Decode.value

        valueDecoder =
            Json.Decode.oneOf [ Json.Decode.map Just decoder, Json.Decode.null fallback ]

        decodeObject rawObject =
            case Json.Decode.decodeValue fieldDecoder rawObject of
                Ok rawValue ->
                    case Json.Decode.decodeValue valueDecoder rawValue of
                        Ok value ->
                            Json.Decode.succeed value

                        Err error ->
                            Json.Decode.fail (Json.Decode.errorToString error)

                Err _ ->
                    Json.Decode.succeed fallback
    in
    Json.Decode.value
        |> Json.Decode.andThen decodeObject


decodeChain : Json.Decode.Decoder a -> Json.Decode.Decoder (a -> b) -> Json.Decode.Decoder b
decodeChain =
    Json.Decode.map2 (|>)


decodeChainLazy : (a -> c) -> Json.Decode.Decoder a -> Json.Decode.Decoder (c -> b) -> Json.Decode.Decoder b
decodeChainLazy f =
    decodeChain << Json.Decode.map f