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

import (
	"context"
	"encoding/hex"
	"fmt"
	"github.com/opencord/bbsim/internal/bbsim/types"
	"io"
	"reflect"
	"time"

	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/opencord/bbsim/internal/bbsim/devices"
	"github.com/opencord/bbsim/internal/bbsim/packetHandlers"
	"github.com/opencord/bbsim/internal/common"
	"github.com/opencord/voltha-protos/v4/go/openolt"
	log "github.com/sirupsen/logrus"
	"google.golang.org/grpc"
)

type OltMock struct {
	LastUsedOnuId map[uint32]uint32
	Olt           *devices.OltDevice
	BBSimIp       string
	BBSimPort     string
	BBSimApiPort  string

	conn *grpc.ClientConn

	TargetOnus    int
	CompletedOnus int // Number of ONUs that have received a DHCPAck
}

// trigger an enable call and start the same listeners on the gRPC stream that VOLTHA would create
// this method is blocking
func (o *OltMock) Start() {
	log.Info("Starting Mock OLT")

	for _, pon := range o.Olt.Pons {
		for _, onu := range pon.Onus {
			if err := onu.InternalState.Event("initialize"); err != nil {
				log.Fatalf("Error initializing ONU: %v", err)
			}
			log.Debugf("Created ONU: %s", onu.Sn())
		}
	}

	client, conn := Connect(o.BBSimIp, o.BBSimPort)
	o.conn = conn
	defer conn.Close()

	deviceInfo, err := o.getDeviceInfo(client)

	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Fatal("Can't read device info")
	}

	log.WithFields(log.Fields{
		"Vendor":             deviceInfo.Vendor,
		"Model":              deviceInfo.Model,
		"DeviceSerialNumber": deviceInfo.DeviceSerialNumber,
		"PonPorts":           deviceInfo.PonPorts,
	}).Info("Retrieved device info")

	o.readIndications(client)

}

func (o *OltMock) getDeviceInfo(client openolt.OpenoltClient) (*openolt.DeviceInfo, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	return client.GetDeviceInfo(ctx, new(openolt.Empty))
}

func (o *OltMock) readIndications(client openolt.OpenoltClient) {
	defer func() {
		log.Info("OLT readIndications done")
	}()

	// Tell the OLT to start sending indications
	indications, err := client.EnableIndication(context.Background(), new(openolt.Empty))
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Error("Failed to enable indication stream")
		return
	}

	// listen for indications
	for {
		indication, err := indications.Recv()
		if err == io.EOF {
			break
		}
		if err != nil {

			// the connection is closed once we have sent the DHCP_ACK packet to all of the ONUs
			// it means BBR completed, it's not an error

			log.WithFields(log.Fields{
				"error": err,
			}).Debug("Failed to read from indications")
			break
		}

		o.handleIndication(client, indication)
	}
}

func (o *OltMock) handleIndication(client openolt.OpenoltClient, indication *openolt.Indication) {
	switch indication.Data.(type) {
	case *openolt.Indication_OltInd:
		log.Info("Received Indication_OltInd")
	case *openolt.Indication_IntfInd:
		log.Info("Received Indication_IntfInd")
	case *openolt.Indication_IntfOperInd:
		log.Info("Received Indication_IntfOperInd")
	case *openolt.Indication_OnuDiscInd:
		onuDiscInd := indication.GetOnuDiscInd()
		o.handleOnuDiscIndication(client, onuDiscInd)
	case *openolt.Indication_OnuInd:
		onuInd := indication.GetOnuInd()
		o.handleOnuIndication(client, onuInd)
	case *openolt.Indication_OmciInd:
		omciIndication := indication.GetOmciInd()
		o.handleOmciIndication(client, omciIndication)
	case *openolt.Indication_PktInd:
		pktIndication := indication.GetPktInd()
		o.handlePktIndication(client, pktIndication)
	case *openolt.Indication_PortStats:
	case *openolt.Indication_FlowStats:
	case *openolt.Indication_AlarmInd:
	default:
		log.WithFields(log.Fields{
			"data": indication.Data,
			"type": reflect.TypeOf(indication.Data),
		}).Warn("Indication unsupported")
	}
}

