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

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

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

		timeout: cr.DefaultTimeout,
	}
}

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

		timeout: timeout,
	}
}

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

		Context: ctx,
	}
}

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

/*ExtrasImageAttachmentsListParams contains all the parameters to send to the API endpoint
for the extras image attachments list operation typically these are written to a http.Request
*/
type ExtrasImageAttachmentsListParams struct {

	/*Limit
	  Number of results to return per page.

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

	*/
	Offset *int64

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

// WithTimeout adds the timeout to the extras image attachments list params
func (o *ExtrasImageAttachmentsListParams) WithTimeout(timeout time.Duration) *ExtrasImageAttachmentsListParams {
	o.SetTimeout(timeout)
	return o
}

// SetTimeout adds the timeout to the extras image attachments list params
func (o *ExtrasImageAttachmentsListParams) SetTimeout(timeout time.Duration) {
	o.timeout = timeout
}

// WithContext adds the context to the extras image attachments list params
func (o *ExtrasImageAttachmentsListParams) WithContext(ctx context.Context) *ExtrasImageAttachmentsListParams {
	o.SetContext(ctx)
	return o
}

// SetContext adds the context to the extras image attachments list params
func (o *ExtrasImageAttachmentsListParams) SetContext(ctx context.Context) {
	o.Context = ctx
}

// WithHTTPClient adds the HTTPClient to the extras image attachments list params
func (o *ExtrasImageAttachmentsListParams) WithHTTPClient(client *http.Client) *ExtrasImageAttachmentsListParams {
	o.SetHTTPClient(client)
	return o
}

// SetHTTPClient adds the HTTPClient to the extras image attachments list params
func (o *ExtrasImageAttachmentsListParams) SetHTTPClient(client *http.Client) {
	o.HTTPClient = client
}

// WithLimit adds the limit to the extras image attachments list params
func (o *ExtrasImageAttachmentsListParams) WithLimit(limit *int64) *ExtrasImageAttachmentsListParams {
	o.SetLimit(limit)
	return o
}

// SetLimit adds the limit to the extras image attachments list params
func (o *ExtrasImageAttachmentsListParams) SetLimit(limit *int64) {
	o.Limit = limit
}

// WithOffset adds the offset to the extras image attachments list params
func (o *ExtrasImageAttachmentsListParams) WithOffset(offset *int64) *ExtrasImageAttachmentsListParams {
	o.SetOffset(offset)
	return o
}

// SetOffset adds the offset to the extras image attachments list params
func (o *ExtrasImageAttachmentsListParams) SetOffset(offset *int64) {
	o.Offset = offset
}

// WriteToRequest writes these params to a swagger request
func (o *ExtrasImageAttachmentsListParams) 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.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 len(res) > 0 {
		return errors.CompositeValidationError(res...)
	}
	return nil
}
