/*
==================================================================================
  Copyright (c) 2019 AT&T Intellectual Property.
  Copyright (c) 2019 Nokia

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================================
*/
/*
Timer takes four parameters:
	 1) strId 			string   			'string format timerMap key'
	 2) nbrId 			int      			'numeric format timerMap key'
	 3) timerDuration	time.Duration  		'timer duration'
	 4) timerFunction	func(string, int) 	'function to be executed when timer expires'

	Timer function is put inside in-build time.AfterFunc() Go function, where it is run inside own Go routine
	when the timer expires. Timer are two key values. Both are used always, but the other one can be left
	"empty", i.e. strId = "" or  nbrId = 0. Fourth parameter, the timer function is bare function name without
	any function parameters and parenthesis! Filling first parameter strId with related name can improve
	code readability and robustness, even the numeric Id would be enough from functionality point of view.

	TimerStart() function starts the timer. If TimerStart() function is called again with same key values
	while earlier started timer is still in the timerMap, i.e. it has not been stopped or the timer has not
	yet expired, the old timer is deleted and new timer is started with the given time value.

	StopTimer() function stops the timer. There is no need to call StopTimer() function after the timer has
	expired. Timer is removed automatically from the timeMap. Calling StopTimer() function with key values not
	existing in the timerMap, has no effect.

	NOTE: Each timer is run in separate Go routine. Therefore, the function that is executed when timer expires
	MUST be designed to be able run concurrently! Also, function run order of simultaneously expired timers cannot
	guaranteed anyway!

	If you need to transport more information to the timer function, consider to use another map to store the
	information with same key value, as the started timer.

	Init timerMap example:
		timerMap := new(TimerMap)
		timerMap.Init()

	StartTimer() and StartTimer() function usage examples.
	1)
		subReqTime := 2 * time.Second
		subId := 123
		timerMap.StartTimer("RIC_SUB_REQ", int(subId), subReqTime, handleSubscriptionRequestTimer)
		timerMap.StopTimer("RIC_SUB_REQ", int(subId))

	2)
		subReqTime := 2 * time.Second
		strId := "1UHSUwNqxiVgUWXvC4zFaatpZFF"
		timerMap.StartTimer(strId, 0, subReqTime, handleSubscriptionRequestTimer)
		timerMap.StopTimer(strId, 0)

	3)
		subReqTime := 2 * time.Second
		strId := "1UHSUwNqxiVgUWXvC4zFaatpZFF"
		timerMap.StartTimer(RIC_SUB_REQ_" + strId, 0, subReqTime, handleSubscriptionRequestTimer)
		timerMap.timerMap.StopTimer("RIC_SUB_REQ_" + strId, 0)

	Timer function example. This is run if any of the above started timer expires.
		func handleSubscriptionRequestTimer1(strId string, nbrId int) {
			fmt.Printf("Subscription Request timer expired. Name: %v, SubId: %v\n",strId, nbrId)
		}
*/

package control

import (
	"gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
	"sync"
	"time"
)

type TimerKey struct {
	strId string
	nbrId int
}

type TimerInfo struct {
	timerAddress         *time.Timer
	timerFunctionAddress func()
}

type TimerMap struct {
	timer map[TimerKey]TimerInfo
	mutex sync.Mutex
}

// This method should run as a constructor
func (t *TimerMap) Init() {
	t.timer = make(map[TimerKey]TimerInfo)
}

func (t *TimerMap) StartTimer(strId string, nbrId int, expireAfterTime time.Duration, timerFunction func(srtId string, nbrId int)) bool {
	t.mutex.Lock()
	defer t.mutex.Unlock()
	if timerFunction == nil {
		xapp.Logger.Error("StartTimer() timerFunc == nil\n")
		return false
	}
	timerKey := TimerKey{strId, nbrId}
	// Stop timer if there is already timer running with the same id
	if val, ok := t.timer[timerKey]; ok {
		xapp.Logger.Debug("StartTimer() old timer found")
		if val.timerAddress != nil {
			xapp.Logger.Debug("StartTimer() deleting old timer")
			val.timerAddress.Stop()
		}
		delete(t.timer, timerKey)
	}

	// Store in timerMap in-build Go "timer", timer function executor, and the function to be executed when the timer expires
	t.timer[timerKey] = TimerInfo{timerAddress: time.AfterFunc(expireAfterTime, func() { t.timerFunctionExecutor(strId, nbrId) }),
		timerFunctionAddress: func() { timerFunction(strId, nbrId) }}
	return true
}

func (t *TimerMap) StopTimer(strId string, nbrId int) bool {
	t.mutex.Lock()
	defer t.mutex.Unlock()
	timerKey := TimerKey{strId, nbrId}
	if val, ok := t.timer[timerKey]; ok {
		if val.timerAddress != nil {
			val.timerAddress.Stop()
			delete(t.timer, timerKey)
			return true
		} else {
			xapp.Logger.Error("StopTimer() timerAddress == nil")
			return false
		}
	} else {
		xapp.Logger.Debug("StopTimer() Timer not found. May be expired or stopped already. timerKey.strId: %v, timerKey.strId: %v\n", timerKey.strId, timerKey.nbrId)
		return false
	}
}

func (t *TimerMap) timerFunctionExecutor(strId string, nbrId int) {
	t.mutex.Lock()
	timerKey := TimerKey{strId, nbrId}
	if val, ok := t.timer[timerKey]; ok {
		if val.timerFunctionAddress != nil {
			// Take local copy of timer function address
			f := val.timerFunctionAddress
			// Delete timer instance from map
			delete(t.timer, timerKey)
			t.mutex.Unlock()
			// Execute the timer function
			f()
			return
		} else {
			xapp.Logger.Error("timerExecutorFunc() timerFunctionAddress == nil")
			t.mutex.Unlock()
			return
		}
	} else {
		xapp.Logger.Error("timerExecutorFunc() Timer is not anymore in map. timerKey.strId: %v, timerKey.strId: %v\n", timerKey.strId, timerKey.nbrId)
		t.mutex.Unlock()
		return
	}
}
