/*
* Copyright 2022-present Open Networking Foundation
* 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.
 */

package application

import (
	"sync"
	"time"

	"voltha-go-controller/log"
)

const (
	dhcpTimeout uint8 = 60
)

// done channel required to gracefully stop dhcp server handler thread
var done = make(chan bool)

// dhcpServerInfo map having dhcp network as key and dhcp request response transaction as value
var dhcpServerInfo map[dhcpServerTag]dhcpTransactionInfo

// alarmsRaised is struct having array of dhcp network for which dhcp unreachable alarm raised
var alarmsRaised alarmsRaisedInfo

// mux is mutex variable used for lock unlock
var mux sync.Mutex

// StartDhcpServerHandler starts go routine periodically(every second) to verify DHCP server reachability.
func StartDhcpServerHandler() {
	// Initialize global dhcp map and ticker as one second
	dhcpServerInfo = make(map[dhcpServerTag]dhcpTransactionInfo)
	ticker := time.NewTicker(1 * time.Second)

	// go routine runs checkDhcpTimeout every second and exit if done value is set.
	go func() {
		for {
			select {
			case <-done:
				ticker.Stop()
				return
			case <-ticker.C:
				mux.Lock()
				checkDhcpTimeout()
				mux.Unlock()
			}
		}
	}()
}

// checkDhcpTimeout method called every second to verify dhcp timeout for each DHCP network
func checkDhcpTimeout() {
	// logger.Debugw(ctx, "[dhcptimeout] DHCP MAP Info", log.Fields{"Map": dhcpServerInfo})
	for dsTag, dtInfo := range dhcpServerInfo {
		dtInfo.decrementTimer()
		if dtInfo.getTimer() == 0 {
			logger.Debugw(ctx, "[dhcptimeout]Timer Expired", log.Fields{"ctag": dsTag.cTag, "stag": dsTag.sTag})
			if dtInfo.getReceivedResponseCount() == 0 && !alarmsRaised.isexist(dsTag) {
				alarmsRaised.add(dsTag)
				logger.Infow(ctx, "Alarms Raised", log.Fields{"ctag": dsTag.cTag, "stag": dsTag.sTag})
			}

			// Reset helps in
			// case 1: when 2 requests, 1 response received within timeout interval.
			// case 2: 1 request and no response even after timeout. (Unreachable alarm raised)
			// In both cases, reset method provides additional timeout to receive response before deleting
			dtInfo.resetRequestResponseCount(dhcpTimeout)

			// Delete dhcp entry in map and continue to process next entry if pending request set to 0
			if dtInfo.getPendingRequestCount() == 0 {
				delete(dhcpServerInfo, dsTag)
				logger.Debugw(ctx, "[dhcptimeout]DhcpServerTag info removed", log.Fields{"ctag": dsTag.cTag, "stag": dsTag.sTag})
				// logger.Debugw(ctx, "[dhcptimeout] DHCP MAP Info", log.Fields{"Map": dhcpServerInfo})
				continue
			}
		}
		// Update decremented timer value and continue loop
		dhcpServerInfo[dsTag] = dtInfo
	}
}

// dhcpRequestReceived called for every DHCP request received from client.
func dhcpRequestReceived(cTag, sTag uint16, smac string) {
	logger.Infow(ctx, "Dhcp Request Received", log.Fields{"ctag": cTag, "stag": sTag, "smac": smac})
	var dtInfo dhcpTransactionInfo
	var valueExist bool
	dsTag := newDhcpServerTag(cTag, sTag)

	mux.Lock()
	if dtInfo, valueExist = dhcpServerInfo[dsTag]; !valueExist {
		dtInfo = newDhcpTransactionInfo(dhcpTimeout, smac)
		dtInfo.incrementPendingRequestCount()
	}

	// Source mac received in dhcp request is not same as dtInfo mac then
	// Its new subscriber request, hence increment pending request count.
	// If multiple dhcp request received with same mac are ignored.
	if dtInfo.smac != smac {
		dtInfo.incrementPendingRequestCount()
	}

	dhcpServerInfo[dsTag] = dtInfo
	mux.Unlock()
}

