/*
 * Copyright 2020-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 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
}
