package rpcsrv

import (
	"git.marketally.com/tutus-one/tutus-chain/pkg/core/state"
	"git.marketally.com/tutus-one/tutus-chain/pkg/tutusrpc"
	"git.marketally.com/tutus-one/tutus-chain/pkg/tutusrpc/rpcevent"
	"git.marketally.com/tutus-one/tutus-chain/pkg/util"
	"git.marketally.com/tutus-one/tutus-chain/pkg/vm/vmstate"
)

// notificationEventComparator is a comparator for notification events.
type notificationEventComparator struct {
	filter tutusrpc.SubscriptionFilter
}

// EventID returns the event ID for the notification event comparator.
func (s notificationEventComparator) EventID() tutusrpc.EventID {
	return tutusrpc.NotificationEventID
}

// Filter returns the filter for the notification event comparator.
func (c notificationEventComparator) Filter() tutusrpc.SubscriptionFilter {
	return c.filter
}

// notificationEventContainer is a container for a notification event.
type notificationEventContainer struct {
	ntf *state.ContainedNotificationEvent
}

// EventID returns the event ID for the notification event container.
func (c notificationEventContainer) EventID() tutusrpc.EventID {
	return tutusrpc.NotificationEventID
}

// EventPayload returns the payload for the notification event container.
func (c notificationEventContainer) EventPayload() any {
	return c.ntf
}

func processAppExecResults(aers []state.AppExecResult, filter *tutusrpc.NotificationFilter) []state.ContainedNotificationEvent {
	var notifications []state.ContainedNotificationEvent
	for _, aer := range aers {
		if aer.VMState == vmstate.Halt {
			notifications = append(notifications, filterEvents(aer.Events, aer.Container, filter)...)
		}
	}
	return notifications
}

func filterEvents(events []state.NotificationEvent, container util.Uint256, filter *tutusrpc.NotificationFilter) []state.ContainedNotificationEvent {
	var notifications []state.ContainedNotificationEvent
	for _, evt := range events {
		ntf := state.ContainedNotificationEvent{
			Container:         container,
			NotificationEvent: evt,
		}
		if filter == nil || rpcevent.Matches(&notificationEventComparator{
			filter: *filter,
		}, &notificationEventContainer{ntf: &ntf}) {
			notifications = append(notifications, ntf)
		}
	}
	return notifications
}