func (o *OltMock) handleOnuDiscIndication(client openolt.OpenoltClient, onuDiscInd *openolt.OnuDiscIndication) {
	log.WithFields(log.Fields{
		"IntfId":       onuDiscInd.IntfId,
		"SerialNumber": common.OnuSnToString(onuDiscInd.SerialNumber),
	}).Info("Received Onu discovery indication")

	onu, err := o.Olt.FindOnuBySn(common.OnuSnToString(onuDiscInd.SerialNumber))

	if err != nil {
		log.WithFields(log.Fields{
			"IntfId":       onuDiscInd.IntfId,
			"SerialNumber": common.OnuSnToString(onuDiscInd.SerialNumber),
			"Err":          err,
		}).Fatal("Cannot find ONU")
	}

	// creating and storing ONU IDs
	id := o.LastUsedOnuId[onuDiscInd.IntfId] + 1
	o.LastUsedOnuId[onuDiscInd.IntfId] = o.LastUsedOnuId[onuDiscInd.IntfId] + 1
	onu.SetID(id)

	var pir uint32 = 1000000
	Onu := openolt.Onu{
		IntfId:       onu.PonPortID,
		OnuId:        id,
		SerialNumber: onu.SerialNumber,
		Pir:          pir,
	}

	if _, err := client.ActivateOnu(context.Background(), &Onu); err != nil {
		log.WithFields(log.Fields{
			"IntfId":       onuDiscInd.IntfId,
			"SerialNumber": common.OnuSnToString(onuDiscInd.SerialNumber),
		}).Error("Failed to activate ONU")
	}
}

func (o *OltMock) handleOnuIndication(client openolt.OpenoltClient, onuInd *openolt.OnuIndication) {
	log.WithFields(log.Fields{
		"IntfId":       onuInd.IntfId,
		"SerialNumber": common.OnuSnToString(onuInd.SerialNumber),
	}).Info("Received Onu indication")

	onu, err := o.Olt.FindOnuBySn(common.OnuSnToString(onuInd.SerialNumber))

	if err != nil {
		log.WithFields(log.Fields{
			"IntfId":       onuInd.IntfId,
			"SerialNumber": common.OnuSnToString(onuInd.SerialNumber),
		}).Fatal("Cannot find ONU")
	}

	ctx, cancel := context.WithCancel(context.TODO())
	go onu.ProcessOnuMessages(ctx, nil, client)

	go func() {

		defer func() {
			log.WithFields(log.Fields{
				"onuSn":         common.OnuSnToString(onuInd.SerialNumber),
				"CompletedOnus": o.CompletedOnus,
				"TargetOnus":    o.TargetOnus,
			}).Debugf("Onu done")

			// close the ONU channel
			cancel()
		}()

		for message := range onu.DoneChannel {
			if message {
				o.CompletedOnus++
				if o.CompletedOnus == o.TargetOnus {
					// NOTE once all the ONUs are completed, exit
					// closing the connection is not the most elegant way,
					// but I haven't found any other way to stop
					// the indications.Recv() infinite loop
					log.Info("Simulation Done")
					ValidateAndClose(o)
				}

				break
			}
		}

	}()

	// TODO change the state instead of calling an ONU method from here
	onu.StartOmci(client)
}

func (o *OltMock) handleOmciIndication(client openolt.OpenoltClient, omciInd *openolt.OmciIndication) {

	pon, err := o.Olt.GetPonById(omciInd.IntfId)
	if err != nil {
		log.WithFields(log.Fields{
			"OnuId":  omciInd.OnuId,
			"IntfId": omciInd.IntfId,
			"err":    err,
		}).Fatal("Can't find PonPort")
	}
	onu, _ := pon.GetOnuById(omciInd.OnuId)
	if err != nil {
		log.WithFields(log.Fields{
			"OnuId":  omciInd.OnuId,
			"IntfId": omciInd.IntfId,
			"err":    err,
		}).Fatal("Can't find Onu")
	}

	log.WithFields(log.Fields{
		"IntfId": onu.PonPortID,
		"OnuId":  onu.ID,
		"OnuSn":  onu.Sn(),
		"Pkt":    omciInd.Pkt,
	}).Trace("Received Onu omci indication")

	msg := types.Message{
		Type: types.OmciIndication,
		Data: types.OmciIndicationMessage{
			OnuSN:   onu.SerialNumber,
			OnuID:   onu.ID,
			OmciInd: omciInd,
		},
	}
	onu.Channel <- msg
}