// dhcpResponseReceived called for every DHCP response received from dhcp server.
func dhcpResponseReceived(cTag, sTag uint16) {
	logger.Infow(ctx, "Dhcp Response Received", log.Fields{"ctag": cTag, "stag": sTag})
	var dtInfo dhcpTransactionInfo
	var valueExist bool
	dsTag := newDhcpServerTag(cTag, sTag)

	mux.Lock()
	if dtInfo, valueExist = dhcpServerInfo[dsTag]; !valueExist {
		logger.Warnw(ctx, "Ignore unknown response", log.Fields{"DhcpResp": dsTag})
		mux.Unlock()
		return
	}

	// If already unreachable alarm raised, clear and remove from array
	if alarmsRaised.isexist(dsTag) {
		alarmsRaised.remove(dsTag)
		logger.Infow(ctx, "Alarm Cleared", log.Fields{"ctag": dsTag.cTag, "stag": dsTag.sTag})
	}

	// Increments received count and decrement pending count
	dtInfo.responseReceived()
	logger.Debugw(ctx, "Updated dtInfo", log.Fields{"pendingReq": dtInfo.pendingRequestCount, "receivedReq": dtInfo.receivedResponseCount})

	if dtInfo.getPendingRequestCount() == 0 {
		delete(dhcpServerInfo, dsTag)
	} else {
		dhcpServerInfo[dsTag] = dtInfo
	}
	mux.Unlock()
}

// StopDhcpServerHandler stops dhcp server handler go routine
func StopDhcpServerHandler() {
	done <- true
}

// dhcpServerTag contains unique dhcp network information
type dhcpServerTag struct {
	sTag uint16
	cTag uint16
}

func newDhcpServerTag(cTag, sTag uint16) dhcpServerTag {
	var d dhcpServerTag
	d.sTag = sTag
	d.cTag = cTag
	return d
}

// dhcpTransactionInfo contains DHCP request response transaction information.
type dhcpTransactionInfo struct {
	smac                  string
	pendingRequestCount   uint32
	receivedResponseCount uint32
	previousRequestCount  uint32
	timer                 uint8
}

func newDhcpTransactionInfo(timer uint8, smac string) dhcpTransactionInfo {
	var dt dhcpTransactionInfo
	dt.timer = timer
	dt.smac = smac
	return dt
}

func (dt *dhcpTransactionInfo) getTimer() uint8 {
	return dt.timer
}

func (dt *dhcpTransactionInfo) decrementTimer() uint8 {
	dt.timer--
	return dt.timer
}

func (dt *dhcpTransactionInfo) getPendingRequestCount() uint32 {
	return dt.pendingRequestCount
}

func (dt *dhcpTransactionInfo) incrementPendingRequestCount() {
	dt.pendingRequestCount++
}

func (dt *dhcpTransactionInfo) getReceivedResponseCount() uint32 {
	return dt.receivedResponseCount
}

func (dt *dhcpTransactionInfo) responseReceived() {
	dt.receivedResponseCount++
	dt.pendingRequestCount--
}

func (dt *dhcpTransactionInfo) resetRequestResponseCount(timer uint8) {
	if dt.pendingRequestCount >= dt.previousRequestCount {
		dt.pendingRequestCount = dt.pendingRequestCount - dt.previousRequestCount
	}
	dt.previousRequestCount = dt.pendingRequestCount
	dt.receivedResponseCount = 0
	dt.timer = timer
}

// alarmsRaisedInfo contains the all networks alarm raised information
type alarmsRaisedInfo struct {
	arrayInfo []dhcpServerTag
}

// add an entry into alarm raised array
func (a *alarmsRaisedInfo) add(val dhcpServerTag) {
	a.arrayInfo = append(a.arrayInfo, val)
}

// isexist check if entry exist in alarm raised array
func (a *alarmsRaisedInfo) isexist(val dhcpServerTag) bool {
	for _, srvTag := range a.arrayInfo {
		if srvTag == val {
			return true
		}
	}
	return false
}

// remove deletes given entry from alarm raised array
func (a *alarmsRaisedInfo) remove(val dhcpServerTag) {
	for ind := range a.arrayInfo {
		if a.arrayInfo[ind] == val {
			a.arrayInfo = append(a.arrayInfo[:ind], a.arrayInfo[ind+1:]...)
			break
		}
	}
}
