/*
* Copyright 2022-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 vpagent

import (
	"context"
	"io"

	"voltha-go-controller/log"

	"google.golang.org/grpc"
	"google.golang.org/protobuf/types/known/emptypb"
)

func (vpa *VPAgent) receivePacketsIn(ctx context.Context) {
	logger.Debug(ctx, "receive-packets-in-started")
	// If we exit, assume disconnected
	defer func() {
		vpa.events <- vpaEventVolthaDisconnected
		logger.Debug(ctx, "receive-packets-in-finished")
	}()
	if vpa.volthaClient == nil {
		logger.Fatal(ctx, "no-voltha-connection")
		return
	}
	opt := grpc.EmptyCallOption{}
	streamCtx, streamDone := context.WithCancel(context.Background())
	defer streamDone()
	stream, err := vpa.volthaClient.Get().ReceivePacketsIn(streamCtx, &emptypb.Empty{}, opt)
	if err != nil {
		logger.Errorw(ctx, "Unable to establish Receive PacketIn Stream",
			log.Fields{"error": err})
		return
	}

top:

	for {
		select {
		case <-ctx.Done():
			logger.Errorw(ctx, "Context Done", log.Fields{"Context": ctx})
			break top
		default:
			pkt, err := stream.Recv()
			if err == io.EOF {
				stream, err = vpa.volthaClient.Get().ReceivePacketsIn(streamCtx, &emptypb.Empty{}, opt)
				if err != nil {
					logger.Errorw(ctx, "Unable to establish Receive PacketIn Stream",
						log.Fields{"error": err})
					return
				}
				continue
			}

			if isConnCanceled(err) {
				logger.Errorw(ctx, "error receiving packet",
					log.Fields{"error": err})
				break top
			} else if err != nil {
				logger.Warnw(ctx, "Ignoring unhandled error", log.Fields{"err": err})
				continue
			}
			vpa.packetInChannel <- pkt
		}
	}
}

func (vpa *VPAgent) handlePacketsIn(ctx context.Context) {
	logger.Debug(ctx, "handle-packets-in-started")
top:
	for {
		select {
		case <-ctx.Done():
			logger.Errorw(ctx, "Context Done", log.Fields{"Context": ctx})
			break top
		case packet := <-vpa.packetInChannel:
			if vpc := vpa.getVPClient(packet.Id); vpc != nil {
				vpc.PacketIn(ctx, packet)
			}
		}
	}
	logger.Debug(ctx, "handle-packets-in-finished")
}
