package client

import (
	"github.com/go-stomp/stomp/v3/frame"
)

type Subscription struct {
	conn    *Conn
	dest    string
	id      string            // client's subscription id
	ack     string            // auto, client, client-individual
	msgId   uint64            // message-id (or ack) for acknowledgement
	subList *SubscriptionList // am I in a list
	frame   *frame.Frame      // message allocated to subscription
}

func newSubscription(c *Conn, dest string, id string, ack string) *Subscription {
	return &Subscription{
		conn: c,
		dest: dest,
		id:   id,
		ack:  ack,
	}
}

func (s *Subscription) Destination() string {
	return s.dest
}

func (s *Subscription) Ack() string {
	return s.ack
}

func (s *Subscription) Id() string {
	return s.id
}

func (s *Subscription) IsAckedBy(msgId uint64) bool {
	switch s.ack {
	case frame.AckAuto:
		return true
	case frame.AckClient:
		// any later message acknowledges an earlier message
		return msgId >= s.msgId
	case frame.AckClientIndividual:
		return msgId == s.msgId
	}

	// should not get here
	panic("invalid value for subscript.ack")
}

func (s *Subscription) IsNackedBy(msgId uint64) bool {
	// TODO: not sure about this, interpreting NACK
	// to apply to an individual message
	return msgId == s.msgId
}

func (s *Subscription) SendQueueFrame(f *frame.Frame) {
	s.setSubscriptionHeader(f)
	s.frame = f

	// let the connection deal with the subscription
	// acknowledgement
	s.conn.subChannel <- s
}

// Send a message frame to the client, as part of this
// subscription. Called within the queue when a message
// frame is available.
func (s *Subscription) SendTopicFrame(f *frame.Frame) {
	s.setSubscriptionHeader(f)

	// topics are handled differently, they just go
	// straight to the client without acknowledgement
	s.conn.writeChannel <- f
}

func (s *Subscription) setSubscriptionHeader(f *frame.Frame) {
	if s.frame != nil {
		panic("subscription already has a frame pending")
	}
	f.Header.Set(frame.Subscription, s.id)
}
