package web

import (
	. "openreplay/backend/pkg/messages"
)

const ClickRelationTime = 1234

type DeadClickDetector struct {
	lastMouseClick     *MouseClick
	lastTimestamp      uint64
	lastClickTimestamp uint64
	lastMessageID      uint64
	inputIDSet         map[uint64]bool
}

func NewDeadClickDetector() *DeadClickDetector {
	return &DeadClickDetector{inputIDSet: make(map[uint64]bool)}
}

func (d *DeadClickDetector) addInputID(id uint64) {
	d.inputIDSet[id] = true
}

func (d *DeadClickDetector) clearInputIDs() {
	d.inputIDSet = make(map[uint64]bool)
}

func (d *DeadClickDetector) reset() {
	d.lastMouseClick = nil
	d.lastClickTimestamp = 0
	d.lastMessageID = 0
	d.clearInputIDs()
}

func (d *DeadClickDetector) Build() Message {
	// remove reset from external Build call
	defer d.reset()
	if d.lastMouseClick == nil || d.lastClickTimestamp+ClickRelationTime > d.lastTimestamp { // reaction is instant
		return nil
	}
	event := &IssueEvent{
		Type:          "dead_click",
		ContextString: d.lastMouseClick.Label,
		Timestamp:     d.lastClickTimestamp,
		MessageID:     d.lastMessageID,
		Context:       d.lastMouseClick.Selector, // hack to pass selector to db (tags filter)
	}
	return event
}

func (d *DeadClickDetector) Handle(message Message, timestamp uint64) Message {
	d.lastTimestamp = timestamp
	switch msg := message.(type) {
	case *SetInputTarget:
		d.addInputID(msg.ID)
	case *CreateDocument:
		d.clearInputIDs()
	case *MouseClick:
		if msg.Label == "" {
			return nil
		}
		isInputEvent := d.inputIDSet[msg.ID]
		event := d.Build()
		if isInputEvent {
			return event
		}
		d.lastMouseClick = msg
		d.lastClickTimestamp = timestamp
		d.lastMessageID = message.MsgID()
		return event
	case *SetNodeAttribute,
		*RemoveNodeAttribute,
		*CreateElementNode,
		*CreateTextNode,
		*SetNodeFocus,
		*MoveNode,
		*RemoveNode,
		*SetCSSData,
		*SetInputValue,
		*SetInputChecked:
		return d.Build()
	}
	return nil
}
