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

// WritableInterface writable interface
// swagger:model WritableInterface
type WritableInterface struct {

	// Description
	// Max Length: 100
	Description string `json:"description,omitempty"`

	// Device
	// Required: true
	Device *int64 `json:"device"`

	// Enabled
	Enabled bool `json:"enabled,omitempty"`

	// Form factor
	FormFactor int64 `json:"form_factor,omitempty"`

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

	// Parent LAG
	Lag int64 `json:"lag,omitempty"`

	// MAC Address
	MacAddress string `json:"mac_address,omitempty"`

	// OOB Management
	//
	// This interface is used only for out-of-band management
	MgmtOnly bool `json:"mgmt_only,omitempty"`

	// Mode
	Mode int64 `json:"mode,omitempty"`

	// MTU
	// Maximum: 32767
	// Minimum: 0
	Mtu *int64 `json:"mtu,omitempty"`

	// Name
	// Required: true
	// Max Length: 64
	Name *string `json:"name"`

	// tagged vlans
	// Unique: true
	TaggedVlans []int64 `json:"tagged_vlans"`

	// Untagged VLAN
	UntaggedVlan int64 `json:"untagged_vlan,omitempty"`
}

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

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

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

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

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

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

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

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

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

func (m *WritableInterface) validateDescription(formats strfmt.Registry) error {

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

	if err := validate.MaxLength("description", "body", string(m.Description), 100); err != nil {
		return err
	}

	return nil
}

func (m *WritableInterface) validateDevice(formats strfmt.Registry) error {

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

	return nil
}

var writableInterfaceTypeFormFactorPropEnum []interface{}

func init() {
	var res []int64
	if err := json.Unmarshal([]byte(`[0,200,800,1000,1150,1170,1050,1100,1200,1300,1310,1320,1350,1400,1500,1510,1520,1550,1600,2600,2610,2620,2630,2640,3010,3020,3040,3080,3160,4000,4010,4040,4050,5000,5050,5100,5150,5200,32767]`), &res); err != nil {
		panic(err)
	}
	for _, v := range res {
		writableInterfaceTypeFormFactorPropEnum = append(writableInterfaceTypeFormFactorPropEnum, v)
	}
}

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

func (m *WritableInterface) validateFormFactor(formats strfmt.Registry) error {

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

	// value enum
	if err := m.validateFormFactorEnum("form_factor", "body", m.FormFactor); err != nil {
		return err
	}

	return nil
}

var writableInterfaceTypeModePropEnum []interface{}

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

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

func (m *WritableInterface) validateMode(formats strfmt.Registry) error {

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

	// value enum
	if err := m.validateModeEnum("mode", "body", m.Mode); err != nil {
		return err
	}

	return nil
}

func (m *WritableInterface) validateMtu(formats strfmt.Registry) error {

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

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

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

	return nil
}

func (m *WritableInterface) validateName(formats strfmt.Registry) error {

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

	if err := validate.MaxLength("name", "body", string(*m.Name), 64); err != nil {
		return err
	}

	return nil
}

func (m *WritableInterface) validateTaggedVlans(formats strfmt.Registry) error {

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

	if err := validate.UniqueItems("tagged_vlans", "body", m.TaggedVlans); err != nil {
		return err
	}

	return nil
}

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

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