package term_conn

import (
	"errors"
	"log"
	"sync"

	"github.com/gorilla/websocket"
)

// a simple registry for actors and their channels. It is possible to
// design this using channels, but it is simple enough with mutex
type Registry struct {
	mtx     sync.Mutex
	players map[string]*TermConn
}

var registry Registry

func (reg *Registry) init() {
	reg.players = make(map[string]*TermConn)
}

func (d *Registry) addPlayer(tc *TermConn) {
	d.mtx.Lock()
	if _, ok := d.players[tc.Name]; ok {
		log.Println(tc.Name, "Already exist in the dispatcher, skip registration")
	} else {
		d.players[tc.Name] = tc
		log.Println("Add interactive session to registry", tc.Name)
	}
	d.mtx.Unlock()
}

func (d *Registry) removePlayer(name string) error {
	d.mtx.Lock()
	var err error = errors.New("not found")

	if _, ok := d.players[name]; ok {
		delete(d.players, name)
		err = nil
		log.Println("Removed interactive session to registry", name)
	}

	d.mtx.Unlock()
	return err
}

// we do not want to return the channel to viewer so it won't be used out of the critical section
func (d *Registry) sendToPlayer(name string, ws *websocket.Conn) bool {
	d.mtx.Lock()
	tc, ok := d.players[name]

	if ok {
		tc.viewChan <- ws
	}

	d.mtx.Unlock()
	return ok
}

// Send a command to the session to start, stop recording
func (d *Registry) recordSession(id string, cmd int) bool {
	d.mtx.Lock()
	tc, ok := d.players[id]

	if ok {
		tc.recordChan <- cmd
	}

	d.mtx.Unlock()
	return ok
}

func ForEachSession(fp func(tc *TermConn)) {
	registry.mtx.Lock()
	for _, v := range registry.players {
		fp(v)
	}
	registry.mtx.Unlock()
}