/*
 * Copyright 2018-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 devices

import (
	"bytes"
	"fmt"
	"sync"

	"github.com/looplab/fsm"
	"github.com/opencord/bbsim/internal/common"
	"github.com/opencord/voltha-protos/v5/go/openolt"
	log "github.com/sirupsen/logrus"
)

var ponLogger = log.WithFields(log.Fields{
	"module": "PON",
})

type AllocIDVal struct {
	OnuSn   *openolt.SerialNumber
	AllocID uint16
}

type AllocIDKey struct {
	PonID    uint32
	OnuID    uint32
	EntityID uint16
}

type PonPort struct {
	// BBSIM Internals
	ID            uint32
	Technology    common.PonTechnology
	NumOnu        int
	Onus          []*Onu
	Olt           *OltDevice
	PacketCount   uint64
	InternalState *fsm.FSM

	// PON Attributes
	OperState *fsm.FSM
	Type      string

	// Allocated resources
	// Some resources (eg: OnuId, AllocId and GemPorts) have to be unique per PON port
	// we are keeping a list so that we can throw an error in cases we receive duplicates
	AllocatedGemPorts     map[uint16]*openolt.SerialNumber
	allocatedGemPortsLock sync.RWMutex
	AllocatedOnuIds       map[uint32]*openolt.SerialNumber
	allocatedOnuIdsLock   sync.RWMutex
	AllocatedAllocIds     map[AllocIDKey]*AllocIDVal // key is AllocIDKey
	allocatedAllocIdsLock sync.RWMutex
}

// CreatePonPort creates pon port object
func CreatePonPort(olt *OltDevice, id uint32, tech common.PonTechnology) *PonPort {
	ponPort := PonPort{
		NumOnu:            olt.NumOnuPerPon,
		ID:                id,
		Technology:        tech,
		Type:              "pon",
		Olt:               olt,
		Onus:              []*Onu{},
		AllocatedGemPorts: make(map[uint16]*openolt.SerialNumber),
		AllocatedOnuIds:   make(map[uint32]*openolt.SerialNumber),
		AllocatedAllocIds: make(map[AllocIDKey]*AllocIDVal),
	}

	ponPort.InternalState = fsm.NewFSM(
		"created",
		fsm.Events{
			{Name: "enable", Src: []string{"created", "disabled"}, Dst: "enabled"},
			{Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
		},
		fsm.Callbacks{
			"enter_enabled": func(e *fsm.Event) {
				ponLogger.WithFields(log.Fields{
					"ID": ponPort.ID,
				}).Debugf("Changing PON Port InternalState from %s to %s", e.Src, e.Dst)

				if e.Src == "created" {
					if olt.ControlledActivation == Default || olt.ControlledActivation == OnlyPON {
						for _, onu := range ponPort.Onus {
							if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
								ponLogger.Errorf("Error initializing ONU: %v", err)
								continue
							}
							if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
								ponLogger.Errorf("Error discover ONU: %v", err)
							}
						}
					}
				} else if e.Src == "disabled" {
					if ponPort.Olt.ControlledActivation == OnlyONU || ponPort.Olt.ControlledActivation == Both {
						// if ONUs are manually activated then only initialize them
						for _, onu := range ponPort.Onus {
							if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
								ponLogger.WithFields(log.Fields{
									"Err":    err,
									"OnuSn":  onu.Sn(),
									"IntfId": onu.PonPortID,
								}).Error("Error initializing ONU")
								continue
							}
						}
					} else {
						for _, onu := range ponPort.Onus {
							if onu.InternalState.Current() == OnuStatePonDisabled {
								if err := onu.InternalState.Event(OnuTxEnable); err != nil {
									ponLogger.WithFields(log.Fields{
										"Err":    err,
										"OnuSn":  onu.Sn(),
										"IntfId": onu.PonPortID,
									}).Error("Error enabling ONU")
								}
							} else if onu.InternalState.Current() == OnuStateDisabled {
								if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
									ponLogger.WithFields(log.Fields{
										"Err":    err,
										"OnuSn":  onu.Sn(),
										"IntfId": onu.PonPortID,
									}).Error("Error initializing ONU")
									continue
								}
								if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
									ponLogger.WithFields(log.Fields{
										"Err":    err,
										"OnuSn":  onu.Sn(),
										"IntfId": onu.PonPortID,
									}).Error("Error discovering ONU")
								}
							} else if onu.InternalState.Current() == OnuStateInitialized {
								if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
									ponLogger.WithFields(log.Fields{
										"Err":    err,
										"OnuSn":  onu.Sn(),
										"IntfId": onu.PonPortID,
									}).Error("Error discovering ONU")
								}
							} else {
								// this is to loudly report unexpected states in order to address them
								ponLogger.WithFields(log.Fields{
									"OnuSn":         onu.Sn(),
									"IntfId":        onu.PonPortID,
									"InternalState": onu.InternalState.Current(),
								}).Error("Unexpected ONU state in PON enabling")
							}
						}
					}
				}
			},
			"enter_disabled": func(e *fsm.Event) {
				for _, onu := range ponPort.Onus {
					if onu.InternalState.Current() == OnuStateInitialized || onu.InternalState.Current() == OnuStateDisabled {
						continue
					}
					if err := onu.InternalState.Event(OnuTxPonDisable); err != nil {
						ponLogger.Errorf("Failed to move ONU in %s states: %v", OnuStatePonDisabled, err)
					}
				}
			},
		},
	)

	ponPort.OperState = fsm.NewFSM(
		"down",
		fsm.Events{
			{Name: "enable", Src: []string{"down"}, Dst: "up"},
			{Name: "disable", Src: []string{"up"}, Dst: "down"},
		},
		fsm.Callbacks{
			"enter_up": func(e *fsm.Event) {
				ponLogger.WithFields(log.Fields{
					"ID": ponPort.ID,
				}).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
				olt.sendPonIndication(ponPort.ID)
			},
			"enter_down": func(e *fsm.Event) {
				ponLogger.WithFields(log.Fields{
					"ID": ponPort.ID,
				}).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
				olt.sendPonIndication(ponPort.ID)
			},
		},
	)
	return &ponPort
}

func (p *PonPort) GetOnuBySn(sn *openolt.SerialNumber) (*Onu, error) {
	for _, onu := range p.Onus {
		if bytes.Equal(onu.SerialNumber.VendorSpecific, sn.VendorSpecific) {
			return onu, nil
		}
	}
	return nil, fmt.Errorf("Cannot find Onu with serial number %d in PonPort %d", sn, p.ID)
}

func (p *PonPort) GetOnuById(id uint32) (*Onu, error) {
	for _, onu := range p.Onus {
		if onu.ID == id {
			return onu, nil
		}
	}
	return nil, fmt.Errorf("Cannot find Onu with id %d in PonPort %d", id, p.ID)
}

// GetNumOfActiveOnus returns number of active ONUs for PON port
func (p *PonPort) GetNumOfActiveOnus() uint32 {
	var count uint32 = 0
	for _, onu := range p.Onus {
		if onu.InternalState.Current() == OnuStateInitialized || onu.InternalState.Current() == OnuStateCreated || onu.InternalState.Current() == OnuStateDisabled {
			continue
		}
		count++
	}
	return count
}

// storeOnuId adds the Id to the ONU Ids already allocated to this PON port
func (p *PonPort) storeOnuId(onuId uint32, onuSn *openolt.SerialNumber) {
	p.allocatedOnuIdsLock.Lock()
	defer p.allocatedOnuIdsLock.Unlock()
	p.AllocatedOnuIds[onuId] = onuSn
}

// removeOnuId removes the OnuId from the allocated resources
func (p *PonPort) removeOnuId(onuId uint32) {
	p.allocatedOnuIdsLock.Lock()
	defer p.allocatedOnuIdsLock.Unlock()
	delete(p.AllocatedOnuIds, onuId)
}

func (p *PonPort) removeAllOnuIds() {
	p.allocatedOnuIdsLock.Lock()
	defer p.allocatedOnuIdsLock.Unlock()
	p.AllocatedOnuIds = make(map[uint32]*openolt.SerialNumber)
}

// isOnuIdAllocated returns whether this OnuId is already in use on this PON
func (p *PonPort) isOnuIdAllocated(onuId uint32) (bool, *openolt.SerialNumber) {
	p.allocatedOnuIdsLock.RLock()
	defer p.allocatedOnuIdsLock.RUnlock()

	if _, ok := p.AllocatedOnuIds[onuId]; ok {
		return true, p.AllocatedOnuIds[onuId]
	}
	return false, nil
}

// storeGemPort adds the gemPortId to the gemports already allocated to this PON port
func (p *PonPort) storeGemPort(gemPortId uint16, onuSn *openolt.SerialNumber) {
	p.allocatedGemPortsLock.Lock()
	defer p.allocatedGemPortsLock.Unlock()
	p.AllocatedGemPorts[gemPortId] = onuSn
}

// removeGemPort removes the gemPortId from the allocated resources
func (p *PonPort) removeGemPort(gemPortId uint16) {
	p.allocatedGemPortsLock.Lock()
	defer p.allocatedGemPortsLock.Unlock()
	delete(p.AllocatedGemPorts, gemPortId)
}

func (p *PonPort) removeGemPortBySn(onuSn *openolt.SerialNumber) {
	p.allocatedGemPortsLock.Lock()
	defer p.allocatedGemPortsLock.Unlock()
	for gemPort, sn := range p.AllocatedGemPorts {
		if sn == onuSn {
			delete(p.AllocatedGemPorts, gemPort)
		}
	}
}

func (p *PonPort) removeAllGemPorts() {
	p.allocatedGemPortsLock.Lock()
	defer p.allocatedGemPortsLock.Unlock()
	p.AllocatedGemPorts = make(map[uint16]*openolt.SerialNumber)
}

// isGemPortAllocated returns whether this gemPort is already in use on this PON
func (p *PonPort) isGemPortAllocated(gemPortId uint16) (bool, *openolt.SerialNumber) {
	p.allocatedGemPortsLock.RLock()
	defer p.allocatedGemPortsLock.RUnlock()

	if _, ok := p.AllocatedGemPorts[gemPortId]; ok {
		return true, p.AllocatedGemPorts[gemPortId]
	}
	return false, nil
}

// storeAllocId adds the Id to the ONU Ids already allocated to this PON port
func (p *PonPort) storeAllocId(ponID uint32, onuID uint32, entityID uint16, allocId uint16, onuSn *openolt.SerialNumber) {
	p.allocatedAllocIdsLock.Lock()
	defer p.allocatedAllocIdsLock.Unlock()
	p.AllocatedAllocIds[AllocIDKey{ponID, onuID, entityID}] = &AllocIDVal{onuSn, allocId}
}

// removeAllocId removes the AllocId from the allocated resources
func (p *PonPort) removeAllocId(ponID uint32, onuID uint32, entityID uint16) {
	p.allocatedAllocIdsLock.Lock()
	defer p.allocatedAllocIdsLock.Unlock()
	allocKey := AllocIDKey{ponID, onuID, entityID}
	delete(p.AllocatedAllocIds, allocKey)
}

// removeAllocIdsForOnuSn removes the all AllocIds for the given onu serial number
func (p *PonPort) removeAllocIdsForOnuSn(onuSn *openolt.SerialNumber) {
	p.allocatedAllocIdsLock.Lock()
	defer p.allocatedAllocIdsLock.Unlock()
	for id, allocObj := range p.AllocatedAllocIds {
		if onuSn == allocObj.OnuSn {
			delete(p.AllocatedAllocIds, id)
		}
	}
}

func (p *PonPort) removeAllAllocIds() {
	p.allocatedAllocIdsLock.Lock()
	defer p.allocatedAllocIdsLock.Unlock()
	p.AllocatedAllocIds = make(map[AllocIDKey]*AllocIDVal)
}

// isAllocIdAllocated returns whether this AllocId is already in use on this PON
func (p *PonPort) isAllocIdAllocated(ponID uint32, onuID uint32, entityID uint16) (bool, *AllocIDVal) {
	p.allocatedAllocIdsLock.RLock()
	defer p.allocatedAllocIdsLock.RUnlock()
	allocKey := AllocIDKey{ponID, onuID, entityID}
	if _, ok := p.AllocatedAllocIds[allocKey]; ok {
		return true, p.AllocatedAllocIds[allocKey]
	}
	return false, nil
}
