/*
 * 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"
	stdErrors "errors"
	"fmt"

	"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/errors"
	"github.com/apache/plc4x/plc4go/spi/utils"
)

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

// CipService is the corresponding interface of CipService
// Every CIP service response starts with the same 4-byte header: the service code
// (with the response bit set), a reserved byte, a 1-byte general status, and a 1-byte
// 'additional status size'. That last byte is a COUNT OF 16-BIT WORDS that follow it,
// not a status value of its own. It is 0 for every successful response, which is why
// modelling it as a plain 'extStatus uint 8' went unnoticed for years -- but as soon
// as a device reports extended error detail, that byte is a length and everything
// after it shifts. Hence extStatusSize + extStatus, and hence every trailing payload
// length below subtracts '2 * extStatusSize'.
type CipService interface {
	CipServiceContract
	CipServiceRequirements
	fmt.Stringer
	utils.LengthAware
	utils.Serializable
	utils.Copyable
	// IsCipService is a marker method to prevent unintentional type checks (interfaces of same signature)
	IsCipService()
	// CreateBuilder creates a CipServiceBuilder
	CreateCipServiceBuilder() CipServiceBuilder
}

// CipServiceContract provides a set of functions which can be overwritten by a sub struct
type CipServiceContract interface {
	// IsCipService is a marker method to prevent unintentional type checks (interfaces of same signature)
	IsCipService()
	// CreateBuilder creates a CipServiceBuilder
	CreateCipServiceBuilder() CipServiceBuilder
}

// CipServiceRequirements provides a set of functions which need to be implemented by a sub struct
type CipServiceRequirements interface {
	GetLengthInBits(ctx context.Context) uint64
	GetLengthInBytes(ctx context.Context) uint64
	// GetResponse returns Response (discriminator field)
	GetResponse() bool
}

// _CipService is the data-structure of this message
type _CipService struct {
	_SubType interface {
		CipServiceContract
		CipServiceRequirements
	}
}

var _ CipServiceContract = (*_CipService)(nil)

// NewCipService factory function for _CipService
func NewCipService() *_CipService {
	return &_CipService{}
}

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

// CipServiceBuilder is a builder for CipService
type CipServiceBuilder interface {
	utils.Copyable
	// WithMandatoryFields adds all mandatory fields (convenience for using multiple builder calls)
	WithMandatoryFields() CipServiceBuilder
	// AsCipServiceRequest converts this build to a subType of CipService. It is always possible to return to current builder using Done()
	AsCipServiceRequest() CipServiceRequestBuilder
	// AsCipServiceResponse converts this build to a subType of CipService. It is always possible to return to current builder using Done()
	AsCipServiceResponse() CipServiceResponseBuilder
	// Build builds the CipService or returns an error if something is wrong
	PartialBuild() (CipServiceContract, error)
	// MustBuild does the same as Build but panics on error
	PartialMustBuild() CipServiceContract
	// Build builds the CipService or returns an error if something is wrong
	Build() (CipService, error)
	// MustBuild does the same as Build but panics on error
	MustBuild() CipService
}

// NewCipServiceBuilder() creates a CipServiceBuilder
func NewCipServiceBuilder() CipServiceBuilder {
	return &_CipServiceBuilder{_CipService: new(_CipService)}
}

type _CipServiceChildBuilder interface {
	utils.Copyable
	setParent(CipServiceContract)
	buildForCipService() (CipService, error)
}

type _CipServiceBuilder struct {
	*_CipService

	childBuilder _CipServiceChildBuilder

	collectedErr []error
}

var _ (CipServiceBuilder) = (*_CipServiceBuilder)(nil)

func (b *_CipServiceBuilder) WithMandatoryFields() CipServiceBuilder {
	return b
}

func (b *_CipServiceBuilder) PartialBuild() (CipServiceContract, error) {
	if err := stdErrors.Join(b.collectedErr...); err != nil {
		return nil, errors.Wrap(err, "error occurred during build")
	}
	return b._CipService.deepCopy(), nil
}

func (b *_CipServiceBuilder) PartialMustBuild() CipServiceContract {
	build, err := b.PartialBuild()
	if err != nil {
		panic(err)
	}
	return build
}

func (b *_CipServiceBuilder) AsCipServiceRequest() CipServiceRequestBuilder {
	if cb, ok := b.childBuilder.(CipServiceRequestBuilder); ok {
		return cb
	}
	cb := NewCipServiceRequestBuilder().(*_CipServiceRequestBuilder)
	cb.parentBuilder = b
	b.childBuilder = cb
	return cb
}

func (b *_CipServiceBuilder) AsCipServiceResponse() CipServiceResponseBuilder {
	if cb, ok := b.childBuilder.(CipServiceResponseBuilder); ok {
		return cb
	}
	cb := NewCipServiceResponseBuilder().(*_CipServiceResponseBuilder)
	cb.parentBuilder = b
	b.childBuilder = cb
	return cb
}

func (b *_CipServiceBuilder) Build() (CipService, error) {
	v, err := b.PartialBuild()
	if err != nil {
		return nil, errors.Wrap(err, "error occurred during partial build")
	}
	if b.childBuilder == nil {
		return nil, errors.New("no child builder present")
	}
	b.childBuilder.setParent(v)
	return b.childBuilder.buildForCipService()
}

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

func (b *_CipServiceBuilder) DeepCopy() any {
	_copy := b.CreateCipServiceBuilder().(*_CipServiceBuilder)
	_copy.childBuilder = b.childBuilder.DeepCopy().(_CipServiceChildBuilder)
	_copy.childBuilder.setParent(_copy)
	if b.collectedErr != nil {
		copy(_copy.collectedErr, b.collectedErr)
	}
	return _copy
}

// CreateCipServiceBuilder creates a CipServiceBuilder
func (b *_CipService) CreateCipServiceBuilder() CipServiceBuilder {
	if b == nil {
		return NewCipServiceBuilder()
	}
	return &_CipServiceBuilder{_CipService: b.deepCopy()}
}

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

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

func (m *_CipService) GetPlx4xTypeName() string {
	return "CipService"
}

func (m *_CipService) getLengthInBits(ctx context.Context) uint64 {
	lengthInBits := uint64(0)
	// Discriminator Field (response)
	lengthInBits += 1

	return lengthInBits
}

func (m *_CipService) GetLengthInBits(ctx context.Context) uint64 {
	return m._SubType.GetLengthInBits(ctx)
}

func (m *_CipService) GetLengthInBytes(ctx context.Context) uint64 {
	return m._SubType.GetLengthInBits(ctx) / 8
}

func CipServiceParse[T CipService](ctx context.Context, theBytes []byte, connected bool, serviceLen uint16) (T, error) {
	return CipServiceParseWithBuffer[T](ctx, utils.NewReadBufferByteBased(theBytes), connected, serviceLen)
}

func CipServiceParseWithBufferProducer[T CipService](connected bool, serviceLen uint16) func(ctx context.Context, readBuffer utils.ReadBuffer) (T, error) {
	return func(ctx context.Context, readBuffer utils.ReadBuffer) (T, error) {
		v, err := CipServiceParseWithBuffer[T](ctx, readBuffer, connected, serviceLen)
		if err != nil {
			var zero T
			return zero, err
		}
		return v, nil
	}
}

func CipServiceParseWithBuffer[T CipService](ctx context.Context, readBuffer utils.ReadBuffer, connected bool, serviceLen uint16) (T, error) {
	v, err := (new(_CipService)).parse(ctx, readBuffer, connected, serviceLen)
	if err != nil {
		var zero T
		return zero, err
	}
	vc, ok := v.(T)
	if !ok {
		var zero T
		return zero, errors.Errorf("Unexpected type %T. Expected type %T", v, *new(T))
	}
	return vc, nil
}

func (m *_CipService) parse(ctx context.Context, readBuffer utils.ReadBuffer, connected bool, serviceLen uint16) (__cipService CipService, err error) {
	positionAware := readBuffer
	_ = positionAware
	if pullErr := readBuffer.PullContext("CipService"); pullErr != nil {
		return nil, errors.Wrap(pullErr, "Error pulling for CipService")
	}
	currentPos := positionAware.GetPos()
	_ = currentPos

	response, err := ReadDiscriminatorField[bool](ctx, "response", ReadBoolean(readBuffer))
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("Error parsing 'response' field"))
	}

	// Switch Field (Depending on the discriminator values, passes the instantiation to a sub-type)
	var _child CipService
	switch {
	case response == bool(false): // CipServiceRequest
		if _child, err = new(_CipServiceRequest).parse(ctx, readBuffer, m, connected, uint16(serviceLen)); err != nil {
			return nil, errors.Wrap(err, "Error parsing sub-type CipServiceRequest for type-switch of CipService")
		}
	case response == bool(true): // CipServiceResponse
		if _child, err = new(_CipServiceResponse).parse(ctx, readBuffer, m, connected, uint16(serviceLen)); err != nil {
			return nil, errors.Wrap(err, "Error parsing sub-type CipServiceResponse for type-switch of CipService")
		}
	default:
		return nil, errors.Errorf("Unmapped type for parameters [response=%v]", response)
	}

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

	return _child, nil
}

func (pm *_CipService) serializeParent(ctx context.Context, writeBuffer utils.WriteBuffer, child CipService, serializeChildFunction func() error) error {
	// We redirect all calls through client as some methods are only implemented there
	m := child
	_ = m
	positionAware := writeBuffer
	_ = positionAware
	log := zerolog.Ctx(ctx)
	_ = log
	if pushErr := writeBuffer.PushContext("CipService"); pushErr != nil {
		return errors.Wrap(pushErr, "Error pushing for CipService")
	}

	if err := WriteDiscriminatorField(ctx, "response", m.GetResponse(), WriteBoolean(writeBuffer)); err != nil {
		return errors.Wrap(err, "Error serializing 'response' field")
	}

	// Switch field (Depending on the discriminator values, passes the serialization to a sub-type)
	if _typeSwitchErr := serializeChildFunction(); _typeSwitchErr != nil {
		return errors.Wrap(_typeSwitchErr, "Error serializing sub-type field")
	}

	if popErr := writeBuffer.PopContext("CipService"); popErr != nil {
		return errors.Wrap(popErr, "Error popping for CipService")
	}
	return nil
}

func (m *_CipService) IsCipService() {}

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

func (m *_CipService) deepCopy() *_CipService {
	if m == nil {
		return nil
	}
	_CipServiceCopy := &_CipService{
		nil, // will be set by child
	}
	return _CipServiceCopy
}
