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

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

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

		timeout: cr.DefaultTimeout,
	}
}

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

		timeout: timeout,
	}
}

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

		Context: ctx,
	}
}

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

/*DcimManufacturersListParams contains all the parameters to send to the API endpoint
for the dcim manufacturers list operation typically these are written to a http.Request
*/
type DcimManufacturersListParams struct {

	/*Limit
	  Number of results to return per page.

	*/
	Limit *int64
	/*Name*/
	Name *string
	/*Offset
	  The initial index from which to return the results.

	*/
	Offset *int64
	/*Slug*/
	Slug *string

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

// WithTimeout adds the timeout to the dcim manufacturers list params
func (o *DcimManufacturersListParams) WithTimeout(timeout time.Duration) *DcimManufacturersListParams {
	o.SetTimeout(timeout)
	return o
}

// SetTimeout adds the timeout to the dcim manufacturers list params
func (o *DcimManufacturersListParams) SetTimeout(timeout time.Duration) {
	o.timeout = timeout
}

// WithContext adds the context to the dcim manufacturers list params
func (o *DcimManufacturersListParams) WithContext(ctx context.Context) *DcimManufacturersListParams {
	o.SetContext(ctx)
	return o
}

// SetContext adds the context to the dcim manufacturers list params
func (o *DcimManufacturersListParams) SetContext(ctx context.Context) {
	o.Context = ctx
}

// WithHTTPClient adds the HTTPClient to the dcim manufacturers list params
func (o *DcimManufacturersListParams) WithHTTPClient(client *http.Client) *DcimManufacturersListParams {
	o.SetHTTPClient(client)
	return o
}

// SetHTTPClient adds the HTTPClient to the dcim manufacturers list params
func (o *DcimManufacturersListParams) SetHTTPClient(client *http.Client) {
	o.HTTPClient = client
}

// WithLimit adds the limit to the dcim manufacturers list params
func (o *DcimManufacturersListParams) WithLimit(limit *int64) *DcimManufacturersListParams {
	o.SetLimit(limit)
	return o
}

// SetLimit adds the limit to the dcim manufacturers list params
func (o *DcimManufacturersListParams) SetLimit(limit *int64) {
	o.Limit = limit
}

// WithName adds the name to the dcim manufacturers list params
func (o *DcimManufacturersListParams) WithName(name *string) *DcimManufacturersListParams {
	o.SetName(name)
	return o
}

// SetName adds the name to the dcim manufacturers list params
func (o *DcimManufacturersListParams) SetName(name *string) {
	o.Name = name
}

// WithOffset adds the offset to the dcim manufacturers list params
func (o *DcimManufacturersListParams) WithOffset(offset *int64) *DcimManufacturersListParams {
	o.SetOffset(offset)
	return o
}

// SetOffset adds the offset to the dcim manufacturers list params
func (o *DcimManufacturersListParams) SetOffset(offset *int64) {
	o.Offset = offset
}

// WithSlug adds the slug to the dcim manufacturers list params
func (o *DcimManufacturersListParams) WithSlug(slug *string) *DcimManufacturersListParams {
	o.SetSlug(slug)
	return o
}

// SetSlug adds the slug to the dcim manufacturers list params
func (o *DcimManufacturersListParams) SetSlug(slug *string) {
	o.Slug = slug
}

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

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

	if o.Limit != nil {

		// query param limit
		var qrLimit int64
		if o.Limit != nil {
			qrLimit = *o.Limit
		}
		qLimit := swag.FormatInt64(qrLimit)
		if qLimit != "" {
			if err := r.SetQueryParam("limit", qLimit); err != nil {
				return err
			}
		}

	}

	if o.Name != nil {

		// query param name
		var qrName string
		if o.Name != nil {
			qrName = *o.Name
		}
		qName := qrName
		if qName != "" {
			if err := r.SetQueryParam("name", qName); err != nil {
				return err
			}
		}

	}

	if o.Offset != nil {

		// query param offset
		var qrOffset int64
		if o.Offset != nil {
			qrOffset = *o.Offset
		}
		qOffset := swag.FormatInt64(qrOffset)
		if qOffset != "" {
			if err := r.SetQueryParam("offset", qOffset); err != nil {
				return err
			}
		}

	}

	if o.Slug != nil {

		// query param slug
		var qrSlug string
		if o.Slug != nil {
			qrSlug = *o.Slug
		}
		qSlug := qrSlug
		if qSlug != "" {
			if err := r.SetQueryParam("slug", qSlug); err != nil {
				return err
			}
		}

	}

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