/*
****************************
struct EventSystem
****************************
session의 Job queue
각 세션마다 자기 자신이 처리해야 할 Event struct의 Event ID를 저장하는 JobQ를 가진다.
*/

package icsevent

import (
	"sync"

	"gitlab.com/ics_cinnamon/voiceStatistics/icserror"
)

///////////////////////////////////////////////////////////////
//전역 세션용 이벤트 시스템 구조체.
type EventSystem struct {
	id   int     //session id
	JobQ *RRData //event id q for session
	m    *sync.Mutex
}

var bigEvtSystem []*EventSystem
var onceEvtSystem sync.Once

//make singleton EventSystem struct
func GetEvtSystemInstance() []*EventSystem {
	onceEvtSystem.Do(func() {
		bigEvtSystem = make([]*EventSystem, channelNum)

		for iter := 0; iter < channelNum; iter++ {
			bigEvtSystem[iter] = new(EventSystem)
			bigEvtSystem[iter].Init(iter)
		}
	})

	return bigEvtSystem
}

func SetChannelNum(chNum int) {
	channelNum = chNum
}

func (es *EventSystem) Init(id int) {
	es.id = id
	es.JobQ = NewRRData()
	es.m = &sync.Mutex{}
}

func GetMyEventSystem(id int) *EventSystem {
	es := GetEvtSystemInstance()
	return es[id]
}

func (es *EventSystem) GetMyID() int {
	return es.id
}

func (es *EventSystem) PutJob(event *Event) (err *icserror.IcsError) {
	if event == nil {
		return icserror.ICSERRInvalidParam
	}
	if es.JobQ == nil {
		return icserror.ICSERREVTNotInit
	}

	es.m.Lock()
	rrerr := Push(es.JobQ, event.ID)
	if rrerr != nil {
		es.m.Unlock()
		return rrerr
	}
	es.m.Unlock()

	return nil
}

func (es *EventSystem) GetJob() (pos int, err *icserror.IcsError) {
	if es.JobQ == nil {
		return -1, icserror.ICSERREVTNotInit
	}

	es.m.Lock()
	var data interface{}
	var h *RRData
	h, data, err = Pop(es.JobQ)
	//es.JobQ, data, err = icsutil.Pop(es.JobQ)
	if err != nil || data == nil {
		//err.Print()
		es.m.Unlock()
		return -1, err
	}

	switch v := data.(type) {
	case int:
		es.JobQ = h
		pos = v

	default:
		pos = -1
		es.m.Unlock()
		return pos, nil
	}
	es.m.Unlock()

	return pos, nil
}

func (es *EventSystem) ClearJob() (err *icserror.IcsError) {
	h := NewEventH()
	for pos, err := es.GetJob(); err != nil; {
		h.removeEvent(pos)
	}

	return nil
}
