/*
 Copyright (C) 2013 Aaron Lindsay <aaron@aclindsay.com>
*/

package main

import (
	"github.com/aclindsa/asink"
	"sync"
	"time"
)

type LongPollGroup struct {
	channels []*chan *asink.Event
	lock     sync.Mutex
}

type PollingManager struct {
	lock   sync.RWMutex
	groups map[int64]*LongPollGroup
}

var pm *PollingManager

func init() {
	pm = new(PollingManager)
	pm.groups = make(map[int64]*LongPollGroup)
}

func addPoller(uid int64, channel *chan *asink.Event) {
	pm.lock.RLock()

	group := pm.groups[uid]
	if group != nil {
		group.lock.Lock()
		pm.lock.RUnlock()
		group.channels = append(group.channels, channel)
		group.lock.Unlock()
	} else {
		pm.lock.RUnlock()
		pm.lock.Lock()
		group = new(LongPollGroup)
		group.channels = append(group.channels, channel)
		pm.groups[uid] = group
		pm.lock.Unlock()
	}

	//set timer to call function after one minute
	timeout := time.Duration(1) * time.Minute
	time.AfterFunc(timeout, func() {
		group.lock.Lock()
		for i, c := range group.channels {
			if c == channel {
				copy(group.channels[i:], group.channels[i+1:])
				group.channels = group.channels[:len(group.channels)-1]
				break
			}
		}
		group.lock.Unlock()
		close(*channel)
	})
}

func broadcastToPollers(uid int64, event *asink.Event) {
	//store off the long polling group we're trying to send to and remove
	//it from PollingManager.groups
	pm.lock.Lock()
	group := pm.groups[uid]
	pm.groups[uid] = nil
	pm.lock.Unlock()

	//send event down each of group's channels
	if group != nil {
		group.lock.Lock()
		for _, c := range group.channels {
			*c <- event
		}
		group.lock.Unlock()
	}
}
