// Copyright 2019 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Code generated file. DO NOT EDIT.

// Package wrapnewlines provides access to the Example API.
//
// Usage example:
//
//   import "google.golang.org/api/wrapnewlines/v1"
//   ...
//   wrapnewlinesService, err := wrapnewlines.New(oauthHttpClient)
package wrapnewlines // import "google.golang.org/api/wrapnewlines/v1"

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	gensupport "google.golang.org/api/gensupport"
	googleapi "google.golang.org/api/googleapi"
)

// Always reference these packages, just in case the auto-generated code
// below doesn't.
var _ = bytes.NewBuffer
var _ = strconv.Itoa
var _ = fmt.Sprintf
var _ = json.NewDecoder
var _ = io.Copy
var _ = url.Parse
var _ = gensupport.MarshalJSON
var _ = googleapi.Version
var _ = errors.New
var _ = strings.Replace
var _ = context.Canceled

const apiId = "wrapnewlines:v1"
const apiName = "wrapnewlines"
const apiVersion = "v1"
const basePath = "https://www.googleapis.com/discovery/v1/apis"

func New(client *http.Client) (*Service, error) {
	if client == nil {
		return nil, errors.New("client is nil")
	}
	s := &Service{client: client, BasePath: basePath}
	return s, nil
}

type Service struct {
	client    *http.Client
	BasePath  string // API endpoint base URL
	UserAgent string // optional additional User-Agent fragment
}

func (s *Service) userAgent() string {
	if s.UserAgent == "" {
		return googleapi.UserAgent
	}
	return googleapi.UserAgent + " " + s.UserAgent
}

