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

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

import (
	"encoding/json"

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

	"github.com/go-openapi/errors"
	"github.com/go-openapi/swag"
	"github.com/go-openapi/validate"
)

// WritableDeviceType writable device type
// swagger:model WritableDeviceType
type WritableDeviceType struct {

	// Comments
	Comments string `json:"comments,omitempty"`

	// Custom fields
	CustomFields interface{} `json:"custom_fields,omitempty"`

	// ID
	// Read Only: true
	ID int64 `json:"id,omitempty"`

	// Interface ordering
	InterfaceOrdering int64 `json:"interface_ordering,omitempty"`

	// Is a console server
	//
	// This type of device has console server ports
	IsConsoleServer bool `json:"is_console_server,omitempty"`

	// Is full depth
	//
	// Device consumes both front and rear rack faces
	IsFullDepth bool `json:"is_full_depth,omitempty"`

	// Is a network device
	//
	// This type of device has network interfaces
	IsNetworkDevice bool `json:"is_network_device,omitempty"`

	// Is a PDU
	//
	// This type of device has power outlets
	IsPdu bool `json:"is_pdu,omitempty"`

	// Manufacturer
	// Required: true
	Manufacturer *int64 `json:"manufacturer"`

	// Model
	// Required: true
	// Max Length: 50
	Model *string `json:"model"`

	// Part number
	//
	// Discrete part number (optional)
	// Max Length: 50
	PartNumber string `json:"part_number,omitempty"`

	// Slug
	// Required: true
	// Max Length: 50
	// Pattern: ^[-a-zA-Z0-9_]+$
	Slug *string `json:"slug"`

	// Parent/child status
	//
	// Parent devices house child devices in device bays. Select "None" if this device type is neither a parent nor a child.
	SubdeviceRole *bool `json:"subdevice_role,omitempty"`

	// Height (U)
	// Maximum: 32767
	// Minimum: 0
	UHeight *int64 `json:"u_height,omitempty"`
}

// Validate validates this writable device type
func (m *WritableDeviceType) Validate(formats strfmt.Registry) error {
	var res []error

	if err := m.validateInterfaceOrdering(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateManufacturer(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateModel(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validatePartNumber(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateSlug(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateSubdeviceRole(formats); err != nil {
		// prop
		res = append(res, err)
	}

	if err := m.validateUHeight(formats); err != nil {
		// prop
		res = append(res, err)
	}

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

var writableDeviceTypeTypeInterfaceOrderingPropEnum []interface{}

func init() {
	var res []int64
	if err := json.Unmarshal([]byte(`[1,2]`), &res); err != nil {
		panic(err)
	}
	for _, v := range res {
		writableDeviceTypeTypeInterfaceOrderingPropEnum = append(writableDeviceTypeTypeInterfaceOrderingPropEnum, v)
	}
}

// prop value enum
func (m *WritableDeviceType) validateInterfaceOrderingEnum(path, location string, value int64) error {
	if err := validate.Enum(path, location, value, writableDeviceTypeTypeInterfaceOrderingPropEnum); err != nil {
		return err
	}
	return nil
}

func (m *WritableDeviceType) validateInterfaceOrdering(formats strfmt.Registry) error {

	if swag.IsZero(m.InterfaceOrdering) { // not required
		return nil
	}

	// value enum
	if err := m.validateInterfaceOrderingEnum("interface_ordering", "body", m.InterfaceOrdering); err != nil {
		return err
	}

	return nil
}

func (m *WritableDeviceType) validateManufacturer(formats strfmt.Registry) error {

	if err := validate.Required("manufacturer", "body", m.Manufacturer); err != nil {
		return err
	}

	return nil
}

func (m *WritableDeviceType) validateModel(formats strfmt.Registry) error {

	if err := validate.Required("model", "body", m.Model); err != nil {
		return err
	}

	if err := validate.MaxLength("model", "body", string(*m.Model), 50); err != nil {
		return err
	}

	return nil
}

func (m *WritableDeviceType) validatePartNumber(formats strfmt.Registry) error {

	if swag.IsZero(m.PartNumber) { // not required
		return nil
	}

	if err := validate.MaxLength("part_number", "body", string(m.PartNumber), 50); err != nil {
		return err
	}

	return nil
}

func (m *WritableDeviceType) validateSlug(formats strfmt.Registry) error {

	if err := validate.Required("slug", "body", m.Slug); err != nil {
		return err
	}

	if err := validate.MaxLength("slug", "body", string(*m.Slug), 50); err != nil {
		return err
	}

	if err := validate.Pattern("slug", "body", string(*m.Slug), `^[-a-zA-Z0-9_]+$`); err != nil {
		return err
	}

	return nil
}

var writableDeviceTypeTypeSubdeviceRolePropEnum []interface{}

func init() {
	var res []bool
	if err := json.Unmarshal([]byte(`[null,true,false]`), &res); err != nil {
		panic(err)
	}
	for _, v := range res {
		writableDeviceTypeTypeSubdeviceRolePropEnum = append(writableDeviceTypeTypeSubdeviceRolePropEnum, v)
	}
}

// prop value enum
func (m *WritableDeviceType) validateSubdeviceRoleEnum(path, location string, value bool) error {
	if err := validate.Enum(path, location, value, writableDeviceTypeTypeSubdeviceRolePropEnum); err != nil {
		return err
	}
	return nil
}

func (m *WritableDeviceType) validateSubdeviceRole(formats strfmt.Registry) error {

	if swag.IsZero(m.SubdeviceRole) { // not required
		return nil
	}

	// value enum
	if err := m.validateSubdeviceRoleEnum("subdevice_role", "body", *m.SubdeviceRole); err != nil {
		return err
	}

	return nil
}

func (m *WritableDeviceType) validateUHeight(formats strfmt.Registry) error {

	if swag.IsZero(m.UHeight) { // not required
		return nil
	}

	if err := validate.MinimumInt("u_height", "body", int64(*m.UHeight), 0, false); err != nil {
		return err
	}

	if err := validate.MaximumInt("u_height", "body", int64(*m.UHeight), 32767, false); err != nil {
		return err
	}

	return nil
}

// MarshalBinary interface implementation
func (m *WritableDeviceType) MarshalBinary() ([]byte, error) {
	if m == nil {
		return nil, nil
	}
	return swag.WriteJSON(m)
}

// UnmarshalBinary interface implementation
func (m *WritableDeviceType) UnmarshalBinary(b []byte) error {
	var res WritableDeviceType
	if err := swag.ReadJSON(b, &res); err != nil {
		return err
	}
	*m = res
	return nil
}
