package web

import (
	"encoding/json"
	"math"

	. "openreplay/backend/pkg/messages"
)

const MIN_COUNT = 3
const MEM_RATE_THRESHOLD = 300 // % to average

type MemoryIssueDetector struct {
	startMessageID uint64
	startTimestamp uint64
	rate           int
	count          float64
	sum            float64
	contextString  string
}

func (f *MemoryIssueDetector) reset() {
	f.startTimestamp = 0
	f.startMessageID = 0
	f.rate = 0
}

func (f *MemoryIssueDetector) Build() Message {
	if f.startTimestamp == 0 {
		return nil
	}
	payload, err := json.Marshal(struct{ Rate int }{f.rate - 100})
	if err != nil {
		payload = []byte("{}")
	}
	event := &IssueEvent{
		Type:          "memory",
		Timestamp:     f.startTimestamp,
		MessageID:     f.startMessageID,
		ContextString: f.contextString,
		Payload:       string(payload),
	}
	f.reset()
	return event
}

func (f *MemoryIssueDetector) Handle(message Message, timestamp uint64) Message {
	switch msg := message.(type) {
	case *PerformanceTrack:
		if f.count < MIN_COUNT {
			f.sum += float64(msg.UsedJSHeapSize)
			f.count++
			return nil
		}

		average := f.sum / f.count
		rate := int(math.Round(float64(msg.UsedJSHeapSize) / average * 100))

		f.sum += float64(msg.UsedJSHeapSize)
		f.count++

		if rate >= MEM_RATE_THRESHOLD {
			if f.startTimestamp == 0 {
				f.startTimestamp = timestamp
				f.startMessageID = message.MsgID()
			}
			if f.rate < rate {
				f.rate = rate
			}
		} else {
			return f.Build()
		}
	case *SetPageLocation:
		f.contextString = msg.URL
	}
	return nil
}