func (o *OltMock) handlePktIndication(client openolt.OpenoltClient, pktIndication *openolt.PacketIndication) {

	pkt := gopacket.NewPacket(pktIndication.Pkt, layers.LayerTypeEthernet, gopacket.Default)

	pktType, err := packetHandlers.GetPktType(pkt)

	if err != nil {
		log.Warnf("Ignoring packet as it's neither EAPOL or DHCP")
		return
	}

	log.WithFields(log.Fields{
		"IntfType":  pktIndication.IntfType,
		"IntfId":    pktIndication.IntfId,
		"GemportId": pktIndication.GemportId,
		"FlowId":    pktIndication.FlowId,
		"PortNo":    pktIndication.PortNo,
		"Cookie":    pktIndication.Cookie,
		"pktType":   pktType,
	}).Trace("Received PktIndication")

	if pktIndication.IntfType == "nni" {
		// This is an packet that is arriving from the NNI and needs to be sent to an ONU

		onuMac, err := packetHandlers.GetDstMacAddressFromPacket(pkt)

		if err != nil {
			log.WithFields(log.Fields{
				"IntfType": "nni",
				"Pkt":      hex.EncodeToString(pkt.Data()),
			}).Fatal("Can't find Dst MacAddress in packet")
		}

		s, err := o.Olt.FindServiceByMacAddress(onuMac)
		if err != nil {
			log.WithFields(log.Fields{
				"IntfType":   "nni",
				"Pkt":        hex.EncodeToString(pkt.Data()),
				"MacAddress": onuMac.String(),
			}).Fatal("Can't find ONU with MacAddress")
		}

		service := s.(*devices.Service)
		onu := service.Onu

		msg := types.Message{
			Type: types.OnuPacketIn,
			Data: types.OnuPacketMessage{
				IntfId:    pktIndication.IntfId,
				OnuId:     onu.ID,
				Packet:    pkt,
				Type:      pktType,
				GemPortId: pktIndication.GemportId,
			},
		}
		// NOTE we send it on the ONU channel so that is handled as all the others packets in a separate thread
		onu.Channel <- msg
	} else {
		// TODO a very similar construct is used in many places,
		// abstract this in an OLT method
		pon, err := o.Olt.GetPonById(pktIndication.IntfId)
		if err != nil {
			log.WithFields(log.Fields{
				"OnuId":  pktIndication.PortNo,
				"IntfId": pktIndication.IntfId,
				"err":    err,
			}).Fatal("Can't find PonPort")
		}
		onu, err := pon.GetOnuById(pktIndication.PortNo)
		if err != nil {
			log.WithFields(log.Fields{
				"OnuId":  pktIndication.PortNo,
				"IntfId": pktIndication.IntfId,
				"err":    err,
			}).Fatal("Can't find Onu")
		}
		// NOTE when we push the EAPOL flow we set the PortNo = OnuId for convenience sake
		// BBsim responds setting the port number that was sent with the flow
		msg := types.Message{
			Type: types.OnuPacketIn,
			Data: types.OnuPacketMessage{
				IntfId: pktIndication.IntfId,
				OnuId:  pktIndication.PortNo,
				Packet: pkt,
				Type:   pktType,
			},
		}
		onu.Channel <- msg
	}
}

// TODO Move in a different file
func Connect(ip string, port string) (openolt.OpenoltClient, *grpc.ClientConn) {
	server := fmt.Sprintf("%s:%s", ip, port)
	conn, err := grpc.Dial(server, grpc.WithInsecure())

	if err != nil {
		log.Fatalf("did not connect: %v", err)
		return nil, conn
	}
	return openolt.NewOpenoltClient(conn), conn
}
