/*
 * Copyright 2017-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 core

import (
	"context"
	"crypto/tls"
	"github.com/golang/protobuf/ptypes/empty"
	"github.com/google/gopacket"
	"github.com/opencord/voltha/ponsim/v2/common"
	"github.com/opencord/voltha/protos/go/ponsim"
	"github.com/sirupsen/logrus"
	"google.golang.org/grpc"
	"google.golang.org/grpc/connectivity"
	"google.golang.org/grpc/credentials"
	"strconv"
	"strings"
	"time"
)

// TODO: Pass-in the certificate information as a structure parameter

/*
PonSimOltDevice is the structure responsible for the handling of an OLT device
*/
type PonSimOltDevice struct {
	PonSimDevice  `json:pon_device`
	VCoreEndpoint string                  `json:vcore_ep`
	MaxOnuCount   int                     `json:max_onu`
	Onus          map[int32]*OnuRegistree `json:onu_registrees`
	outgoing      chan []byte

	counterLoop *common.IntervalHandler
	alarmLoop   *common.IntervalHandler
}

/*

 */
type OnuRegistree struct {
	Device *PonSimOnuDevice                      `json:onu_device`
	Conn   *grpc.ClientConn                      `json:grpc_conn`
	Client ponsim.PonSimCommonClient             `json:client`
	Stream ponsim.PonSimCommon_ProcessDataClient `json:stream`
}

const (
	BASE_PORT_NUMBER = 128
)

/*
NewPonSimOltDevice instantiates a new OLT device structure
*/
func NewPonSimOltDevice(device PonSimDevice) *PonSimOltDevice {
	olt := &PonSimOltDevice{PonSimDevice: device}
	return olt
}

/*
forwardToONU defines a EGRESS function to forward a packet to a specific ONU
*/
func (o *PonSimOltDevice) forwardToONU(onuPort int32) func(int, gopacket.Packet) {
	return func(port int, frame gopacket.Packet) {
		ipAddress := common.GetInterfaceIP(o.ExternalIf)
		incoming := &ponsim.IncomingData{
			Id:      "EGRESS.OLT." + ipAddress,
			Address: ipAddress,
			Port:    int32(port),
			Payload: frame.Data(),
		}
		common.Logger().WithFields(logrus.Fields{
			"device": o,
			"port":   port,
			"frame":  frame,
		}).Debug("Forwarding to ONU")

		// Forward packet to ONU
		if err := o.GetOnu(onuPort).Stream.Send(incoming); err != nil {
			common.Logger().WithFields(logrus.Fields{
				"device":    o,
				"frameDump": frame.Dump(),
				"incoming":  incoming,
				"error":     err.Error(),
			}).Error("A problem occurred while forwarding to ONU")
		}

	}
}

/*
forwardToLAN defines an INGRESS function to forward a packet to VOLTHA
*/
func (o *PonSimOltDevice) forwardToLAN() func(int, gopacket.Packet) {
	return func(port int, frame gopacket.Packet) {
		common.Logger().WithFields(logrus.Fields{
			"frame": frame.Dump(),
		}).Info("Sending packet")

		select {
		case o.outgoing <- frame.Data():
			common.Logger().WithFields(logrus.Fields{
				"frame": frame.Dump(),
			}).Info("Sent packet")
		default:
			common.Logger().WithFields(logrus.Fields{
				"frame": frame.Dump(),
			}).Warn("Unable to send packet")
		}
	}
}

/*
Start performs setup operations for an OLT device
*/
func (o *PonSimOltDevice) Start(ctx context.Context) {
	common.Logger().Info("Starting OLT device...")
	o.PonSimDevice.Start(ctx)

	// Open network interfaces for listening
	o.connectNetworkInterfaces()

	o.outgoing = make(chan []byte, 1)

	// Add INGRESS operation
	o.AddLink(2, 0, o.forwardToLAN())

	// Start PM counter logging
	o.counterLoop = common.NewIntervalHandler(90, o.Counter.LogCounts)
	o.counterLoop.Start()

	// Start alarm simulation
	if o.AlarmsOn {
		common.Logger().WithFields(logrus.Fields{
			"device": o,
		}).Debug("Starting alarm simulation")

		alarms := NewPonSimAlarm(o.InternalIf, o.VCoreEndpoint, o.forwardToLAN())
		o.alarmLoop = common.NewIntervalHandler(o.AlarmsFreq, alarms.GenerateAlarm)
		o.alarmLoop.Start()
	}
}

