// Code generated by go-uaa/generator; DO NOT EDIT.

package uaa

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
)

// GetUser with the given userID.
func (a *API) GetUser(userID string) (*User, error) {
	u := urlWithPath(*a.TargetURL, fmt.Sprintf("%s/%s", UsersEndpoint, userID))
	user := &User{}
	err := a.doJSON(http.MethodGet, &u, nil, user, true)
	if err != nil {
		return nil, err
	}
	return user, nil
}

// CreateUser creates the given user.
func (a *API) CreateUser(user User) (*User, error) {
	u := urlWithPath(*a.TargetURL, UsersEndpoint)
	created := &User{}
	j, err := json.Marshal(user)
	if err != nil {
		return nil, err
	}
	err = a.doJSON(http.MethodPost, &u, bytes.NewBuffer([]byte(j)), created, true)
	if err != nil {
		return nil, err
	}
	return created, nil
}

// UpdateUser updates the given user.
func (a *API) UpdateUser(user User) (*User, error) {
	u := urlWithPath(*a.TargetURL, fmt.Sprintf("%s/%s", UsersEndpoint, user.Identifier()))

	created := &User{}
	j, err := json.Marshal(user)
	if err != nil {
		return nil, err
	}
	err = a.doJSON(http.MethodPut, &u, bytes.NewBuffer([]byte(j)), created, true)
	if err != nil {
		return nil, err
	}
	return created, nil
}

// DeleteUser deletes the user with the given user ID.
func (a *API) DeleteUser(userID string) (*User, error) {
	if userID == "" {
		return nil, errors.New("userID cannot be blank")
	}
	u := urlWithPath(*a.TargetURL, fmt.Sprintf("%s/%s", UsersEndpoint, userID))
	deleted := &User{}
	err := a.doJSON(http.MethodDelete, &u, nil, deleted, true)
	if err != nil {
		return nil, err
	}
	return deleted, nil
}

// ListUsers with the given filter, sortBy, attributes, sortOrder, startIndex
// (1-based), and count (default 100).
// If successful, ListUsers returns the users and the total itemsPerPage of users for
// all pages. If unsuccessful, ListUsers returns the error.
func (a *API) ListUsers(filter string, sortBy string, attributes string, sortOrder SortOrder, startIndex int, itemsPerPage int) ([]User, Page, error) {
	u := urlWithPath(*a.TargetURL, UsersEndpoint)
	query := url.Values{}
	if filter != "" {
		query.Set("filter", filter)
	}
	if attributes != "" {
		query.Set("attributes", attributes)
	}
	if sortBy != "" {
		query.Set("sortBy", sortBy)
	}
	if sortOrder != "" {
		query.Set("sortOrder", string(sortOrder))
	}
	if startIndex == 0 {
		startIndex = 1
	}
	query.Set("startIndex", strconv.Itoa(startIndex))
	if itemsPerPage == 0 {
		itemsPerPage = 100
	}
	query.Set("count", strconv.Itoa(itemsPerPage))
	u.RawQuery = query.Encode()

	users := &paginatedUserList{}
	err := a.doJSON(http.MethodGet, &u, nil, users, true)
	if err != nil {
		return nil, Page{}, err
	}
	page := Page{
		StartIndex:   users.StartIndex,
		ItemsPerPage: users.ItemsPerPage,
		TotalResults: users.TotalResults,
	}
	return users.Resources, page, err
}

// ListAllUsers retrieves UAA users
func (a *API) ListAllUsers(filter string, sortBy string, attributes string, sortOrder SortOrder) ([]User, error) {
	page := Page{
		StartIndex:   1,
		ItemsPerPage: 100,
	}
	var (
		results     []User
		currentPage []User
		err         error
	)

	for {
		currentPage, page, err = a.ListUsers(filter, sortBy, attributes, sortOrder, page.StartIndex, page.ItemsPerPage)
		if err != nil {
			return nil, err
		}
		results = append(results, currentPage...)

		if (page.StartIndex + page.ItemsPerPage) > page.TotalResults {
			break
		}
		page.StartIndex = page.StartIndex + page.ItemsPerPage
	}
	return results, nil
}
