/*
 * Copyright 2020-2023 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.Debugw(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.Debugw(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
}
