package handler

import (
	"natpass/code/network"
	"sync"
	"sync/atomic"
	"time"

	"github.com/lwch/logging"
)

type clients struct {
	sync.RWMutex
	parent *Handler
	id     string
	data   map[uint32]*client // idx => client
	idx    uint32
}

func newClients(parent *Handler, id string) *clients {
	logging.Info("new clients: %s", id)
	return &clients{
		parent: parent,
		id:     id,
		data:   make(map[uint32]*client),
	}
}

func (cs *clients) new(idx uint32, conn *network.Conn) *client {
	logging.Info("new client: %s-%d", cs.id, idx)
	cli := &client{
		parent:  cs,
		idx:     idx,
		conn:    conn,
		updated: time.Now(),
		links:   make(map[string]struct{}),
	}
	cs.Lock()
	cs.data[idx] = cli
	cs.Unlock()
	return cli
}

func (cs *clients) next() *client {
	list := make([]*client, 0, len(cs.data))
	cs.RLock()
	for _, cli := range cs.data {
		list = append(list, cli)
	}
	cs.RUnlock()
	if len(list) > 0 {
		idx := atomic.AddUint32(&cs.idx, 1)
		cli := list[int(idx)%len(list)]
		return cli
	}
	return nil
}

func (cs *clients) close(idx uint32) {
	cs.Lock()
	delete(cs.data, idx)
	cs.Unlock()
	if len(cs.data) == 0 {
		cs.parent.removeClients(cs.id)
	}
}
