package examplesgraphqlusers

/**
 * Generated by API Builder - https://www.apibuilder.io
 * Service version: 0.0.1
 * User agent: apibuilder app.apibuilder.io/apicollective/examples-graphql-users/0.0.1/go_1_5_client
 */

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"html"
	"io"
	"net/http"
	"strconv"
	"strings"
)

const UserAgent = "apibuilder app.apibuilder.io/apicollective/examples-graphql-users/0.0.1/go_1_5_client"
const Version = "0.0.1"
const VersionMajor = 0

type Client struct {
	HttpClient *http.Client
	Username   string
	Password   string
	BaseUrl    string
	Headers    http.Header
}

type ClientRequestBody struct {
	contentType string
	bytes       io.Reader
}

type UserStatus string

const (
	UserStatusActive UserStatus  = "active"
	UserStatusInactive           = "inactive"
	UserStatusUNDEFINED          = "UNDEFINED"
)

func UserStatusFromString(value string) UserStatus {
	switch strings.TrimSpace(strings.ToLower(value)) {
	case "active":
		return UserStatusActive
	case "inactive":
		return UserStatusInactive
	default:
		return UserStatusUNDEFINED
	}
}

type User struct {
	Id     string     `json:"id"`
	Status UserStatus `json:"status"`
	Email  string     `json:"email"`
	Name   string     `json:"name,omitempty"`
}

func UserFromMap(data interface{}) User {
	b, err := json.Marshal(data)
	if err == nil {
		return UserFromJson(bytes.NewReader(b))
	} else {
		panic(err)
	}
}

func UserFromJson(bytes io.Reader) User {
	var user User
	json.NewDecoder(bytes).Decode(&user)
	return user
}

type UserEmailPatchForm struct {
	Email string `json:"email"`
}

func UserEmailPatchFormFromMap(data interface{}) UserEmailPatchForm {
	b, err := json.Marshal(data)
	if err == nil {
		return UserEmailPatchFormFromJson(bytes.NewReader(b))
	} else {
		panic(err)
	}
}

func UserEmailPatchFormFromJson(bytes io.Reader) UserEmailPatchForm {
	var userEmailPatchForm UserEmailPatchForm
	json.NewDecoder(bytes).Decode(&userEmailPatchForm)
	return userEmailPatchForm
}

type UserForm struct {
	Status UserStatus `json:"status"`
	Email  string     `json:"email"`
	Name   string     `json:"name,omitempty"`
}

func UserFormFromMap(data interface{}) UserForm {
	b, err := json.Marshal(data)
	if err == nil {
		return UserFormFromJson(bytes.NewReader(b))
	} else {
		panic(err)
	}
}

func UserFormFromJson(bytes io.Reader) UserForm {
	var userForm UserForm
	json.NewDecoder(bytes).Decode(&userForm)
	return userForm
}

type UserStatusPatchForm struct {
	Status UserStatus `json:"status"`
}

func UserStatusPatchFormFromMap(data interface{}) UserStatusPatchForm {
	b, err := json.Marshal(data)
	if err == nil {
		return UserStatusPatchFormFromJson(bytes.NewReader(b))
	} else {
		panic(err)
	}
}

func UserStatusPatchFormFromJson(bytes io.Reader) UserStatusPatchForm {
	var userStatusPatchForm UserStatusPatchForm
	json.NewDecoder(bytes).Decode(&userStatusPatchForm)
	return userStatusPatchForm
}

type UserPatchForm struct {
	UserStatusPatchForm UserStatusPatchForm
	UserEmailPatchForm  UserEmailPatchForm
	Undefined           string
}

func UserPatchFormFromMap(data interface{}) UserPatchForm {
	b, err := json.Marshal(data)
	if err == nil {
		return UserPatchFormFromJson(bytes.NewReader(b))
	} else {
		panic(err)
	}
}

func UserPatchFormFromJson(bytes io.Reader) UserPatchForm {
	var el map[string]interface{}
	json.NewDecoder(bytes).Decode(&el)
	switch el["discriminator"] {
	case "user_status_patch_form":
		return UserPatchForm{UserStatusPatchForm: UserStatusPatchFormFromMap(el)}
	case "user_email_patch_form":
		return UserPatchForm{UserEmailPatchForm: UserEmailPatchFormFromMap(el)}
	default:
		return UserPatchForm{Undefined: el["discriminator"].(string)}
	}
}

type UsersGetByIdResponse struct {
	StatusCode int
	Response   *http.Response
	Error      error
	User       User
}

func UsersGetById(client Client, id string) UsersGetByIdResponse {

	requestUrl := fmt.Sprintf("%s/users/%s", client.BaseUrl, html.EscapeString(id))

	request, err := buildRequest(client, "GET", requestUrl, ClientRequestBody{})
	if err != nil {
		return UsersGetByIdResponse{Error: err}
	}

	resp, err := client.HttpClient.Do(request)
	if err != nil {
		return UsersGetByIdResponse{Error: err}
	}
	defer resp.Body.Close()

	switch resp.StatusCode {
	case 200:
		return UsersGetByIdResponse{StatusCode: resp.StatusCode, Response: resp, User: UserFromJson(resp.Body)}

	case 404:
		return UsersGetByIdResponse{StatusCode: resp.StatusCode, Response: resp}

	default:
		return UsersGetByIdResponse{StatusCode: resp.StatusCode, Response: resp, Error: errors.New(resp.Status)}
	}

}

