/*
 * 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 route

import (
	"context"
	"fmt"
	"github.com/opencord/voltha-lib-go/v3/pkg/log"
	"github.com/opencord/voltha-protos/v3/go/voltha"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"sync"
)

// Hop represent a route hop
type Hop struct {
	DeviceID string
	Ingress  uint32
	Egress   uint32
}

// PathID is the identification of a route between two logical ports
type PathID struct {
	Ingress uint32
	Egress  uint32
}

type OFPortLink struct {
	Ingress uint32
	Egress  uint32
}

// GetDeviceFunc returns device function
type GetDeviceFunc func(ctx context.Context, id string) (*voltha.Device, error)

// DeviceRoutes represent the set of routes between logical ports of a logical device
type DeviceRoutes struct {
	logicalDeviceID     string
	getDeviceFromModel  GetDeviceFunc
	logicalPorts        []*voltha.LogicalPort
	RootPorts           map[uint32]uint32
	rootPortsLock       sync.RWMutex
	Routes              map[PathID][]Hop
	routeBuildLock      sync.RWMutex
	devicesPonPorts     map[string][]*voltha.Port
	devicesPonPortsLock sync.RWMutex
}

// NewDeviceRoutes creates device graph instance
func NewDeviceRoutes(logicalDeviceID string, getDevice GetDeviceFunc) *DeviceRoutes {
	var dr DeviceRoutes
	dr.logicalDeviceID = logicalDeviceID
	dr.getDeviceFromModel = getDevice
	dr.RootPorts = make(map[uint32]uint32)
	dr.Routes = make(map[PathID][]Hop)
	dr.devicesPonPorts = make(map[string][]*voltha.Port)
	logger.Debug("new device routes created ...")
	return &dr
}

//IsRootPort returns true if the port is a root port on a logical device
func (dr *DeviceRoutes) IsRootPort(port uint32) bool {
	dr.rootPortsLock.RLock()
	defer dr.rootPortsLock.RUnlock()
	_, exist := dr.RootPorts[port]
	return exist
}

//ComputeRoutes calculates all the routes between the logical ports.  This will clear up any existing route
func (dr *DeviceRoutes) ComputeRoutes(ctx context.Context, lps []*voltha.LogicalPort) error {
	dr.routeBuildLock.Lock()
	defer dr.routeBuildLock.Unlock()

	logger.Debugw("computing-all-routes", log.Fields{"len-logical-ports": len(lps)})
	var err error
	defer func() {
		// On error, clear the routes - any flow request or a port add/delete will trigger the rebuild
		if err != nil {
			dr.reset()
		}
	}()

	if len(lps) < 2 {
		return status.Error(codes.FailedPrecondition, "not-enough-logical-ports")
	}

	dr.reset()
	dr.logicalPorts = append(dr.logicalPorts, lps...)

	// Setup the physical ports to logical ports map, the nni ports as well as the root ports map
	physPortToLogicalPortMap := make(map[string]uint32)
	nniPorts := make([]*voltha.LogicalPort, 0)
	for _, lp := range lps {
		physPortToLogicalPortMap[concatDeviceIDPortID(lp.DeviceId, lp.DevicePortNo)] = lp.OfpPort.PortNo
		if lp.RootPort {
			nniPorts = append(nniPorts, lp)
			dr.RootPorts[lp.OfpPort.PortNo] = lp.OfpPort.PortNo
		}
	}
	if len(nniPorts) == 0 {
		err = status.Error(codes.FailedPrecondition, "no nni port")
		return err
	}
	var rootDevice *voltha.Device
	var childDevice *voltha.Device
	var copyFromNNIPort *voltha.LogicalPort
	for idx, nniPort := range nniPorts {
		if idx == 0 {
			copyFromNNIPort = nniPort
		} else if len(dr.Routes) > 0 {
			dr.copyFromExistingNNIRoutes(nniPort, copyFromNNIPort)
			return nil
		}
		// Get root device
		rootDevice, err = dr.getDevice(ctx, nniPort.DeviceId)
		if err != nil {
			return err
		}
		if len(rootDevice.Ports) == 0 {
			err = status.Errorf(codes.FailedPrecondition, "no-port-%s", rootDevice.Id)
			return err
		}
		for _, rootDevicePort := range rootDevice.Ports {
			if rootDevicePort.Type == voltha.Port_PON_OLT {
				logger.Debugw("peers", log.Fields{"root-device-id": rootDevice.Id, "port-no": rootDevicePort.PortNo, "len-peers": len(rootDevicePort.Peers)})
				for _, rootDevicePeer := range rootDevicePort.Peers {
					childDevice, err = dr.getDevice(ctx, rootDevicePeer.DeviceId)
					if err != nil {
						return err
					}
					childPonPorts := dr.getDevicePonPorts(childDevice.Id, nniPort.DeviceId)
					if len(childPonPorts) < 1 {
						err = status.Errorf(codes.Aborted, "no-child-pon-port-%s", childDevice.Id)
						return err
					}
					// We use the first PON port on the ONU whose parent is the root device.
					childPonPort := childPonPorts[0].PortNo
					for _, childDevicePort := range childDevice.Ports {
						if childDevicePort.Type == voltha.Port_ETHERNET_UNI {
							childLogicalPort, exist := physPortToLogicalPortMap[concatDeviceIDPortID(childDevice.Id, childDevicePort.PortNo)]
							if !exist {
								// This can happen if this logical port has not been created yet for that device
								continue
							}
							dr.Routes[PathID{Ingress: nniPort.OfpPort.PortNo, Egress: childLogicalPort}] = []Hop{
								{DeviceID: rootDevice.Id, Ingress: nniPort.DevicePortNo, Egress: rootDevicePort.PortNo},
								{DeviceID: childDevice.Id, Ingress: childPonPort, Egress: childDevicePort.PortNo},
							}
							dr.Routes[PathID{Ingress: childLogicalPort, Egress: nniPort.OfpPort.PortNo}] = getReverseRoute(
								dr.Routes[PathID{Ingress: nniPort.OfpPort.PortNo, Egress: childLogicalPort}])
						}
					}
				}
			}
		}
	}
	return nil
}

// verifyPrecondition verify whether the preconditions are met to proceed with addition of the new logical port
func (dr *DeviceRoutes) addPortAndVerifyPrecondition(lp *voltha.LogicalPort) error {
	var exist, nniLogicalPortExist, uniLogicalPortExist bool
	for _, existingLogicalPort := range dr.logicalPorts {
		nniLogicalPortExist = nniLogicalPortExist || existingLogicalPort.RootPort
		uniLogicalPortExist = uniLogicalPortExist || !existingLogicalPort.RootPort
		exist = exist || existingLogicalPort.OfpPort.PortNo == lp.OfpPort.PortNo
		if nniLogicalPortExist && uniLogicalPortExist && exist {
			break
		}
	}
	if !exist {
		dr.logicalPorts = append(dr.logicalPorts, lp)
		nniLogicalPortExist = nniLogicalPortExist || lp.RootPort
		uniLogicalPortExist = uniLogicalPortExist || !lp.RootPort
	}

	// If we do not have both NNI and UNI ports then return an error
	if !(nniLogicalPortExist && uniLogicalPortExist) {
		fmt.Println("errors", nniLogicalPortExist, uniLogicalPortExist)
		return status.Error(codes.FailedPrecondition, "no-uni-and-nni-ports-combination")
	}
	return nil
}

// AddPort augments the current set of routes with new routes corresponding to the logical port "lp".  If the routes have
// not been built yet then use logical port "lps" to compute all current routes (lps includes lp)
func (dr *DeviceRoutes) AddPort(ctx context.Context, lp *voltha.LogicalPort, lps []*voltha.LogicalPort) error {
	logger.Debugw("add-port-to-routes", log.Fields{"port": lp, "len-logical-ports": len(lps)})

	dr.routeBuildLock.Lock()
	if len(dr.Routes) == 0 {
		dr.routeBuildLock.Unlock()
		return dr.ComputeRoutes(ctx, lps)
	}

	// A set of routes exists
	if err := dr.addPortAndVerifyPrecondition(lp); err != nil {
		dr.reset()
		dr.routeBuildLock.Unlock()
		return err
	}

	defer dr.routeBuildLock.Unlock()
	// Update the set of root ports, if applicable
	if lp.RootPort {
		dr.RootPorts[lp.OfpPort.PortNo] = lp.OfpPort.PortNo
	}

	var copyFromNNIPort *voltha.LogicalPort
	// Setup the physical ports to logical ports map
	nniPorts := make([]*voltha.LogicalPort, 0)
	for _, lport := range dr.logicalPorts {
		if lport.RootPort {
			nniPorts = append(nniPorts, lport)
			if copyFromNNIPort == nil && lport.OfpPort.PortNo != lp.OfpPort.PortNo {
				copyFromNNIPort = lport
			}
		}
	}

	if copyFromNNIPort == nil {
		// Trying to add the same NNI port.  Just return
		return nil
	}

	// Adding NNI Port?   If we are here we already have an NNI port with a set of routes.  Just copy the existing
	// routes using an existing NNI port
	if lp.RootPort {
		dr.copyFromExistingNNIRoutes(lp, copyFromNNIPort)
		return nil
	}

	// Adding a UNI port
	for _, nniPort := range nniPorts {
		childPonPorts := dr.getDevicePonPorts(lp.DeviceId, nniPort.DeviceId)
		if len(childPonPorts) == 0 || len(childPonPorts[0].Peers) == 0 {
			// Ports may not have been cached yet - get the device info which sets the PON port cache
			if _, err := dr.getDevice(ctx, lp.DeviceId); err != nil {
				dr.reset()
				return err
			}
			childPonPorts = dr.getDevicePonPorts(lp.DeviceId, nniPort.DeviceId)
			if len(childPonPorts) == 0 || len(childPonPorts[0].Peers) == 0 {
				dr.reset()
				return status.Errorf(codes.FailedPrecondition, "no-pon-ports-%s", lp.DeviceId)
			}
		}
		// We use the first PON port on the child device
		childPonPort := childPonPorts[0]
		dr.Routes[PathID{Ingress: nniPort.OfpPort.PortNo, Egress: lp.OfpPort.PortNo}] = []Hop{
			{DeviceID: nniPort.DeviceId, Ingress: nniPort.DevicePortNo, Egress: childPonPort.Peers[0].PortNo},
			{DeviceID: lp.DeviceId, Ingress: childPonPort.PortNo, Egress: lp.DevicePortNo},
		}
		dr.Routes[PathID{Ingress: lp.OfpPort.PortNo, Egress: nniPort.OfpPort.PortNo}] = getReverseRoute(
			dr.Routes[PathID{Ingress: nniPort.OfpPort.PortNo, Egress: lp.OfpPort.PortNo}])
	}
	return nil
}

// Print prints routes
func (dr *DeviceRoutes) Print() error {
	logger.Debugw("Print", log.Fields{"logical-device-id": dr.logicalDeviceID, "logical-ports": dr.logicalPorts})
	if logger.V(log.DebugLevel) {
		output := ""
		routeNumber := 1
		for k, v := range dr.Routes {
			key := fmt.Sprintf("LP:%d->LP:%d", k.Ingress, k.Egress)
			val := ""
			for _, i := range v {
				val += fmt.Sprintf("{%d->%s->%d},", i.Ingress, i.DeviceID, i.Egress)
			}
			val = val[:len(val)-1]
			output += fmt.Sprintf("%d:{%s=>%s}   ", routeNumber, key, fmt.Sprintf("[%s]", val))
			routeNumber++
		}
		if len(dr.Routes) == 0 {
			logger.Debugw("no-routes-found", log.Fields{"logical-device-id": dr.logicalDeviceID})
		} else {
			logger.Debugw("graph_routes", log.Fields{"lDeviceId": dr.logicalDeviceID, "Routes": output})
		}
	}
	return nil
}

// IsUpToDate returns true if device is up to date
func (dr *DeviceRoutes) IsUpToDate(ld *voltha.LogicalDevice) bool {
	dr.routeBuildLock.Lock()
	defer dr.routeBuildLock.Unlock()
	numNNI, numUNI := 0, 0
	if ld != nil {
		if len(dr.logicalPorts) != len(ld.Ports) {
			return false
		}
		numNNI = len(dr.RootPorts)
		numUNI = len(ld.Ports) - numNNI
	}
	return len(dr.Routes) == numNNI*numUNI*2
}

// getDevicePonPorts returns all the PON ports of a device whose peer device ID is peerDeviceID
func (dr *DeviceRoutes) getDevicePonPorts(deviceID string, peerDeviceID string) []*voltha.Port {
	dr.devicesPonPortsLock.RLock()
	defer dr.devicesPonPortsLock.RUnlock()
	ponPorts := make([]*voltha.Port, 0)
	ports, exist := dr.devicesPonPorts[deviceID]
	if !exist {
		return ponPorts
	}
	//fmt.Println("getDevicePonPorts", deviceID, peerDeviceID, ports)
	for _, port := range ports {
		for _, peer := range port.Peers {
			if peer.DeviceId == peerDeviceID {
				ponPorts = append(ponPorts, port)
			}
		}
	}
	return ponPorts
}

//getDevice returns the from the model and updates the PON ports map of that device.
func (dr *DeviceRoutes) getDevice(ctx context.Context, deviceID string) (*voltha.Device, error) {
	device, err := dr.getDeviceFromModel(ctx, deviceID)
	if err != nil {
		logger.Errorw("device-not-found", log.Fields{"deviceId": deviceID, "error": err})
		return nil, err
	}
	dr.devicesPonPortsLock.Lock()
	defer dr.devicesPonPortsLock.Unlock()
	for _, port := range device.Ports {
		if port.Type == voltha.Port_PON_ONU || port.Type == voltha.Port_PON_OLT {
			dr.devicesPonPorts[device.Id] = append(dr.devicesPonPorts[device.Id], port)
		}
	}
	return device, nil
}

//copyFromExistingNNIRoutes copies routes from an existing set of NNI routes
func (dr *DeviceRoutes) copyFromExistingNNIRoutes(newNNIPort *voltha.LogicalPort, copyFromNNIPort *voltha.LogicalPort) {
	updatedRoutes := make(map[PathID][]Hop)
	for key, val := range dr.Routes {
		if key.Ingress == copyFromNNIPort.OfpPort.PortNo {
			updatedRoutes[PathID{Ingress: newNNIPort.OfpPort.PortNo, Egress: key.Egress}] = []Hop{
				{DeviceID: newNNIPort.DeviceId, Ingress: newNNIPort.DevicePortNo, Egress: val[0].Egress},
				val[1],
			}
		}
		if key.Egress == copyFromNNIPort.OfpPort.PortNo {
			updatedRoutes[PathID{Ingress: key.Ingress, Egress: newNNIPort.OfpPort.PortNo}] = []Hop{
				val[0],
				{DeviceID: newNNIPort.DeviceId, Ingress: val[1].Ingress, Egress: newNNIPort.DevicePortNo},
			}
		}
		updatedRoutes[key] = val
	}
	dr.Routes = updatedRoutes
}

// reset cleans up the device graph
func (dr *DeviceRoutes) reset() {
	dr.rootPortsLock.Lock()
	dr.RootPorts = make(map[uint32]uint32)
	dr.rootPortsLock.Unlock()
	// Do not numGetDeviceCalledLock Routes, logicalPorts  as the callee function already holds its numGetDeviceCalledLock.
	dr.Routes = make(map[PathID][]Hop)
	dr.logicalPorts = make([]*voltha.LogicalPort, 0)
	dr.devicesPonPortsLock.Lock()
	dr.devicesPonPorts = make(map[string][]*voltha.Port)
	dr.devicesPonPortsLock.Unlock()
}

//concatDeviceIdPortId formats a portid using the device id and the port number
func concatDeviceIDPortID(deviceID string, portNo uint32) string {
	return fmt.Sprintf("%s:%d", deviceID, portNo)
}

//getReverseRoute returns the reverse of the route
func getReverseRoute(route []Hop) []Hop {
	reverse := make([]Hop, len(route))
	for i, j := 0, len(route)-1; j >= 0; i, j = i+1, j-1 {
		reverse[i].DeviceID, reverse[i].Ingress, reverse[i].Egress = route[j].DeviceID, route[j].Egress, route[j].Ingress
	}
	return reverse
}