/*
Stop performs cleanup operations for an OLT device
*/
func (o *PonSimOltDevice) Stop(ctx context.Context) {
	common.Logger().Info("Stopping OLT device...")

	// Stop PM counters loop
	o.counterLoop.Stop()
	o.counterLoop = nil

	// Stop alarm simulation
	if o.AlarmsOn {
		o.alarmLoop.Stop()
	}
	o.alarmLoop = nil

	o.ingressHandler.Close()
	o.egressHandler.Close()

	o.PonSimDevice.Stop(ctx)
}

/*
ConnectToRemoteOnu establishes communication to a remote ONU device
*/
func (o *PonSimOltDevice) ConnectToRemoteOnu(onu *OnuRegistree) error {
	var err error

	host := strings.Join([]string{
		onu.Device.Address,
		strconv.Itoa(int(onu.Device.Port)),
	}, ":")

	common.Logger().WithFields(logrus.Fields{
		"device": o,
		"host":   host,
	}).Debug("Formatting host address")

	// TODO: make it secure
	ta := credentials.NewTLS(&tls.Config{
		//Certificates:       []tls.Certificate{peerCert},
		//RootCAs:            caCertPool,
		InsecureSkipVerify: true,
	})

	// GRPC communication needs to be secured
	if onu.Conn, err = grpc.DialContext(
		context.Background(),
		host,
		grpc.WithTransportCredentials(ta),
	); err != nil {
		common.Logger().WithFields(logrus.Fields{
			"device": o,
			"error":  err.Error(),
		}).Error("Problem with client connection")
	}

	return err
}

/*
Listen waits for incoming EGRESS data on the internal interface
*/
func (o *PonSimOltDevice) Listen(ctx context.Context, port int32) {
	var reply *empty.Empty
	var err error

	// Establish a GRPC connection with the ONU
	onu := o.GetOnu(port)

	common.Logger().WithFields(logrus.Fields{
		"onu": onu,
	}).Debug("Connecting to remote ONU")

	if onu.Client = ponsim.NewPonSimCommonClient(onu.Conn); onu.Client == nil {
		common.Logger().WithFields(logrus.Fields{
			"device": o,
		}).Error("Problem establishing client connection to ONU")
		o.RemoveOnu(ctx, port)
		return
	}

	// Prepare stream to ONU to forward incoming data as needed
	if onu.Stream, err = onu.Client.ProcessData(ctx); err != nil {
		common.Logger().WithFields(logrus.Fields{
			"device": o,
		}).Error("Problem establishing stream to ONU")
		o.RemoveOnu(ctx, port)
		return
	}

	defer o.egressHandler.Close()
	packetSource := gopacket.NewPacketSource(o.egressHandler, o.egressHandler.LinkType())
	common.Logger().WithFields(logrus.Fields{
		"device":    o,
		"interface": o.InternalIf,
	}).Debug("Listening to incoming EGRESS data")

	// Wait for incoming EGRESS data
	for packet := range packetSource.Packets() {
		if dot1q := common.GetDot1QLayer(packet); dot1q != nil {
			common.Logger().WithFields(logrus.Fields{
				"device": o,
				"packet": packet,
			}).Debug("Received EGRESS packet")

			o.Forward(ctx, 2, packet)
		}
	}

	common.Logger().WithFields(logrus.Fields{
		"device": o,
	}).Debug("No more packets to process")

	if reply, err = onu.Stream.CloseAndRecv(); err != nil {
		common.Logger().WithFields(logrus.Fields{
			"device": o,
			"error":  err.Error(),
		}).Error("A problem occurred while closing client stream")
	} else {
		common.Logger().WithFields(logrus.Fields{
			"device": o,
			"reply":  reply,
		}).Warn("Client stream closed")
	}
}

