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

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

		timeout: cr.DefaultTimeout,
	}
}

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

		timeout: timeout,
	}
}

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

		Context: ctx,
	}
}

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

/*DcimRackReservationsDeleteParams contains all the parameters to send to the API endpoint
for the dcim rack reservations delete operation typically these are written to a http.Request
*/
type DcimRackReservationsDeleteParams struct {

	/*ID
	  A unique integer value identifying this rack reservation.

	*/
	ID int64

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

// WithTimeout adds the timeout to the dcim rack reservations delete params
func (o *DcimRackReservationsDeleteParams) WithTimeout(timeout time.Duration) *DcimRackReservationsDeleteParams {
	o.SetTimeout(timeout)
	return o
}

// SetTimeout adds the timeout to the dcim rack reservations delete params
func (o *DcimRackReservationsDeleteParams) SetTimeout(timeout time.Duration) {
	o.timeout = timeout
}

// WithContext adds the context to the dcim rack reservations delete params
func (o *DcimRackReservationsDeleteParams) WithContext(ctx context.Context) *DcimRackReservationsDeleteParams {
	o.SetContext(ctx)
	return o
}

// SetContext adds the context to the dcim rack reservations delete params
func (o *DcimRackReservationsDeleteParams) SetContext(ctx context.Context) {
	o.Context = ctx
}

// WithHTTPClient adds the HTTPClient to the dcim rack reservations delete params
func (o *DcimRackReservationsDeleteParams) WithHTTPClient(client *http.Client) *DcimRackReservationsDeleteParams {
	o.SetHTTPClient(client)
	return o
}

// SetHTTPClient adds the HTTPClient to the dcim rack reservations delete params
func (o *DcimRackReservationsDeleteParams) SetHTTPClient(client *http.Client) {
	o.HTTPClient = client
}

// WithID adds the id to the dcim rack reservations delete params
func (o *DcimRackReservationsDeleteParams) WithID(id int64) *DcimRackReservationsDeleteParams {
	o.SetID(id)
	return o
}

// SetID adds the id to the dcim rack reservations delete params
func (o *DcimRackReservationsDeleteParams) SetID(id int64) {
	o.ID = id
}

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

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

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