// Thing: don't care
type Thing struct {
	// BoolEmptyDefaultA:
	// Nonempty default: no
	// Unfortunate default: no
	BoolEmptyDefaultA bool `json:"bool_empty_default_a,omitempty"`

	// BoolEmptyDefaultB:
	// Nonempty default: no
	// Unfortunate default: no
	BoolEmptyDefaultB bool `json:"bool_empty_default_b,omitempty"`

	// BoolNonemptyDefault:
	// Nonempty default: yes
	// Unfortunate default: yes
	//
	// Default: true
	BoolNonemptyDefault *bool `json:"bool_nonempty_default,omitempty"`

	// NumericEmptyDefaultA:
	// Nonempty default: no
	// Unfortunate default: no
	NumericEmptyDefaultA int64 `json:"numeric_empty_default_a,omitempty,string"`

	// NumericEmptyDefaultB:
	// Nonempty default: no
	// Unfortunate default: no
	NumericEmptyDefaultB int64 `json:"numeric_empty_default_b,omitempty,string"`

	// NumericEmptyDefaultC:
	// Nonempty default: no
	// Unfortunate default: no
	NumericEmptyDefaultC int64 `json:"numeric_empty_default_c,omitempty,string"`

	// NumericEmptyDefaultD:
	// Nonempty default: no
	// Unfortunate default: no
	NumericEmptyDefaultD float64 `json:"numeric_empty_default_d,omitempty"`

	// NumericEmptyDefaultE:
	// Nonempty default: no
	// Unfortunate default: no
	NumericEmptyDefaultE float64 `json:"numeric_empty_default_e,omitempty"`

	// NumericNonemptyDefaultA:
	// Nonempty default: yes
	// Unfortunate default: yes
	// string encoded, so will not be represented as pointer.
	//
	// Default: 1
	NumericNonemptyDefaultA *int64 `json:"numeric_nonempty_default_a,omitempty,string"`

	// NumericNonemptyDefaultB:
	// Nonempty default: yes
	// Unfortunate default: yes
	//
	// Default: 0.001
	NumericNonemptyDefaultB *float64 `json:"numeric_nonempty_default_b,omitempty"`

	// StringEmptyDefaultDoesntAcceptEmpty:
	// Nonempty default: no
	// Accepts empty value: no
	// Unfortunate default: no
	StringEmptyDefaultDoesntAcceptEmpty string `json:"string_empty_default_doesnt_accept_empty,omitempty"`

	// StringEmptyDefaultEnumAcceptsEmpty:
	// Nonempty default: no
	// Accepts empty value: yes (enum)
	// Unfortunate default: no
	//
	// Possible values:
	//   "" (default)
	//   "value"
	StringEmptyDefaultEnumAcceptsEmpty string `json:"string_empty_default_enum_accepts_empty,omitempty"`

	// StringEmptyDefaultEnumDoesntAcceptEmpty:
	// Nonempty default: no
	// Accepts empty value: no (enum)
	// Unfortunate default: no
	//
	// Possible values:
	//   "value"
	StringEmptyDefaultEnumDoesntAcceptEmpty string `json:"string_empty_default_enum_doesnt_accept_empty,omitempty"`

	// StringEmptyDefaultPatternAcceptsEmpty:
	// Nonempty default: no
	// Accepts empty value: yes (pattern)
	// Unfortunate default: no
	StringEmptyDefaultPatternAcceptsEmpty string `json:"string_empty_default_pattern_accepts_empty,omitempty"`

	// StringEmptyDefaultPatternDoesntAcceptEmpty:
	// Nonempty default: no
	// Accepts empty value: no (pattern)
	// Unfortunate default: no
	StringEmptyDefaultPatternDoesntAcceptEmpty string `json:"string_empty_default_pattern_doesnt_accept_empty,omitempty"`

	// StringNonemptyDefaultDoesntAcceptEmpty:
	// Nonempty default: yes
	// Accepts empty value: no
	// Unfortunate default: no
	StringNonemptyDefaultDoesntAcceptEmpty string `json:"string_nonempty_default_doesnt_accept_empty,omitempty"`

	// StringNonemptyDefaultEnumAcceptsEmpty:
	// Nonempty default: yes
	// Accepts empty value: yes (enum)
	// Unfortunate default: yes
	//
	// Possible values:
	//   ""
	//   "nonempty" (default)
	//   "aaa"
	StringNonemptyDefaultEnumAcceptsEmpty *string `json:"string_nonempty_default_enum_accepts_empty,omitempty"`

	// StringNonemptyDefaultEnumDoesntAcceptEmpty:
	// Nonempty default: yes
	// Accepts empty value: no (enum)
	// Unfortunate default: no
	//
	// Possible values:
	//   "nonempty" (default)
	//   "aaa"
	StringNonemptyDefaultEnumDoesntAcceptEmpty string `json:"string_nonempty_default_enum_doesnt_accept_empty,omitempty"`

	// StringNonemptyDefaultPatternAcceptsEmpty:
	// Nonempty default: yes
	// Accepts empty value: yes (pattern)
	// Unfortunate default: yes
	//
	// Default: nonempty
	StringNonemptyDefaultPatternAcceptsEmpty *string `json:"string_nonempty_default_pattern_accepts_empty,omitempty"`

	// StringNonemptyDefaultPatternDoesntAcceptEmpty:
	// Nonempty default: yes
	// Accepts empty value: no (pattern)
	// Unfortunate default: no
	StringNonemptyDefaultPatternDoesntAcceptEmpty string `json:"string_nonempty_default_pattern_doesnt_accept_empty,omitempty"`

	// ForceSendFields is a list of field names (e.g. "BoolEmptyDefaultA")
	// to unconditionally include in API requests. By default, fields with
	// empty values are omitted from API requests. However, any non-pointer,
	// non-interface field appearing in ForceSendFields will be sent to the
	// server regardless of whether the field is empty or not. This may be
	// used to include empty fields in Patch requests.
	ForceSendFields []string `json:"-"`

	// NullFields is a list of field names (e.g. "BoolEmptyDefaultA") to
	// include in API requests with the JSON null value. By default, fields
	// with empty values are omitted from API requests. However, any field
	// with an empty value appearing in NullFields will be sent to the
	// server as null. It is an error if a field in this list has a
	// non-empty value. This may be used to include null fields in Patch
	// requests.
	NullFields []string `json:"-"`
}

func (s *Thing) MarshalJSON() ([]byte, error) {
	type NoMethod Thing
	raw := NoMethod(*s)
	return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
}

func (s *Thing) UnmarshalJSON(data []byte) error {
	type NoMethod Thing
	var s1 struct {
		NumericEmptyDefaultD    gensupport.JSONFloat64  `json:"numeric_empty_default_d"`
		NumericEmptyDefaultE    gensupport.JSONFloat64  `json:"numeric_empty_default_e"`
		NumericNonemptyDefaultB *gensupport.JSONFloat64 `json:"numeric_nonempty_default_b"`
		*NoMethod
	}
	s1.NoMethod = (*NoMethod)(s)
	if err := json.Unmarshal(data, &s1); err != nil {
		return err
	}
	s.NumericEmptyDefaultD = float64(s1.NumericEmptyDefaultD)
	s.NumericEmptyDefaultE = float64(s1.NumericEmptyDefaultE)
	if s1.NumericNonemptyDefaultB != nil {
		s.NumericNonemptyDefaultB = (*float64)(s1.NumericNonemptyDefaultB)
	}
	return nil
}
