/*
 * 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 (
	"bytes"
	"context"
	"encoding/binary"
	"errors"
	"fmt"
	"net"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/looplab/fsm"
	me "github.com/opencord/omci-lib-go/v2/generated"
	"github.com/opencord/voltha-lib-go/v7/pkg/log"
)

// GetTpIDFromTpPath extracts TpID from the TpPath.
// On success it returns a valid TpID and nil error.
// On failure it returns TpID as 0 and the error.
func GetTpIDFromTpPath(tpPath string) (uint8, error) {
	// tpPath is of the format  <technology>/<table_id>/olt-{}/pon-{}/onu-{}/uni-{}
	// A sample tpPath is ==> XGS-PON/64/olt-{12345abcd}/pon-{0}/onu-{1}/uni-{1}
	var tpPathFormat = regexp.MustCompile(`^[a-zA-Z\-_]+/[0-9]+/olt-{[a-z0-9\-]+}/pon-{[0-9]+}/onu-{[0-9]+}/uni-{[0-9]+}$`)

	// Ensure tpPath is of the format  <technology>/<table_id>/<uni_port_name>
	if !tpPathFormat.Match([]byte(tpPath)) {
		return 0, errors.New("tp-path-not-confirming-to-format")
	}
	// Extract the TP table-id field.
	tpID, err := strconv.Atoi(strings.Split(tpPath, "/")[1])
	// Atoi returns uint64 and need to be type-casted to uint8 as tpID is uint8 size.
	return uint8(tpID), err
}

//IPToInt32 transforms an IP of net.Ip type to int32
func IPToInt32(ip net.IP) uint32 {
	if len(ip) == 16 {
		return binary.BigEndian.Uint32(ip[12:16])
	}
	return binary.BigEndian.Uint32(ip)
}

//AsByteSlice transforms a string of manually set bits to a byt array
func AsByteSlice(bitString string) []byte {
	var out []byte
	var str string

	for i := len(bitString); i > 0; i -= 8 {
		if i-8 < 0 {
			str = bitString[0:i]
		} else {
			str = bitString[i-8 : i]
		}
		v, err := strconv.ParseUint(str, 2, 8)
		if err != nil {
			panic(err)
		}
		out = append([]byte{byte(v)}, out...)
	}
	return out
}

// TwosComplementToSignedInt16 convert 2s complement to signed int16
func TwosComplementToSignedInt16(val uint16) int16 {
	var uint16MsbMask uint16 = 0x8000
	if val&uint16MsbMask == uint16MsbMask {
		return int16(^val+1) * -1
	}

	return int16(val)
}

// TrimStringFromMeOctet trim string out of Me octet
func TrimStringFromMeOctet(input interface{}) string {
	ifBytes, _ := me.InterfaceToOctets(input)
	return fmt.Sprintf("%s", bytes.Trim(ifBytes, "\x00"))
}

////////////////////////////////////////////////////////////////////////

//NewAdapterFsm - FSM details including event, device and channel.
func NewAdapterFsm(aName string, aDeviceID string, aCommChannel chan Message) *AdapterFsm {
	aFsm := &AdapterFsm{
		fsmName:  aName,
		deviceID: aDeviceID,
		CommChan: aCommChannel,
	}
	return aFsm
}

// LogFsmStateChange logs FSM state changes
func (oo *AdapterFsm) LogFsmStateChange(ctx context.Context, e *fsm.Event) {
	logger.Debugw(ctx, "FSM state change", log.Fields{"device-id": oo.deviceID, "FSM name": oo.fsmName,
		"event name": string(e.Event), "src state": string(e.Src), "dst state": string(e.Dst)})
}

////////////////////////////////////////////////////////////////////////

// GenerateIeeMaperServiceProfileEID returns IeeMaperServiceProfileEntityID
func GenerateIeeMaperServiceProfileEID(uniPortMacBpNo uint16, tpID uint16) (uint16, error) {
	if tpID < tpIDStart || tpID >= tpIDEnd {
		return 0, fmt.Errorf("tech profile id out of range - %d", tpID)
	}
	if uniPortMacBpNo > maxUni {
		return 0, fmt.Errorf("uni macbpno out of range - %d", uniPortMacBpNo)
	}
	return (IeeMaperServiceProfileBaseEID + uniPortMacBpNo*tpRange + tpID - tpIDStart), nil
}

// GenerateANISideMBPCDEID returns ANISideMacBridgePortConfigurationDataEntryID
func GenerateANISideMBPCDEID(uniPortMacBpNo uint16, tpID uint16) (uint16, error) {
	if tpID < tpIDStart || tpID >= tpIDEnd {
		return 0, fmt.Errorf("tech profile id out of range - %d", tpID)
	}
	if uniPortMacBpNo > maxUni {
		return 0, fmt.Errorf("uni macbpno out of range - %d", uniPortMacBpNo)
	}
	return (MacBridgePortAniBaseEID + uniPortMacBpNo*tpRange + tpID - tpIDStart), nil
}

// GenerateUNISideMBPCDEID returns UNISideMacBridgePortConfigurationDataEntityID
func GenerateUNISideMBPCDEID(uniPortMacBpNo uint16) (uint16, error) {
	if uniPortMacBpNo > maxUni {
		return 0, fmt.Errorf("uni macbpno out of range - %d", uniPortMacBpNo)
	}
	return (MacBridgePortUniBaseEID + uniPortMacBpNo), nil
}

// GenerateMcastANISideMBPCDEID returns McastANISideMacBridgePortConfigurationDataEntityID
func GenerateMcastANISideMBPCDEID(uniPortMacBpNo uint16) (uint16, error) {

	if uniPortMacBpNo > maxUni {
		return 0, fmt.Errorf("uni macbpno out of range - %d", uniPortMacBpNo)
	}
	return (MacBridgePortAniMcastBaseEID + uniPortMacBpNo), nil
}

// GenerateVoipUNISideMEID return VoipUNISideMEEntityID
func GenerateVoipUNISideMEID(uniPortMacBpNo uint16) (uint16, error) {
	if uniPortMacBpNo > maxUni {
		return 0, fmt.Errorf("uni macbpno out of range - %d", uniPortMacBpNo)
	}
	return (VoipUniBaseEID + uniPortMacBpNo), nil
}

//WaitTimeout of waitGroupWithTimeOut is blocking
//  returns true, if the wg request was executed successfully, false on timeout
func (wg *WaitGroupWithTimeOut) WaitTimeout(timeout time.Duration) bool {
	done := make(chan struct{})

	go func() {
		defer close(done)
		wg.Wait()
	}()

	select {
	case <-done:
		return true

	case <-time.After(timeout):
		return false
	}
}
