// 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 virtualization

// 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"
)

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

		timeout: cr.DefaultTimeout,
	}
}

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

		timeout: timeout,
	}
}

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

		Context: ctx,
	}
}

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

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

	/*Data*/
	Data *models.WritableCluster
	/*ID
	  A unique integer value identifying this cluster.

	*/
	ID int64

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

// WithTimeout adds the timeout to the virtualization clusters update params
func (o *VirtualizationClustersUpdateParams) WithTimeout(timeout time.Duration) *VirtualizationClustersUpdateParams {
	o.SetTimeout(timeout)
	return o
}

// SetTimeout adds the timeout to the virtualization clusters update params
func (o *VirtualizationClustersUpdateParams) SetTimeout(timeout time.Duration) {
	o.timeout = timeout
}

// WithContext adds the context to the virtualization clusters update params
func (o *VirtualizationClustersUpdateParams) WithContext(ctx context.Context) *VirtualizationClustersUpdateParams {
	o.SetContext(ctx)
	return o
}

// SetContext adds the context to the virtualization clusters update params
func (o *VirtualizationClustersUpdateParams) SetContext(ctx context.Context) {
	o.Context = ctx
}

// WithHTTPClient adds the HTTPClient to the virtualization clusters update params
func (o *VirtualizationClustersUpdateParams) WithHTTPClient(client *http.Client) *VirtualizationClustersUpdateParams {
	o.SetHTTPClient(client)
	return o
}

// SetHTTPClient adds the HTTPClient to the virtualization clusters update params
func (o *VirtualizationClustersUpdateParams) SetHTTPClient(client *http.Client) {
	o.HTTPClient = client
}

// WithData adds the data to the virtualization clusters update params
func (o *VirtualizationClustersUpdateParams) WithData(data *models.WritableCluster) *VirtualizationClustersUpdateParams {
	o.SetData(data)
	return o
}

// SetData adds the data to the virtualization clusters update params
func (o *VirtualizationClustersUpdateParams) SetData(data *models.WritableCluster) {
	o.Data = data
}

// WithID adds the id to the virtualization clusters update params
func (o *VirtualizationClustersUpdateParams) WithID(id int64) *VirtualizationClustersUpdateParams {
	o.SetID(id)
	return o
}

// SetID adds the id to the virtualization clusters update params
func (o *VirtualizationClustersUpdateParams) SetID(id int64) {
	o.ID = id
}

// WriteToRequest writes these params to a swagger request
func (o *VirtualizationClustersUpdateParams) 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
}
