package pubsub

import (
	"context"

	"github.com/pingcap/log"
	"go.uber.org/zap"
)

type pubsub struct {
	logger      *zap.Logger
	subscribers []Subscriber
}

func NewPublisher(subscribers ...Subscriber) *pubsub {
	return &pubsub{
		logger:      log.With(zap.String("module", "pubsub")),
		subscribers: subscribers,
	}
}

func (p *pubsub) Publish(ctx context.Context, events ...Event) error {
	// TODO(chenfei): should be executed async
	p.scheduleAllSubscriber(ctx, events...)
	return nil
}

func (p *pubsub) scheduleAllSubscriber(ctx context.Context, events ...Event) {
	for _, sub := range p.subscribers {
		p.logger.Debug("schedule on subscriber started", zap.String("name", sub.Name()), zap.Int("evLen", len(events)))
		for _, ev := range events {
			if !sub.Focused(ctx, ev) {
				p.logger.Debug("dont focused on this event, skip", zap.String("name", sub.Name()))
				continue
			}

			if err := sub.OnEvent(ctx, ev); err != nil {
				p.logger.Error("schedule event failed", zap.String("name", sub.Name()), zap.Error(err))
				continue
			}
		}
		p.logger.Debug("schedule on subscriber finished", zap.String("name", sub.Name()))
	}
}
