// Code generated by Azure.Iot.Operations.ProtocolCompilerLib v0.10.0.0; DO NOT EDIT.
package counter

import (
	"context"

	"github.com/Azure/iot-operations-sdks/go/protocol"
)

type CounterCommandHandlers interface {

	ReadCounter(
		context.Context,
		*protocol.CommandRequest[any],
	) (*protocol.CommandResponse[ReadCounterResponsePayload], error)

	Increment(
		context.Context,
		*protocol.CommandRequest[IncrementRequestPayload],
	) (*protocol.CommandResponse[IncrementResponsePayload], error)

	Reset(
		context.Context,
		*protocol.CommandRequest[any],
	) (*protocol.CommandResponse[any], error)
}

type CounterService struct {
	protocol.Listeners
	*ReadCounterCommandExecutor
	*IncrementCommandExecutor
	*ResetCommandExecutor
	*TelemetrySender
}

type CounterClient struct {
	protocol.Listeners
	*ReadCounterCommandInvoker
	*IncrementCommandInvoker
	*ResetCommandInvoker
	*TelemetryReceiver
}

const (
	CommandTopic = "rpc/command-samples/{executorId}/{commandName}"
	TelemetryTopic = "telemetry/telemetry-samples/counterValue"
)

func NewCounterService(
	app *protocol.Application,
	client protocol.MqttClient,
	commandHandlers CounterCommandHandlers,
	opts ...protocol.Option,
) (*CounterService, error) {
	var err error

	serverOpts := []protocol.Option{
		protocol.WithTopicTokenNamespace("ex:"),
		protocol.WithTopicTokens{
			"executorId": client.ID(),
			"senderId":   client.ID(),
		},
	}

	var executorOpts protocol.CommandExecutorOptions
	executorOpts.ApplyOptions(opts, serverOpts...)

	var senderOpts protocol.TelemetrySenderOptions
	senderOpts.ApplyOptions(opts, serverOpts...)

	counterService := &CounterService{}

	counterService.ReadCounterCommandExecutor, err = NewReadCounterCommandExecutor(
		app,
		client,
		CommandTopic,
		commandHandlers.ReadCounter,
		&executorOpts,
	)
	if err != nil {
		counterService.Close()
		return nil, err
	}
	counterService.Listeners = append(counterService.Listeners, counterService.ReadCounterCommandExecutor)

	counterService.IncrementCommandExecutor, err = NewIncrementCommandExecutor(
		app,
		client,
		CommandTopic,
		commandHandlers.Increment,
		&executorOpts,
	)
	if err != nil {
		counterService.Close()
		return nil, err
	}
	counterService.Listeners = append(counterService.Listeners, counterService.IncrementCommandExecutor)

	counterService.ResetCommandExecutor, err = NewResetCommandExecutor(
		app,
		client,
		CommandTopic,
		commandHandlers.Reset,
		&executorOpts,
	)
	if err != nil {
		counterService.Close()
		return nil, err
	}
	counterService.Listeners = append(counterService.Listeners, counterService.ResetCommandExecutor)

	counterService.TelemetrySender, err = NewTelemetrySender(
		app,
		client,
		TelemetryTopic,
		&senderOpts,
	)
	if err != nil {
		counterService.Close()
		return nil, err
	}

	return counterService, nil
}

func NewCounterClient(
	app *protocol.Application,
	client protocol.MqttClient,
	telemetryHandler protocol.TelemetryHandler[TelemetryCollection],
	opts ...protocol.Option,
) (*CounterClient, error) {
	var err error

	clientOpts := []protocol.Option{
		protocol.WithTopicTokenNamespace("ex:"),
		protocol.WithTopicTokens{
			"invokerClientId": client.ID(),
		},
	}

	var invokerOpts protocol.CommandInvokerOptions
	invokerOpts.ApplyOptions(opts, clientOpts...)

	var receiverOpts protocol.TelemetryReceiverOptions
	receiverOpts.ApplyOptions(opts, clientOpts...)

	counterClient := &CounterClient{}

	counterClient.ReadCounterCommandInvoker, err = NewReadCounterCommandInvoker(
		app,
		client,
		CommandTopic,
		&invokerOpts,
	)
	if err != nil {
		counterClient.Close()
		return nil, err
	}
	counterClient.Listeners = append(counterClient.Listeners, counterClient.ReadCounterCommandInvoker)

	counterClient.IncrementCommandInvoker, err = NewIncrementCommandInvoker(
		app,
		client,
		CommandTopic,
		&invokerOpts,
	)
	if err != nil {
		counterClient.Close()
		return nil, err
	}
	counterClient.Listeners = append(counterClient.Listeners, counterClient.IncrementCommandInvoker)

	counterClient.ResetCommandInvoker, err = NewResetCommandInvoker(
		app,
		client,
		CommandTopic,
		&invokerOpts,
	)
	if err != nil {
		counterClient.Close()
		return nil, err
	}
	counterClient.Listeners = append(counterClient.Listeners, counterClient.ResetCommandInvoker)

	counterClient.TelemetryReceiver, err = NewTelemetryReceiver(
		app,
		client,
		TelemetryTopic,
		telemetryHandler,
		&receiverOpts,
	)
	if err != nil {
		counterClient.Close()
		return nil, err
	}
	counterClient.Listeners = append(counterClient.Listeners, counterClient.TelemetryReceiver)

	return counterClient, nil
}
