package model

import (
	"sync"

	"github.com/boltdb/bolt"
	"github.com/gorilla/websocket"
)

// Settings defines configuration parameters for presence detection behavior.
type SettingsVal struct {
	Location_confidence  int64 `json:"location_confidence"`
	Last_seen_threshold  int64 `json:"last_seen_threshold"`
	Beacon_metrics_size  int   `json:"beacon_metrics_size"`
	HA_send_interval     int64 `json:"ha_send_interval"`
	HA_send_changes_only bool  `json:"ha_send_changes_only"`
}

type Settings struct {
	Settings SettingsVal
	Lock     sync.RWMutex
}

// Incoming_json represents the JSON payload received from beacon messages.
type Incoming_json struct {
	Hostname         string `json:"hostname"`
	MAC              string `json:"mac"`
	RSSI             int64  `json:"rssi"`
	Is_scan_response string `json:"is_scan_response"`
	Ttype            string `json:"type"`
	Data             string `json:"data"`
	Beacon_type      string `json:"beacon_type"`
	UUID             string `json:"uuid"`
	Major            string `json:"major"`
	Minor            string `json:"minor"`
	TX_power         string `json:"tx_power"`
	Namespace        string `json:"namespace"`
	Instance_id      string `json:"instance_id"`
	// button stuff
	HB_ButtonCounter      int64  `json:"hb_button_counter"`
	HB_ButtonCounter_Prev int64  `json:"hb_button_counter_prev"`
	HB_Battery            int64  `json:"hb_button_battery"`
	HB_RandomNonce        string `json:"hb_button_random"`
	HB_ButtonMode         string `json:"hb_button_mode"`
}

// Advertisement describes a generic beacon advertisement payload.
type Advertisement struct {
	ttype   string
	content string
	seen    int64
}

// BeaconMetric stores signal and distance data for a beacon.
type BeaconMetric struct {
	Location  string
	Distance  float64
	Rssi      int64
	Timestamp int64
}

// Location defines a physical location and synchronization control.
type Location struct {
	name string
	lock sync.RWMutex
}

// BestLocation represents the most probable location of a beacon.
type BestLocation struct {
	Distance  float64
	Name      string
	Last_seen int64
}

// HTTPLocation describes a beacon's state as served over HTTP.
type HTTPLocation struct {
	Previous_confident_location string  `json:"previous_confident_location"`
	Distance                    float64 `json:"distance"`
	Name                        string  `json:"name"`
	Beacon_name                 string  `json:"beacon_name"`
	Beacon_id                   string  `json:"beacon_id"`
	Beacon_type                 string  `json:"beacon_type"`
	HB_Battery                  int64   `json:"hb_button_battery"`
	HB_ButtonMode               string  `json:"hb_button_mode"`
	HB_ButtonCounter            int64   `json:"hb_button_counter"`
	Location                    string  `json:"location"`
	Last_seen                   int64   `json:"last_seen"`
}

// LocationChange defines a change event for a beacon's detected location.
type LocationChange struct {
	Beacon_ref        Beacon `json:"beacon_info"`
	Name              string `json:"name"`
	Beacon_name       string `json:"beacon_name"`
	Previous_location string `json:"previous_location"`
	New_location      string `json:"new_location"`
	Timestamp         int64  `json:"timestamp"`
}

// HAMessage represents a Home Assistant integration payload.
type HAMessage struct {
	Beacon_id   string  `json:"id"`
	Beacon_name string  `json:"name"`
	Distance    float64 `json:"distance"`
}

// Beacon holds all relevant information about a tracked beacon device.
type Beacon struct {
	Name                        string        `json:"name"`
	Beacon_id                   string        `json:"beacon_id"`
	Beacon_type                 string        `json:"beacon_type"`
	Beacon_location             string        `json:"beacon_location"`
	Last_seen                   int64         `json:"last_seen"`
	Incoming_JSON               Incoming_json `json:"incoming_json"`
	Distance                    float64       `json:"distance"`
	Previous_location           string
	Previous_confident_location string
	Expired_location            string
	Location_confidence         int64
	Location_history            []string
	Beacon_metrics              []BeaconMetric

	HB_ButtonCounter      int64  `json:"hb_button_counter"`
	HB_ButtonCounter_Prev int64  `json:"hb_button_counter_prev"`
	HB_Battery            int64  `json:"hb_button_battery"`
	HB_RandomNonce        string `json:"hb_button_random"`
	HB_ButtonMode         string `json:"hb_button_mode"`
}

// Button represents a hardware button beacon device.
type Button struct {
	Name            string        `json:"name"`
	Button_id       string        `json:"button_id"`
	Button_type     string        `json:"button_type"`
	Button_location string        `json:"button_location"`
	Incoming_JSON   Incoming_json `json:"incoming_json"`
	Distance        float64       `json:"distance"`
	Last_seen       int64         `json:"last_seen"`

	HB_ButtonCounter int64  `json:"hb_button_counter"`
	HB_Battery       int64  `json:"hb_button_battery"`
	HB_RandomNonce   string `json:"hb_button_random"`
	HB_ButtonMode    string `json:"hb_button_mode"`
}

// BeaconsList holds all known beacons and their synchronization lock.
type BeaconsList struct {
	Beacons map[string]Beacon `json:"beacons"`
	Lock    sync.RWMutex
}

// LocationsList holds all known locations with concurrency protection.
type LocationsList struct {
	Locations map[string]Location
	Lock      sync.RWMutex
}

// Message defines the WebSocket or broadcast message payload.
type Message struct {
	Email    string `json:"email"`
	Username string `json:"username"`
	Message  string `json:"message"`
}

// RawReading represents an incoming raw sensor reading.
type RawReading struct {
	Timestamp string `json:"timestamp"`
	Type      string `json:"type"`
	MAC       string `json:"mac"`
	RSSI      int    `json:"rssi"`
	RawData   string `json:"rawData"`
}

type LatestBeaconsList struct {
	LatestList map[string]Beacon
	Lock       sync.RWMutex
}

type HTTPLocationsList struct {
	Beacons []HTTPLocation `json:"beacons"`
}

type HTTPResultsList struct {
	HTTPResultsLock sync.RWMutex
	HTTPResults     HTTPLocationsList
}

type AppContext struct {
	HTTPResults HTTPResultsList
	Beacons     BeaconsList
	ButtonsList map[string]Button
	Settings    Settings
	Broadcast   chan Message
	Locations   LocationsList
	LatestList  LatestBeaconsList
	Clients     map[*websocket.Conn]bool
}

type ApiUpdate struct {
	Method string
	Beacon Beacon
	ID     string
}

var World = []byte("presence")

var Db *bolt.DB

var HTTPHostPathPtr *string
var HTTPWSHostPathPtr *string
