/*
 * Copyright 2020-2024 Open Networking Foundation (ONF) and the ONF Contributors
 *
 * 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 common provides global definitions
package common

import (
	"context"
	"fmt"
	"strconv"
	"strings"
	"time"

	//"sync"
	//"time"

	//"github.com/opencord/voltha-lib-go/v7/pkg/kafka"
	"github.com/opencord/voltha-lib-go/v7/pkg/log"
	vc "github.com/opencord/voltha-protos/v5/go/common"
	of "github.com/opencord/voltha-protos/v5/go/openflow_13"
	"github.com/opencord/voltha-protos/v5/go/voltha"
)

// NewOnuUniPort returns a new instance of a OnuUniPort
func NewOnuUniPort(ctx context.Context, aUniID uint8, aPortNo uint32, aInstNo uint16,
	aPortType UniPortType) *OnuUniPort {
	logger.Infow(ctx, "init-onuUniPort", log.Fields{"uniID": aUniID,
		"portNo": aPortNo, "InstNo": aInstNo, "type": aPortType})
	var OnuUniPort OnuUniPort
	OnuUniPort.Enabled = false
	OnuUniPort.Name = "uni-" + strconv.FormatUint(uint64(aPortNo), 10)
	OnuUniPort.PortNo = aPortNo
	OnuUniPort.PortType = aPortType
	// so far it seems as here ofpPortNo/Name ist the same as the original port name ...??
	OnuUniPort.OfpPortNo = OnuUniPort.Name
	OnuUniPort.UniID = aUniID
	OnuUniPort.MacBpNo = aUniID + 1 //ensure >0 instanceNo
	OnuUniPort.EntityID = aInstNo
	OnuUniPort.AdminState = vc.AdminState_ENABLED //enabled per create
	OnuUniPort.OperState = vc.OperStatus_UNKNOWN
	OnuUniPort.PPort = nil // to be set on create
	return &OnuUniPort
}

// CreateVolthaPort creates the Voltha port based on ONU UNI Port and informs the core about it
func (oo *OnuUniPort) CreateVolthaPort(ctx context.Context, apDeviceHandler IdeviceHandler) error {
	logger.Infow(ctx, "creating-voltha-uni-port", log.Fields{
		"device-id": apDeviceHandler.GetDevice().Id, "portNo": oo.PortNo})
	//200630: per [VOL-3202] OF port info is now to be delivered within UniPort create
	//  not doing so crashes rw_core processing (at least still in 200630 version)
	var name string
	var capacity uint32
	// In the future, We'll add port type into if case
	if oo.PortType == UniPPTPPots {
		name = apDeviceHandler.GetDevice().SerialNumber + "-P-" + strconv.FormatUint(uint64(oo.MacBpNo), 10)
		capacity = uint32(of.OfpPortFeatures_OFPPF_COPPER | of.OfpPortFeatures_OFPPF_OTHER)
	} else {
		name = apDeviceHandler.GetDevice().SerialNumber + "-" + strconv.FormatUint(uint64(oo.MacBpNo), 10)
		capacity = uint32(of.OfpPortFeatures_OFPPF_COPPER | of.OfpPortFeatures_OFPPF_1GB_FD)
	}
	var macOctets [6]uint8
	macOctets[5] = 0x08
	macOctets[4] = uint8(*apDeviceHandler.GetPonPortNumber() >> 8)
	macOctets[3] = uint8(*apDeviceHandler.GetPonPortNumber())
	macOctets[2] = uint8(oo.PortNo >> 16)
	macOctets[1] = uint8(oo.PortNo >> 8)
	macOctets[0] = uint8(oo.PortNo)
	hwAddr := genMacFromOctets(macOctets)
	ofHwAddr := macAddressToUint32Array(hwAddr)
	ofUniPortState := of.OfpPortState_OFPPS_LINK_DOWN
	/* as the VOLTHA port create is only called directly after Uni Port create
	   the OfPortOperState is always Down
	   Note: this way the OfPortOperState won't ever change (directly in adapter)
	   maybe that was already always the case, but looks a bit weird - to be kept in mind ...
		if pUniPort.operState == vc.OperStatus_ACTIVE {
			ofUniPortState = of.OfpPortState_OFPPS_LIVE
		}
	*/
	logger.Infow(ctx, "ofPort values", log.Fields{
		"forUniPortName": oo.Name, "forMacBase": hwAddr,
		"name": name, "hwAddr": ofHwAddr, "OperState": ofUniPortState, "capacity": capacity})

	pUniPort := &voltha.Port{
		DeviceId:   apDeviceHandler.GetDevice().Id,
		PortNo:     oo.PortNo,
		Label:      oo.Name,
		Type:       voltha.Port_ETHERNET_UNI,
		AdminState: oo.AdminState,
		OperStatus: oo.OperState,
		// obviously empty peer setting
		OfpPort: &of.OfpPort{
			Name:       name,
			HwAddr:     ofHwAddr,
			Config:     0,
			State:      uint32(ofUniPortState),
			Curr:       capacity,
			Advertised: capacity,
			Peer:       capacity,
			CurrSpeed:  1000,
			MaxSpeed:   1000,
		},
	}
	maxRetry := 3
	retryCnt := 0
	var err error
	for retryCnt = 0; retryCnt < maxRetry; retryCnt++ {
		if err = apDeviceHandler.CreatePortInCore(ctx, pUniPort); err != nil {
			logger.Errorf(ctx, "Device FSM: PortCreated-failed-%s, retrying after a delay", err)
			// retry after a sleep
			time.Sleep(2 * time.Second)
		} else {
			// success, break from retry loop
			break
		}
	}
	if retryCnt == maxRetry { // maxed out..
		logger.Errorf(ctx, "Device FSM: PortCreated-failed-%s", err)
		return fmt.Errorf("device-fsm-port-create-failed-%s", err)
	}
	logger.Infow(ctx, "Voltha OnuUniPort-added", log.Fields{
		"device-id": apDeviceHandler.GetDevice().Id, "PortNo": oo.PortNo})
	oo.PPort = pUniPort
	oo.OperState = vc.OperStatus_DISCOVERED

	return nil
}

// SetOperState modifies OperState of the the UniPort
func (oo *OnuUniPort) SetOperState(aNewOperState vc.OperStatus_Types) {
	oo.OperState = aNewOperState
}

// uni port related utility functions (so far only used here)
func genMacFromOctets(aOctets [6]uint8) string {
	return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
		aOctets[5], aOctets[4], aOctets[3],
		aOctets[2], aOctets[1], aOctets[0])
}

// copied from OLT Adapter: unify centrally ?
func macAddressToUint32Array(mac string) []uint32 {
	slist := strings.Split(mac, ":")
	result := make([]uint32, len(slist))
	var err error
	var tmp int64
	for index, val := range slist {
		if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
			return []uint32{1, 2, 3, 4, 5, 6}
		}
		result[index] = uint32(tmp)
	}
	return result
}
