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

import (
	"net"
	"strconv"

	"github.com/opencord/bbsim/api/legacy"
	api "github.com/opencord/bbsim/api/legacy"
	"github.com/opencord/bbsim/internal/bbsim/devices"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

// Constants for reboot delays
const (
	OltRebootDelay     = 40
	OnuSoftRebootDelay = 10
	OnuHardRebootDelay = 30
)

// handleONUStatusRequest process ONU status request
func (s BBSimLegacyServer) handleONUStatusRequest(in *api.ONUInfo) (*api.ONUs, error) {
	logger.Trace("handleONUStatusRequest() invoked")
	onuInfo := &api.ONUs{}
	olt := devices.GetOLT()

	if in.OnuSerial != "" { // Get status of a single ONU by SerialNumber
		onu, err := olt.FindOnuBySn(in.OnuSerial)
		if err != nil {
			logger.Errorf("ONU error: %+v", err)
			return onuInfo, status.Errorf(codes.NotFound, "Unable to retrieve ONU %s", in.OnuSerial)
		}
		onuInfo.Onus = append(onuInfo.Onus, copyONUInfo(onu))
	} else {
		if in.OnuId != 0 { // Get status of a single ONU by ONU-ID
			onu, err := olt.FindOnuById(in.PonPortId, in.OnuId)
			if err != nil {
				logger.Errorf("ONU error: %+v", err)
				return onuInfo, status.Errorf(codes.NotFound, "Unable to retrieve ONU with ID %d", in.OnuId)
			}

			onuInfo.Onus = append(onuInfo.Onus, copyONUInfo(onu))
		} else { // Get status of all ONUs
			for _, p := range olt.Pons {
				for _, o := range p.Onus {
					onuInfo.Onus = append(onuInfo.Onus, copyONUInfo(o))
				}
			}
		}
	}

	return onuInfo, nil
}

func copyONUInfo(onu *devices.Onu) *api.ONUInfo {
	onuData := &api.ONUInfo{
		OnuId:     onu.ID,
		PonPortId: onu.PonPortID,
		OnuSerial: onu.Sn(),
		OnuState:  onu.InternalState.Current(),
		OperState: onu.OperState.Current(),
	}

	return onuData
}

func (s BBSimLegacyServer) fetchPortDetail(intfID uint32, portType string) (*api.PortInfo, error) {
	logger.Tracef("fetchPortDetail() invoked %s-%d", portType, intfID)
	olt := devices.GetOLT()

	switch portType {
	case "pon":
		for _, pon := range olt.Pons {
			if pon.ID == intfID {
				ponPortInfo := &api.PortInfo{
					PortType:          "pon",
					PortId:            uint32(pon.ID),
					PonPortMaxOnus:    uint32(olt.NumOnuPerPon),
					PonPortActiveOnus: uint32(olt.NumPon),
					PortState:         pon.OperState.Current(),
				}
				return ponPortInfo, nil
			}
		}
	case "nni":
		for _, nni := range olt.Nnis {
			if nni.ID == intfID {
				nniPortInfo := &legacy.PortInfo{
					PortType:  "nni",
					PortId:    uint32(nni.ID),
					PortState: nni.OperState.Current(),
				}
				return nniPortInfo, nil
			}
		}
	}

	portInfo := &api.PortInfo{}
	return portInfo, status.Errorf(codes.NotFound, "Invalid port %s-%d", portType, intfID)
}

// ConvB2S converts byte array to string
func ConvB2S(b []byte) string {
	s := ""
	for _, i := range b {
		s = s + strconv.FormatInt(int64(i/16), 16) + strconv.FormatInt(int64(i%16), 16)
	}
	return s
}

func getOltIP() net.IP {
	// TODO make this better
	conn, err := net.Dial("udp", "8.8.8.8:80")
	if err != nil {
		logger.Error(err.Error())
		return net.IP{}
	}
	defer func() {
		err := conn.Close()
		if err != nil {
			logger.Error(err.Error())
		}
	}()

	localAddr := conn.LocalAddr().(*net.UDPAddr)

	return localAddr.IP
}
