/*
   Copyright 2020 the original author or authors.

   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 ofagent

import (
	"context"
	"encoding/json"
	ofp "github.com/donNewtonAlpha/goloxi/of13"
	"github.com/golang/protobuf/ptypes/empty"
	"github.com/opencord/ofagent-go/internal/pkg/openflow"
	"github.com/opencord/voltha-lib-go/v2/pkg/log"
	"google.golang.org/grpc"
	"net"
)

func (ofa *OFAgent) receiveChangeEvents(ctx context.Context) {
	logger.Debug("receive-change-events-started")
	opt := grpc.EmptyCallOption{}
	streamCtx, streamDone := context.WithCancel(context.Background())
	stream, err := ofa.volthaClient.ReceiveChangeEvents(streamCtx, &empty.Empty{}, opt)
	if err != nil {
		logger.Errorw("Unable to establish Receive Change Event Stream",
			log.Fields{"error": err})
		ofa.events <- ofaEventVolthaDisconnected
	}
	defer streamDone()

	for {
		select {
		case <-ctx.Done():
			return
		default:
			if ce, err := stream.Recv(); err != nil {
				logger.Errorw("error receiving change event",
					log.Fields{"error": err})
				ofa.events <- ofaEventVolthaDisconnected
			} else {
				ofa.changeEventChannel <- ce
			}
		}
	}
}

func (ofa *OFAgent) handleChangeEvents(ctx context.Context) {
	logger.Debugln("handle-change-event-started")
	for {
		select {
		case <-ctx.Done():
			return
		case changeEvent := <-ofa.changeEventChannel:
			deviceID := changeEvent.GetId()
			portStatus := changeEvent.GetPortStatus()
			logger.Debugw("received-change-event",
				log.Fields{
					"device-id":   deviceID,
					"port-status": portStatus})

			if portStatus == nil {
				if logger.V(log.WarnLevel) {
					js, _ := json.Marshal(changeEvent.GetEvent())
					logger.Warnw("Received change event that was not port status",
						log.Fields{"ChangeEvent": js})
				}
				break
			}
			ofPortStatus := ofp.NewPortStatus()
			ofPortStatus.SetXid(openflow.GetXid())
			ofPortStatus.SetVersion(4)

			ofReason := ofp.PortReason(portStatus.GetReason())
			ofPortStatus.SetReason(ofReason)
			ofDesc := ofp.NewPortDesc()

			desc := portStatus.GetDesc()
			ofDesc.SetAdvertised(ofp.PortFeatures(desc.GetAdvertised()))
			ofDesc.SetConfig(ofp.PortConfig(0))
			ofDesc.SetCurr(ofp.PortFeatures(desc.GetAdvertised()))
			ofDesc.SetCurrSpeed(desc.GetCurrSpeed())
			intArray := desc.GetHwAddr()
			var octets []byte
			for _, val := range intArray {
				octets = append(octets, byte(val))
			}
			addr := net.HardwareAddr(octets)
			ofDesc.SetHwAddr(addr)
			ofDesc.SetMaxSpeed(desc.GetMaxSpeed())
			ofDesc.SetName(openflow.PadString(desc.GetName(), 16))
			ofDesc.SetPeer(ofp.PortFeatures(desc.GetPeer()))
			ofDesc.SetPortNo(ofp.Port(desc.GetPortNo()))
			ofDesc.SetState(ofp.PortState(desc.GetState()))
			ofDesc.SetSupported(ofp.PortFeatures(desc.GetSupported()))
			ofPortStatus.SetDesc(*ofDesc)
			ofa.getOFClient(deviceID).SendMessage(ofPortStatus)
		}
	}
}