/*
GetOnus returns the list of registered ONU devices
*/
func (o *PonSimOltDevice) GetOnus() map[int32]*OnuRegistree {
	if o.Onus == nil {
		o.Onus = make(map[int32]*OnuRegistree)
	}

	return o.Onus
}

/*
GetOnu return a specific registered ONU
*/
func (o *PonSimOltDevice) GetOnu(index int32) *OnuRegistree {
	var onu *OnuRegistree
	var ok bool

	if onu, ok = (o.GetOnus())[index]; ok {
		return onu
	}

	return nil
}

func (o *PonSimOltDevice) GetOutgoing() chan []byte {
	return o.outgoing
}

/*
nextAvailablePort returns a port that is not already used by a registered ONU
*/
func (o *PonSimOltDevice) nextAvailablePort() int32 {
	var port int32 = BASE_PORT_NUMBER

	if len(o.GetOnus()) < o.MaxOnuCount {
		for {
			if o.GetOnu(port) != nil {
				// port is already used
				port += 1
			} else {
				// port is available... use it
				return port
			}
		}
	} else {
		// OLT has reached its max number of ONUs
		return -1
	}
}

/*
AddOnu registers an ONU device and sets up all required monitoring and connections
*/
func (o *PonSimOltDevice) AddOnu(onu *PonSimOnuDevice) (int32, error) {
	var portNum int32
	ctx := context.Background()

	if portNum = o.nextAvailablePort(); portNum != -1 {
		common.Logger().WithFields(logrus.Fields{
			"device": o,
			"port":   portNum,
			"onu":    onu,
		}).Info("Adding ONU")

		registree := &OnuRegistree{Device: onu}

		// Setup GRPC communication and check if it succeeded
		if err := o.ConnectToRemoteOnu(registree); err == nil {
			o.GetOnus()[portNum] = registree

			o.AddLink(1, int(portNum), o.forwardToONU(portNum))
			go o.MonitorOnu(ctx, portNum)
			go o.Listen(ctx, portNum)
		}

	} else {
		common.Logger().WithFields(logrus.Fields{
			"device": o,
		}).Warn("ONU Map is full")
	}

	return int32(portNum), nil
}

/*
RemoveOnu removes the reference to a registered ONU
*/
func (o *PonSimOltDevice) RemoveOnu(ctx context.Context, onuIndex int32) error {
	onu := o.GetOnu(onuIndex)
	if err := onu.Conn.Close(); err != nil {
		common.Logger().WithFields(logrus.Fields{
			"device":   o,
			"onu":      onu.Device,
			"onuIndex": onuIndex,
		}).Error("Problem closing connection to ONU")
	}

	common.Logger().WithFields(logrus.Fields{
		"device":   o,
		"onu":      onu,
		"onuIndex": onuIndex,
	}).Info("Removing ONU")

	delete(o.Onus, onuIndex)

	// Remove link entries for this ONU
	o.RemoveLink(1, int(onuIndex))

	return nil
}

/*
MonitorOnu verifies the connection status of a specific ONU and cleans up as necessary
*/
func (o *PonSimOltDevice) MonitorOnu(ctx context.Context, onuIndex int32) {
	for {
		if o.GetOnu(onuIndex) != nil {
			if conn := o.GetOnu(onuIndex).Conn; conn.GetState() == connectivity.Ready {
				// Wait for any change to occur
				conn.WaitForStateChange(ctx, conn.GetState())
				// We lost communication with the ONU ... remove it
				o.RemoveOnu(ctx, onuIndex)
				return
			}
			common.Logger().WithFields(logrus.Fields{
				"device":   o,
				"ctx":      ctx,
				"onuIndex": onuIndex,
			}).Debug("ONU is not ready")
			time.Sleep(1 * time.Second)
		} else {
			return
		}
	}
}