type UsersPostResponse struct {
	StatusCode int
	Response   *http.Response
	Error      error
	User       User
	Values     []string
}

func UsersPost(client Client, userForm UserForm) UsersPostResponse {

	requestUrl := fmt.Sprintf("%s/users", client.BaseUrl)


	if "" == userForm.Status {
		userForm.Status = UserStatusFromString("active")
	}

	bodyDocument, err := json.Marshal(userForm)
	if err != nil {
		return UsersPostResponse{Error: err}
	}
	body := ClientRequestBody{contentType: "application/json", bytes: bytes.NewReader(bodyDocument)}

	request, err := buildRequest(client, "POST", requestUrl, body)
	if err != nil {
		return UsersPostResponse{Error: err}
	}

	resp, err := client.HttpClient.Do(request)
	if err != nil {
		return UsersPostResponse{Error: err}
	}
	defer resp.Body.Close()

	switch resp.StatusCode {
	case 201:
		return UsersPostResponse{StatusCode: resp.StatusCode, Response: resp, User: UserFromJson(resp.Body)}

	case 422:
		return UsersPostResponse{StatusCode: resp.StatusCode, Response: resp, Values: func() []string {
			var tmp []interface{}
			json.NewDecoder(resp.Body).Decode(&tmp)
			var all []string
			for _, el := range tmp {
				all = append(all, el.(string))
			}
			return all
		}()}

	default:
		return UsersPostResponse{StatusCode: resp.StatusCode, Response: resp, Error: errors.New(resp.Status)}
	}

}

type UsersPatchResponse struct {
	StatusCode int
	Response   *http.Response
	Error      error
	User       User
	Values     []string
}

func UsersPatch(client Client, userPatchForm UserPatchForm) UsersPatchResponse {

	requestUrl := fmt.Sprintf("%s/users", client.BaseUrl)

	bodyDocument, err := json.Marshal(userPatchForm)
	if err != nil {
		return UsersPatchResponse{Error: err}
	}
	body := ClientRequestBody{contentType: "application/json", bytes: bytes.NewReader(bodyDocument)}

	request, err := buildRequest(client, "PATCH", requestUrl, body)
	if err != nil {
		return UsersPatchResponse{Error: err}
	}

	resp, err := client.HttpClient.Do(request)
	if err != nil {
		return UsersPatchResponse{Error: err}
	}
	defer resp.Body.Close()

	switch resp.StatusCode {
	case 200:
		return UsersPatchResponse{StatusCode: resp.StatusCode, Response: resp, User: UserFromJson(resp.Body)}

	case 422:
		return UsersPatchResponse{StatusCode: resp.StatusCode, Response: resp, Values: func() []string {
			var tmp []interface{}
			json.NewDecoder(resp.Body).Decode(&tmp)
			var all []string
			for _, el := range tmp {
				all = append(all, el.(string))
			}
			return all
		}()}

	default:
		return UsersPatchResponse{StatusCode: resp.StatusCode, Response: resp, Error: errors.New(resp.Status)}
	}

}

type UsersDeleteByIdResponse struct {
	StatusCode int
	Response   *http.Response
	Error      error
}

func UsersDeleteById(client Client, id string) UsersDeleteByIdResponse {

	requestUrl := fmt.Sprintf("%s/users/%s", client.BaseUrl, html.EscapeString(id))

	request, err := buildRequest(client, "DELETE", requestUrl, ClientRequestBody{})
	if err != nil {
		return UsersDeleteByIdResponse{Error: err}
	}

	resp, err := client.HttpClient.Do(request)
	if err != nil {
		return UsersDeleteByIdResponse{Error: err}
	}
	defer resp.Body.Close()

	switch resp.StatusCode {
	case 204:
		return UsersDeleteByIdResponse{StatusCode: resp.StatusCode, Response: resp}

	case 404:
		return UsersDeleteByIdResponse{StatusCode: resp.StatusCode, Response: resp}

	default:
		return UsersDeleteByIdResponse{StatusCode: resp.StatusCode, Response: resp, Error: errors.New(resp.Status)}
	}

}

func buildRequest(client Client, method, urlStr string, body ClientRequestBody) (*http.Request, error) {

	request, err := http.NewRequest(method, urlStr, body.bytes)
	if err != nil {
		return nil, err
	}

	request.Header.Add("User-Agent",             UserAgent)
	request.Header.Add("X-Apidoc-Version",       Version)
	request.Header.Add("X-Apidoc-Version-Major", strconv.Itoa(VersionMajor))

	if client.Headers != nil {
		for key, values := range client.Headers {
			for _, value := range values {
				request.Header.Add(key, value)
			}
		}
	}

	if body.contentType != "" {
		request.Header.Add("Content-Type", body.contentType)
	}

	if client.Username != "" {
		request.SetBasicAuth(client.Username, client.Password)
	}

	return request, nil

}