// Code generated by go-swagger; DO NOT EDIT.

// Copyright 2018 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tenancy

// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command

import (
	"net/http"
	"time"

	"golang.org/x/net/context"

	"github.com/go-openapi/errors"
	"github.com/go-openapi/runtime"
	cr "github.com/go-openapi/runtime/client"
	"github.com/go-openapi/swag"

	strfmt "github.com/go-openapi/strfmt"

	"github.com/digitalocean/go-netbox/netbox/models"
)

// NewTenancyTenantsUpdateParams creates a new TenancyTenantsUpdateParams object
// with the default values initialized.
func NewTenancyTenantsUpdateParams() *TenancyTenantsUpdateParams {
	var ()
	return &TenancyTenantsUpdateParams{

		timeout: cr.DefaultTimeout,
	}
}

// NewTenancyTenantsUpdateParamsWithTimeout creates a new TenancyTenantsUpdateParams object
// with the default values initialized, and the ability to set a timeout on a request
func NewTenancyTenantsUpdateParamsWithTimeout(timeout time.Duration) *TenancyTenantsUpdateParams {
	var ()
	return &TenancyTenantsUpdateParams{

		timeout: timeout,
	}
}

// NewTenancyTenantsUpdateParamsWithContext creates a new TenancyTenantsUpdateParams object
// with the default values initialized, and the ability to set a context for a request
func NewTenancyTenantsUpdateParamsWithContext(ctx context.Context) *TenancyTenantsUpdateParams {
	var ()
	return &TenancyTenantsUpdateParams{

		Context: ctx,
	}
}

// NewTenancyTenantsUpdateParamsWithHTTPClient creates a new TenancyTenantsUpdateParams object
// with the default values initialized, and the ability to set a custom HTTPClient for a request
func NewTenancyTenantsUpdateParamsWithHTTPClient(client *http.Client) *TenancyTenantsUpdateParams {
	var ()
	return &TenancyTenantsUpdateParams{
		HTTPClient: client,
	}
}

/*TenancyTenantsUpdateParams contains all the parameters to send to the API endpoint
for the tenancy tenants update operation typically these are written to a http.Request
*/
type TenancyTenantsUpdateParams struct {

	/*Data*/
	Data *models.WritableTenant
	/*ID
	  A unique integer value identifying this tenant.

	*/
	ID int64

	timeout    time.Duration
	Context    context.Context
	HTTPClient *http.Client
}

// WithTimeout adds the timeout to the tenancy tenants update params
func (o *TenancyTenantsUpdateParams) WithTimeout(timeout time.Duration) *TenancyTenantsUpdateParams {
	o.SetTimeout(timeout)
	return o
}

// SetTimeout adds the timeout to the tenancy tenants update params
func (o *TenancyTenantsUpdateParams) SetTimeout(timeout time.Duration) {
	o.timeout = timeout
}

// WithContext adds the context to the tenancy tenants update params
func (o *TenancyTenantsUpdateParams) WithContext(ctx context.Context) *TenancyTenantsUpdateParams {
	o.SetContext(ctx)
	return o
}

// SetContext adds the context to the tenancy tenants update params
func (o *TenancyTenantsUpdateParams) SetContext(ctx context.Context) {
	o.Context = ctx
}

// WithHTTPClient adds the HTTPClient to the tenancy tenants update params
func (o *TenancyTenantsUpdateParams) WithHTTPClient(client *http.Client) *TenancyTenantsUpdateParams {
	o.SetHTTPClient(client)
	return o
}

// SetHTTPClient adds the HTTPClient to the tenancy tenants update params
func (o *TenancyTenantsUpdateParams) SetHTTPClient(client *http.Client) {
	o.HTTPClient = client
}

// WithData adds the data to the tenancy tenants update params
func (o *TenancyTenantsUpdateParams) WithData(data *models.WritableTenant) *TenancyTenantsUpdateParams {
	o.SetData(data)
	return o
}

// SetData adds the data to the tenancy tenants update params
func (o *TenancyTenantsUpdateParams) SetData(data *models.WritableTenant) {
	o.Data = data
}

// WithID adds the id to the tenancy tenants update params
func (o *TenancyTenantsUpdateParams) WithID(id int64) *TenancyTenantsUpdateParams {
	o.SetID(id)
	return o
}

// SetID adds the id to the tenancy tenants update params
func (o *TenancyTenantsUpdateParams) SetID(id int64) {
	o.ID = id
}

// WriteToRequest writes these params to a swagger request
func (o *TenancyTenantsUpdateParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {

	if err := r.SetTimeout(o.timeout); err != nil {
		return err
	}
	var res []error

	if o.Data != nil {
		if err := r.SetBodyParam(o.Data); err != nil {
			return err
		}
	}

	// path param id
	if err := r.SetPathParam("id", swag.FormatInt64(o.ID)); err != nil {
		return err
	}

	if len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}
