/*
 * 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
 *
 *   https://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 (
	"context"
	"fmt"

	"github.com/pkg/errors"
	"github.com/rs/zerolog"

	. "github.com/apache/plc4x/plc4go/spi/codegen/fields"
	. "github.com/apache/plc4x/plc4go/spi/codegen/io"
	"github.com/apache/plc4x/plc4go/spi/utils"
)

// Code generated by code-generation. DO NOT EDIT.

// MediaTransportControlDataTotalTracks is the corresponding interface of MediaTransportControlDataTotalTracks
type MediaTransportControlDataTotalTracks interface {
	fmt.Stringer
	utils.LengthAware
	utils.Serializable
	utils.Copyable
	MediaTransportControlData
	// GetTotalTracksMSB returns TotalTracksMSB (property field)
	GetTotalTracksMSB() byte
	// GetTotalTracksMMSB returns TotalTracksMMSB (property field)
	GetTotalTracksMMSB() byte
	// GetTotalTracksMLSB returns TotalTracksMLSB (property field)
	GetTotalTracksMLSB() byte
	// GetTotalTracksLSB returns TotalTracksLSB (property field)
	GetTotalTracksLSB() byte
	// IsMediaTransportControlDataTotalTracks is a marker method to prevent unintentional type checks (interfaces of same signature)
	IsMediaTransportControlDataTotalTracks()
	// CreateBuilder creates a MediaTransportControlDataTotalTracksBuilder
	CreateMediaTransportControlDataTotalTracksBuilder() MediaTransportControlDataTotalTracksBuilder
}

// _MediaTransportControlDataTotalTracks is the data-structure of this message
type _MediaTransportControlDataTotalTracks struct {
	MediaTransportControlDataContract
	TotalTracksMSB  byte
	TotalTracksMMSB byte
	TotalTracksMLSB byte
	TotalTracksLSB  byte
}

var _ MediaTransportControlDataTotalTracks = (*_MediaTransportControlDataTotalTracks)(nil)
var _ MediaTransportControlDataRequirements = (*_MediaTransportControlDataTotalTracks)(nil)

// NewMediaTransportControlDataTotalTracks factory function for _MediaTransportControlDataTotalTracks
func NewMediaTransportControlDataTotalTracks(commandTypeContainer MediaTransportControlCommandTypeContainer, mediaLinkGroup byte, totalTracksMSB byte, totalTracksMMSB byte, totalTracksMLSB byte, totalTracksLSB byte) *_MediaTransportControlDataTotalTracks {
	_result := &_MediaTransportControlDataTotalTracks{
		MediaTransportControlDataContract: NewMediaTransportControlData(commandTypeContainer, mediaLinkGroup),
		TotalTracksMSB:                    totalTracksMSB,
		TotalTracksMMSB:                   totalTracksMMSB,
		TotalTracksMLSB:                   totalTracksMLSB,
		TotalTracksLSB:                    totalTracksLSB,
	}
	_result.MediaTransportControlDataContract.(*_MediaTransportControlData)._SubType = _result
	return _result
}

///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
/////////////////////// Builder
///////////////////////

// MediaTransportControlDataTotalTracksBuilder is a builder for MediaTransportControlDataTotalTracks
type MediaTransportControlDataTotalTracksBuilder interface {
	utils.Copyable
	// WithMandatoryFields adds all mandatory fields (convenience for using multiple builder calls)
	WithMandatoryFields(totalTracksMSB byte, totalTracksMMSB byte, totalTracksMLSB byte, totalTracksLSB byte) MediaTransportControlDataTotalTracksBuilder
	// WithTotalTracksMSB adds TotalTracksMSB (property field)
	WithTotalTracksMSB(byte) MediaTransportControlDataTotalTracksBuilder
	// WithTotalTracksMMSB adds TotalTracksMMSB (property field)
	WithTotalTracksMMSB(byte) MediaTransportControlDataTotalTracksBuilder
	// WithTotalTracksMLSB adds TotalTracksMLSB (property field)
	WithTotalTracksMLSB(byte) MediaTransportControlDataTotalTracksBuilder
	// WithTotalTracksLSB adds TotalTracksLSB (property field)
	WithTotalTracksLSB(byte) MediaTransportControlDataTotalTracksBuilder
	// Done is used to finish work on this child and return (or create one if none) to the parent builder
	Done() MediaTransportControlDataBuilder
	// Build builds the MediaTransportControlDataTotalTracks or returns an error if something is wrong
	Build() (MediaTransportControlDataTotalTracks, error)
	// MustBuild does the same as Build but panics on error
	MustBuild() MediaTransportControlDataTotalTracks
}

// NewMediaTransportControlDataTotalTracksBuilder() creates a MediaTransportControlDataTotalTracksBuilder
func NewMediaTransportControlDataTotalTracksBuilder() MediaTransportControlDataTotalTracksBuilder {
	return &_MediaTransportControlDataTotalTracksBuilder{_MediaTransportControlDataTotalTracks: new(_MediaTransportControlDataTotalTracks)}
}

type _MediaTransportControlDataTotalTracksBuilder struct {
	*_MediaTransportControlDataTotalTracks

	parentBuilder *_MediaTransportControlDataBuilder

	err *utils.MultiError
}

var _ (MediaTransportControlDataTotalTracksBuilder) = (*_MediaTransportControlDataTotalTracksBuilder)(nil)

func (b *_MediaTransportControlDataTotalTracksBuilder) setParent(contract MediaTransportControlDataContract) {
	b.MediaTransportControlDataContract = contract
	contract.(*_MediaTransportControlData)._SubType = b._MediaTransportControlDataTotalTracks
}

func (b *_MediaTransportControlDataTotalTracksBuilder) WithMandatoryFields(totalTracksMSB byte, totalTracksMMSB byte, totalTracksMLSB byte, totalTracksLSB byte) MediaTransportControlDataTotalTracksBuilder {
	return b.WithTotalTracksMSB(totalTracksMSB).WithTotalTracksMMSB(totalTracksMMSB).WithTotalTracksMLSB(totalTracksMLSB).WithTotalTracksLSB(totalTracksLSB)
}

func (b *_MediaTransportControlDataTotalTracksBuilder) WithTotalTracksMSB(totalTracksMSB byte) MediaTransportControlDataTotalTracksBuilder {
	b.TotalTracksMSB = totalTracksMSB
	return b
}

func (b *_MediaTransportControlDataTotalTracksBuilder) WithTotalTracksMMSB(totalTracksMMSB byte) MediaTransportControlDataTotalTracksBuilder {
	b.TotalTracksMMSB = totalTracksMMSB
	return b
}

func (b *_MediaTransportControlDataTotalTracksBuilder) WithTotalTracksMLSB(totalTracksMLSB byte) MediaTransportControlDataTotalTracksBuilder {
	b.TotalTracksMLSB = totalTracksMLSB
	return b
}

func (b *_MediaTransportControlDataTotalTracksBuilder) WithTotalTracksLSB(totalTracksLSB byte) MediaTransportControlDataTotalTracksBuilder {
	b.TotalTracksLSB = totalTracksLSB
	return b
}

func (b *_MediaTransportControlDataTotalTracksBuilder) Build() (MediaTransportControlDataTotalTracks, error) {
	if b.err != nil {
		return nil, errors.Wrap(b.err, "error occurred during build")
	}
	return b._MediaTransportControlDataTotalTracks.deepCopy(), nil
}

func (b *_MediaTransportControlDataTotalTracksBuilder) MustBuild() MediaTransportControlDataTotalTracks {
	build, err := b.Build()
	if err != nil {
		panic(err)
	}
	return build
}

func (b *_MediaTransportControlDataTotalTracksBuilder) Done() MediaTransportControlDataBuilder {
	if b.parentBuilder == nil {
		b.parentBuilder = NewMediaTransportControlDataBuilder().(*_MediaTransportControlDataBuilder)
	}
	return b.parentBuilder
}

func (b *_MediaTransportControlDataTotalTracksBuilder) buildForMediaTransportControlData() (MediaTransportControlData, error) {
	return b.Build()
}

func (b *_MediaTransportControlDataTotalTracksBuilder) DeepCopy() any {
	_copy := b.CreateMediaTransportControlDataTotalTracksBuilder().(*_MediaTransportControlDataTotalTracksBuilder)
	if b.err != nil {
		_copy.err = b.err.DeepCopy().(*utils.MultiError)
	}
	return _copy
}

// CreateMediaTransportControlDataTotalTracksBuilder creates a MediaTransportControlDataTotalTracksBuilder
func (b *_MediaTransportControlDataTotalTracks) CreateMediaTransportControlDataTotalTracksBuilder() MediaTransportControlDataTotalTracksBuilder {
	if b == nil {
		return NewMediaTransportControlDataTotalTracksBuilder()
	}
	return &_MediaTransportControlDataTotalTracksBuilder{_MediaTransportControlDataTotalTracks: b.deepCopy()}
}

///////////////////////
///////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
/////////////////////// Accessors for discriminator values.
///////////////////////

///////////////////////
///////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////

func (m *_MediaTransportControlDataTotalTracks) GetParent() MediaTransportControlDataContract {
	return m.MediaTransportControlDataContract
}

///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
/////////////////////// Accessors for property fields.
///////////////////////

func (m *_MediaTransportControlDataTotalTracks) GetTotalTracksMSB() byte {
	return m.TotalTracksMSB
}

func (m *_MediaTransportControlDataTotalTracks) GetTotalTracksMMSB() byte {
	return m.TotalTracksMMSB
}

func (m *_MediaTransportControlDataTotalTracks) GetTotalTracksMLSB() byte {
	return m.TotalTracksMLSB
}

func (m *_MediaTransportControlDataTotalTracks) GetTotalTracksLSB() byte {
	return m.TotalTracksLSB
}

///////////////////////
///////////////////////
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////

// Deprecated: use the interface for direct cast
func CastMediaTransportControlDataTotalTracks(structType any) MediaTransportControlDataTotalTracks {
	if casted, ok := structType.(MediaTransportControlDataTotalTracks); ok {
		return casted
	}
	if casted, ok := structType.(*MediaTransportControlDataTotalTracks); ok {
		return *casted
	}
	return nil
}

func (m *_MediaTransportControlDataTotalTracks) GetTypeName() string {
	return "MediaTransportControlDataTotalTracks"
}

func (m *_MediaTransportControlDataTotalTracks) GetLengthInBits(ctx context.Context) uint16 {
	lengthInBits := uint16(m.MediaTransportControlDataContract.(*_MediaTransportControlData).getLengthInBits(ctx))

	// Simple field (totalTracksMSB)
	lengthInBits += 8

	// Simple field (totalTracksMMSB)
	lengthInBits += 8

	// Simple field (totalTracksMLSB)
	lengthInBits += 8

	// Simple field (totalTracksLSB)
	lengthInBits += 8

	return lengthInBits
}

func (m *_MediaTransportControlDataTotalTracks) GetLengthInBytes(ctx context.Context) uint16 {
	return m.GetLengthInBits(ctx) / 8
}

func (m *_MediaTransportControlDataTotalTracks) parse(ctx context.Context, readBuffer utils.ReadBuffer, parent *_MediaTransportControlData) (__mediaTransportControlDataTotalTracks MediaTransportControlDataTotalTracks, err error) {
	m.MediaTransportControlDataContract = parent
	parent._SubType = m
	positionAware := readBuffer
	_ = positionAware
	if pullErr := readBuffer.PullContext("MediaTransportControlDataTotalTracks"); pullErr != nil {
		return nil, errors.Wrap(pullErr, "Error pulling for MediaTransportControlDataTotalTracks")
	}
	currentPos := positionAware.GetPos()
	_ = currentPos

	totalTracksMSB, err := ReadSimpleField(ctx, "totalTracksMSB", ReadByte(readBuffer, 8))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'totalTracksMSB' field"))
	}
	m.TotalTracksMSB = totalTracksMSB

	totalTracksMMSB, err := ReadSimpleField(ctx, "totalTracksMMSB", ReadByte(readBuffer, 8))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'totalTracksMMSB' field"))
	}
	m.TotalTracksMMSB = totalTracksMMSB

	totalTracksMLSB, err := ReadSimpleField(ctx, "totalTracksMLSB", ReadByte(readBuffer, 8))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'totalTracksMLSB' field"))
	}
	m.TotalTracksMLSB = totalTracksMLSB

	totalTracksLSB, err := ReadSimpleField(ctx, "totalTracksLSB", ReadByte(readBuffer, 8))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'totalTracksLSB' field"))
	}
	m.TotalTracksLSB = totalTracksLSB

	if closeErr := readBuffer.CloseContext("MediaTransportControlDataTotalTracks"); closeErr != nil {
		return nil, errors.Wrap(closeErr, "Error closing for MediaTransportControlDataTotalTracks")
	}

	return m, nil
}

func (m *_MediaTransportControlDataTotalTracks) Serialize() ([]byte, error) {
	wb := utils.NewWriteBufferByteBased(utils.WithInitialSizeForByteBasedBuffer(int(m.GetLengthInBytes(context.Background()))))
	if err := m.SerializeWithWriteBuffer(context.Background(), wb); err != nil {
		return nil, err
	}
	return wb.GetBytes(), nil
}

func (m *_MediaTransportControlDataTotalTracks) SerializeWithWriteBuffer(ctx context.Context, writeBuffer utils.WriteBuffer) error {
	positionAware := writeBuffer
	_ = positionAware
	log := zerolog.Ctx(ctx)
	_ = log
	ser := func() error {
		if pushErr := writeBuffer.PushContext("MediaTransportControlDataTotalTracks"); pushErr != nil {
			return errors.Wrap(pushErr, "Error pushing for MediaTransportControlDataTotalTracks")
		}

		if err := WriteSimpleField[byte](ctx, "totalTracksMSB", m.GetTotalTracksMSB(), WriteByte(writeBuffer, 8)); err != nil {
			return errors.Wrap(err, "Error serializing 'totalTracksMSB' field")
		}

		if err := WriteSimpleField[byte](ctx, "totalTracksMMSB", m.GetTotalTracksMMSB(), WriteByte(writeBuffer, 8)); err != nil {
			return errors.Wrap(err, "Error serializing 'totalTracksMMSB' field")
		}

		if err := WriteSimpleField[byte](ctx, "totalTracksMLSB", m.GetTotalTracksMLSB(), WriteByte(writeBuffer, 8)); err != nil {
			return errors.Wrap(err, "Error serializing 'totalTracksMLSB' field")
		}

		if err := WriteSimpleField[byte](ctx, "totalTracksLSB", m.GetTotalTracksLSB(), WriteByte(writeBuffer, 8)); err != nil {
			return errors.Wrap(err, "Error serializing 'totalTracksLSB' field")
		}

		if popErr := writeBuffer.PopContext("MediaTransportControlDataTotalTracks"); popErr != nil {
			return errors.Wrap(popErr, "Error popping for MediaTransportControlDataTotalTracks")
		}
		return nil
	}
	return m.MediaTransportControlDataContract.(*_MediaTransportControlData).serializeParent(ctx, writeBuffer, m, ser)
}

func (m *_MediaTransportControlDataTotalTracks) IsMediaTransportControlDataTotalTracks() {}

func (m *_MediaTransportControlDataTotalTracks) DeepCopy() any {
	return m.deepCopy()
}

func (m *_MediaTransportControlDataTotalTracks) deepCopy() *_MediaTransportControlDataTotalTracks {
	if m == nil {
		return nil
	}
	_MediaTransportControlDataTotalTracksCopy := &_MediaTransportControlDataTotalTracks{
		m.MediaTransportControlDataContract.(*_MediaTransportControlData).deepCopy(),
		m.TotalTracksMSB,
		m.TotalTracksMMSB,
		m.TotalTracksMLSB,
		m.TotalTracksLSB,
	}
	_MediaTransportControlDataTotalTracksCopy.MediaTransportControlDataContract.(*_MediaTransportControlData)._SubType = m
	return _MediaTransportControlDataTotalTracksCopy
}

func (m *_MediaTransportControlDataTotalTracks) String() string {
	if m == nil {
		return "<nil>"
	}
	wb := utils.NewWriteBufferBoxBased(
		utils.WithWriteBufferBoxBasedMergeSingleBoxes(),
		utils.WithWriteBufferBoxBasedOmitEmptyBoxes(),
		utils.WithWriteBufferBoxBasedPrintPosLengthFooter(),
	)
	if err := wb.WriteSerializable(context.Background(), m); err != nil {
		return err.Error()
	}
	return wb.GetBox().String()
}
