package event

import (
	"encoding/json"
	"time"

	"github.com/rs/zerolog/log"
	"source.gleipnir.technology/Gleipnir/nidus-sync/config"
)

var chanEvents chan<- Envelope

type Event struct {
	Resource string    `json:"resource"`
	Time     time.Time `json:"time"`
	Type     EventType `json:"type"`
	URI      string    `json:"uri"`
}

func (e Event) MarshalJSON() ([]byte, error) {
	to_marshal := make(map[string]any, 0)
	to_marshal["resource"] = e.Resource
	to_marshal["time"] = e.Time
	to_marshal["type"] = e.Type.String()
	to_marshal["uri"] = e.URI
	return json.Marshal(to_marshal)
}

type Envelope struct {
	Event          Event
	OrganizationID int32
	UserID         int32
}

func SetEventChannel(chan_events chan<- Envelope) {
	chanEvents = chan_events
}

type EventType int

const (
	EventTypeCreated EventType = iota
	EventTypeDeleted
	EventTypeHeartbeat
	EventTypeShutdown
	EventTypeSudo
	EventTypeUnknown
	EventTypeUpdated
)

func (et EventType) String() string {
	switch et {
	case EventTypeCreated:
		return "created"
	case EventTypeDeleted:
		return "deleted"
	case EventTypeHeartbeat:
		return "heartbeat"
	case EventTypeShutdown:
		return "shutdown"
	case EventTypeSudo:
		return "sudo"
	case EventTypeUnknown:
		return "unknown"
	case EventTypeUpdated:
		return "updated"
	}
	return "unknown"
}
func EventTypeFromString(s string) EventType {
	switch s {
	case "created":
		return EventTypeCreated
	case "deleted":
		return EventTypeDeleted
	case "heartbeat":
		return EventTypeHeartbeat
	case "shutdown":
		return EventTypeShutdown
	case "sudo":
		return EventTypeSudo
	case "updated":
		return EventTypeUpdated
	default:
		return EventTypeUnknown
	}
}

type ResourceType int

const (
	TypeUnknown = iota
	TypeCommunication
	TypeFileCSV
	TypeNoteAudio
	TypeNoteImage
	TypeReviewTask
	TypeRMOCompliance
	TypeRMONuisance
	TypeRMOPublicReport
	TypeRMOWater
	TypeSession
	TypeSignal
	TypeSite
)

func Created(t ResourceType, organization_id int32, uri_id string) {
	log.Debug().Int("resource type", int(t)).Int32("org", organization_id).Str("uri", uri_id).Msg("created event")
	go Send(Envelope{
		Event: Event{
			Resource: resourceString(t),
			Time:     time.Now(),
			Type:     EventTypeCreated,
			URI:      makeURI(t, uri_id),
		},
		OrganizationID: organization_id,
	})
}
func Shutdown() {
	go Send(Envelope{
		Event: Event{
			Resource: "system",
			Time:     time.Now(),
			Type:     EventTypeShutdown,
			URI:      config.MakeURLNidus("/"),
		},
		OrganizationID: 0,
	})
}
func Updated(t ResourceType, organization_id int32, uri_id string) {
	go Send(Envelope{
		Event: Event{
			Resource: resourceString(t),
			Time:     time.Now(),
			Type:     EventTypeUpdated,
			URI:      makeURI(t, uri_id),
		},
		OrganizationID: organization_id,
	})
}
func UpdatedUser(t ResourceType, user_id int32, uri_id string) {
	go Send(Envelope{
		Event: Event{
			Resource: resourceString(t),
			Time:     time.Now(),
			Type:     EventTypeUpdated,
			URI:      makeURI(t, uri_id),
		},
		UserID: user_id,
	})
}
func Send(env Envelope) {
	chanEvents <- env
}
func resourceString(t ResourceType) string {
	switch t {
	case TypeCommunication:
		return "sync:communication"
	case TypeFileCSV:
		return "sync:filecsv"
	case TypeNoteAudio:
		return "sync:note:audio"
	case TypeNoteImage:
		return "sync:note:image"
	case TypeReviewTask:
		return "sync:review-task"
	case TypeRMOCompliance:
		return "rmo:publicreport.compliance"
	case TypeRMONuisance:
		return "rmo:publicreport.nuisance"
	case TypeRMOPublicReport:
		return "rmo:publicreport"
	case TypeRMOWater:
		return "rmo:publicreport.water"
	case TypeSession:
		return "sync:session"
	case TypeSignal:
		return "sync:signal"
	case TypeSite:
		return "sync:site"
	default:
		return "unknown"
	}
}
func makeURI(t ResourceType, id string) string {
	switch t {
	case TypeCommunication:
		return config.MakeURLNidus("/api/communication/%s", id)
	case TypeFileCSV:
		return config.MakeURLNidus("/api/upload/%s", id)
	case TypeNoteAudio:
		return config.MakeURLNidus("/api/note/%s", id)
	case TypeNoteImage:
		return config.MakeURLNidus("/api/note/%s", id)
	case TypeReviewTask:
		return config.MakeURLNidus("/api/review/%s", id)
	case TypeRMOCompliance:
		return config.MakeURLReport("/api/publicreport/compliance/%s", id)
	case TypeRMONuisance:
		return config.MakeURLReport("/api/publicreport/nuisance/%s", id)
	case TypeRMOPublicReport:
		return config.MakeURLReport("/api/publicreport/%s", id)
	case TypeRMOWater:
		return config.MakeURLReport("/api/publicrreport/water/%s", id)
	case TypeSession:
		return config.MakeURLReport("/api/session")
	case TypeSignal:
		return config.MakeURLReport("/api/signal/%s", id)
	case TypeSite:
		return config.MakeURLReport("/api/site/%s", id)
	default:
		return config.MakeURLReport("/unknown")
	}
}
