//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 model

import (
	"github.com/apache/plc4x/plc4go/internal/plc4go/spi/utils"
	"github.com/pkg/errors"
)

// Code generated by build-utils. DO NOT EDIT.

// The data-structure of this message
type COTPParameterCallingTsap struct {
	TsapId uint16
	Parent *COTPParameter
}

// The corresponding interface
type ICOTPParameterCallingTsap interface {
	LengthInBytes() uint16
	LengthInBits() uint16
	Serialize(writeBuffer utils.WriteBuffer) error
}

///////////////////////////////////////////////////////////
// Accessors for discriminator values.
///////////////////////////////////////////////////////////
func (m *COTPParameterCallingTsap) ParameterType() uint8 {
	return 0xC1
}

func (m *COTPParameterCallingTsap) InitializeParent(parent *COTPParameter) {
}

func NewCOTPParameterCallingTsap(tsapId uint16) *COTPParameter {
	child := &COTPParameterCallingTsap{
		TsapId: tsapId,
		Parent: NewCOTPParameter(),
	}
	child.Parent.Child = child
	return child.Parent
}

func CastCOTPParameterCallingTsap(structType interface{}) *COTPParameterCallingTsap {
	castFunc := func(typ interface{}) *COTPParameterCallingTsap {
		if casted, ok := typ.(COTPParameterCallingTsap); ok {
			return &casted
		}
		if casted, ok := typ.(*COTPParameterCallingTsap); ok {
			return casted
		}
		if casted, ok := typ.(COTPParameter); ok {
			return CastCOTPParameterCallingTsap(casted.Child)
		}
		if casted, ok := typ.(*COTPParameter); ok {
			return CastCOTPParameterCallingTsap(casted.Child)
		}
		return nil
	}
	return castFunc(structType)
}

func (m *COTPParameterCallingTsap) GetTypeName() string {
	return "COTPParameterCallingTsap"
}

func (m *COTPParameterCallingTsap) LengthInBits() uint16 {
	return m.LengthInBitsConditional(false)
}

func (m *COTPParameterCallingTsap) LengthInBitsConditional(lastItem bool) uint16 {
	lengthInBits := uint16(m.Parent.ParentLengthInBits())

	// Simple field (tsapId)
	lengthInBits += 16

	return lengthInBits
}

func (m *COTPParameterCallingTsap) LengthInBytes() uint16 {
	return m.LengthInBits() / 8
}

func COTPParameterCallingTsapParse(readBuffer utils.ReadBuffer) (*COTPParameter, error) {
	if pullErr := readBuffer.PullContext("COTPParameterCallingTsap"); pullErr != nil {
		return nil, pullErr
	}

	// Simple Field (tsapId)
	tsapId, _tsapIdErr := readBuffer.ReadUint16("tsapId", 16)
	if _tsapIdErr != nil {
		return nil, errors.Wrap(_tsapIdErr, "Error parsing 'tsapId' field")
	}

	if closeErr := readBuffer.CloseContext("COTPParameterCallingTsap"); closeErr != nil {
		return nil, closeErr
	}

	// Create a partially initialized instance
	_child := &COTPParameterCallingTsap{
		TsapId: tsapId,
		Parent: &COTPParameter{},
	}
	_child.Parent.Child = _child
	return _child.Parent, nil
}

func (m *COTPParameterCallingTsap) Serialize(writeBuffer utils.WriteBuffer) error {
	ser := func() error {
		if pushErr := writeBuffer.PushContext("COTPParameterCallingTsap"); pushErr != nil {
			return pushErr
		}

		// Simple Field (tsapId)
		tsapId := uint16(m.TsapId)
		_tsapIdErr := writeBuffer.WriteUint16("tsapId", 16, (tsapId))
		if _tsapIdErr != nil {
			return errors.Wrap(_tsapIdErr, "Error serializing 'tsapId' field")
		}

		if popErr := writeBuffer.PopContext("COTPParameterCallingTsap"); popErr != nil {
			return popErr
		}
		return nil
	}
	return m.Parent.SerializeParent(writeBuffer, m, ser)
}

func (m *COTPParameterCallingTsap) String() string {
	if m == nil {
		return "<nil>"
	}
	buffer := utils.NewBoxedWriteBufferWithOptions(true, true)
	m.Serialize(buffer)
	return buffer.GetBox().String()
}
