/*
 * Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors

 * 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 (
	"encoding/hex"
	"fmt"
	"net"
	"time"

	"github.com/looplab/fsm"
	"github.com/opencord/bbsim/internal/bbsim/packetHandlers"
	"github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
	"github.com/opencord/bbsim/internal/bbsim/responders/eapol"
	"github.com/opencord/bbsim/internal/bbsim/responders/igmp"
	bbsimTypes "github.com/opencord/bbsim/internal/bbsim/types"
	"github.com/opencord/bbsim/internal/common"
	log "github.com/sirupsen/logrus"
)

var serviceLogger = log.WithFields(log.Fields{
	"module": "SERVICE",
})

// time to wait before fail EAPOL/DHCP
// (it's a variable and not a constant so it can be overridden in the tests)
var eapolWaitTime = 60 * time.Second
var dhcpWaitTime = 60 * time.Second

const (
	ServiceStateCreated     = "created"
	ServiceStateInitialized = "initialized"
	ServiceStateDisabled    = "disabled"

	ServiceTxInitialize = "initialize"
	ServiceTxDisable    = "disable"

	fttbDpuMgmtServiceName = "DPU_MGMT_TRAFFIC"
)

type ServiceIf interface {
	HandlePackets()                   // start listening on the PacketCh
	HandleAuth()                      // Sends the EapoStart packet
	HandleDhcp(oPbit uint8, oVid int) // Sends the DHCPDiscover packet

	Initialize(stream bbsimTypes.Stream)
	UpdateStream(stream bbsimTypes.Stream)
	Disable()
}

type Service struct {
	Id                  uint32
	Name                string
	HwAddress           net.HardwareAddr
	UniPort             *UniPort
	CTag                int
	STag                int
	NeedsEapol          bool
	NeedsDhcp           bool
	NeedsIgmp           bool
	NeedsPPPoE          bool
	TechnologyProfileID int
	UniTagMatch         int
	ConfigureMacAddress bool
	EnableMacLearning   bool
	UsPonCTagPriority   uint8
	UsPonSTagPriority   uint8
	DsPonCTagPriority   uint8
	DsPonSTagPriority   uint8

	// state
	GemPort       uint32
	InternalState *fsm.FSM
	EapolState    *fsm.FSM
	DHCPState     *fsm.FSM
	IGMPState     *fsm.FSM
	Channel       chan bbsimTypes.Message          // drive Service lifecycle
	PacketCh      chan bbsimTypes.OnuPacketMessage // handle packets
	Stream        bbsimTypes.Stream                // the gRPC stream to communicate with the adapter, created in the initialize transition
}

func NewService(id uint32, name string, hwAddress net.HardwareAddr, uni *UniPort, cTag int, sTag int,
	needsEapol bool, needsDchp bool, needsIgmp bool, needsPPPoE bool, tpID int, uniTagMatch int, configMacAddress bool,
	enableMacLearning bool, usPonCTagPriority uint8, usPonSTagPriority uint8, dsPonCTagPriority uint8,
	dsPonSTagPriority uint8) (*Service, error) {

	service := Service{
		Id:                  id,
		Name:                name,
		HwAddress:           hwAddress,
		UniPort:             uni,
		CTag:                cTag,
		STag:                sTag,
		NeedsEapol:          needsEapol,
		NeedsDhcp:           needsDchp,
		NeedsIgmp:           needsIgmp,
		NeedsPPPoE:          needsPPPoE,
		TechnologyProfileID: tpID,
		UniTagMatch:         uniTagMatch,
		ConfigureMacAddress: configMacAddress,
		EnableMacLearning:   enableMacLearning,
		UsPonCTagPriority:   usPonCTagPriority,
		UsPonSTagPriority:   usPonSTagPriority,
		DsPonCTagPriority:   dsPonCTagPriority,
		DsPonSTagPriority:   dsPonSTagPriority,
	}

	service.InternalState = fsm.NewFSM(
		ServiceStateCreated,
		fsm.Events{
			{Name: ServiceTxInitialize, Src: []string{ServiceStateCreated, ServiceStateDisabled}, Dst: ServiceStateInitialized},
			{Name: ServiceTxDisable, Src: []string{ServiceStateInitialized}, Dst: ServiceStateDisabled},
		},
		fsm.Callbacks{
			"enter_state": func(e *fsm.Event) {
				service.logStateChange("InternalState", e.Src, e.Dst)
			},
			fmt.Sprintf("enter_%s", ServiceStateInitialized): func(e *fsm.Event) {

				stream, ok := e.Args[0].(bbsimTypes.Stream)
				if !ok {
					serviceLogger.Fatal("initialize invoke with wrong arguments")
				}

				service.UpdateStream(stream)

				service.PacketCh = make(chan bbsimTypes.OnuPacketMessage)
				service.Channel = make(chan bbsimTypes.Message)

				go service.HandlePackets()
				go service.HandleChannel()
			},
			fmt.Sprintf("enter_%s", ServiceStateDisabled): func(e *fsm.Event) {
				// reset the state machines
				service.EapolState.SetState(eapol.StateCreated)
				service.DHCPState.SetState("created")

				// stop listening for packets
				close(service.PacketCh)
				close(service.Channel)

				service.PacketCh = nil
				service.Channel = nil
			},
		},
	)

	service.EapolState = fsm.NewFSM(
		eapol.StateCreated,
		fsm.Events{
			{Name: eapol.EventStartAuth, Src: []string{eapol.StateCreated, eapol.StateResponseSuccessReceived, eapol.StateAuthFailed}, Dst: eapol.StateAuthStarted},
			{Name: eapol.EventStartSent, Src: []string{eapol.StateAuthStarted}, Dst: eapol.StateStartSent},
			{Name: eapol.EventResponseIdentitySent, Src: []string{eapol.StateStartSent}, Dst: eapol.StateResponseIdentitySent},
			{Name: eapol.EventResponseChallengeSent, Src: []string{eapol.StateResponseIdentitySent}, Dst: eapol.StateResponseChallengeSent},
			{Name: eapol.EventResponseSuccessReceived, Src: []string{eapol.StateResponseChallengeSent}, Dst: eapol.StateResponseSuccessReceived},
			{Name: eapol.EventAuthFailed, Src: []string{eapol.StateAuthStarted, eapol.StateStartSent, eapol.StateResponseIdentitySent, eapol.StateResponseChallengeSent}, Dst: eapol.StateAuthFailed},
		},
		fsm.Callbacks{
			"enter_state": func(e *fsm.Event) {
				service.logStateChange("EapolState", e.Src, e.Dst)
			},
			fmt.Sprintf("before_%s", eapol.EventStartAuth): func(e *fsm.Event) {
				msg := bbsimTypes.Message{
					Type: bbsimTypes.StartEAPOL,
				}
				service.Channel <- msg
			},
			fmt.Sprintf("enter_%s", eapol.StateAuthStarted): func(e *fsm.Event) {
				go func() {

					for {
						select {
						case <-service.UniPort.Onu.PonPort.Olt.enableContext.Done():
							serviceLogger.WithFields(log.Fields{
								"context": service.UniPort.Onu.PonPort.Olt.enableContext,
							}).Debug("EAPOL cancelled, OLT is disabled")
							return
						case <-time.After(eapolWaitTime):
							if service.EapolState.Current() != eapol.StateResponseSuccessReceived {
								serviceLogger.WithFields(log.Fields{
									"OnuId":      service.UniPort.Onu.ID,
									"IntfId":     service.UniPort.Onu.PonPortID,
									"OnuSn":      service.UniPort.Onu.Sn(),
									"Name":       service.Name,
									"PortNo":     service.UniPort.PortNo,
									"UniId":      service.UniPort.ID,
									"EapolState": service.EapolState.Current(),
								}).Warn("EAPOL failed, resetting EAPOL State")

								_ = service.EapolState.Event(eapol.EventAuthFailed)
								if common.Config.BBSim.AuthRetry {
									_ = service.EapolState.Event(eapol.EventStartAuth)
								}

								return
							}
						}

					}
				}()
			},
		},
	)

	service.DHCPState = fsm.NewFSM(
		"created",
		fsm.Events{
			{Name: "start_dhcp", Src: []string{"created", "dhcp_ack_received", "dhcp_failed"}, Dst: "dhcp_started"},
			{Name: "dhcp_discovery_sent", Src: []string{"dhcp_started"}, Dst: "dhcp_discovery_sent"},
			{Name: "dhcp_request_sent", Src: []string{"dhcp_discovery_sent"}, Dst: "dhcp_request_sent"},
			{Name: "dhcp_ack_received", Src: []string{"dhcp_request_sent"}, Dst: "dhcp_ack_received"},
			{Name: "dhcp_failed", Src: []string{"dhcp_started", "dhcp_discovery_sent", "dhcp_request_sent"}, Dst: "dhcp_failed"},
		},
		fsm.Callbacks{
			"enter_state": func(e *fsm.Event) {
				service.logStateChange("DHCPState", e.Src, e.Dst)
			},
			"before_start_dhcp": func(e *fsm.Event) {
				msg := bbsimTypes.Message{
					Type: bbsimTypes.StartDHCP,
				}
				service.Channel <- msg
			},
			"enter_dhcp_started": func(e *fsm.Event) {
				go func() {

					for {
						select {
						case <-service.UniPort.Onu.PonPort.Olt.enableContext.Done():
							serviceLogger.WithFields(log.Fields{
								"context": service.UniPort.Onu.PonPort.Olt.enableContext,
							}).Debug("DHCP cancelled, OLT is disabled")
							return
						case <-time.After(dhcpWaitTime):
							if service.DHCPState.Current() != "dhcp_ack_received" {
								serviceLogger.WithFields(log.Fields{
									"OnuId":     service.UniPort.Onu.ID,
									"IntfId":    service.UniPort.Onu.PonPortID,
									"OnuSn":     service.UniPort.Onu.Sn(),
									"Name":      service.Name,
									"PortNo":    service.UniPort.PortNo,
									"UniId":     service.UniPort.ID,
									"DHCPState": service.DHCPState.Current(),
								}).Warn("DHCP failed, resetting DHCP State")

								_ = service.DHCPState.Event("dhcp_failed")
								if common.Config.BBSim.DhcpRetry {
									_ = service.DHCPState.Event("start_dhcp")
								}

								return
							}
						}

					}
				}()
			},
		},
	)

	service.IGMPState = fsm.NewFSM(
		"created",
		fsm.Events{
			{Name: "igmp_join_start", Src: []string{"created", "igmp_left", "igmp_join_error", "igmp_join_started"}, Dst: "igmp_join_started"},
			{Name: "igmp_join_startv3", Src: []string{"igmp_left", "igmp_join_error", "igmp_join_started"}, Dst: "igmp_join_started"},
			{Name: "igmp_join_error", Src: []string{"igmp_join_started"}, Dst: "igmp_join_error"},
			{Name: "igmp_leave", Src: []string{"igmp_join_started"}, Dst: "igmp_left"},
		},
		fsm.Callbacks{
			"igmp_join_start": func(e *fsm.Event) {
				igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
				msg := bbsimTypes.Message{
					Type: bbsimTypes.IGMPMembershipReportV2,
					Data: bbsimTypes.IgmpMessage{
						GroupAddress: igmpInfo.GroupAddress,
					},
				}
				service.Channel <- msg
			},
			"igmp_leave": func(e *fsm.Event) {
				igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
				msg := bbsimTypes.Message{
					Type: bbsimTypes.IGMPLeaveGroup,
					Data: bbsimTypes.IgmpMessage{
						GroupAddress: igmpInfo.GroupAddress,
					},
				}
				service.Channel <- msg
			},
			"igmp_join_startv3": func(e *fsm.Event) {
				igmpInfo, _ := e.Args[0].(bbsimTypes.IgmpMessage)
				msg := bbsimTypes.Message{
					Type: bbsimTypes.IGMPMembershipReportV3,
					Data: bbsimTypes.IgmpMessage{
						GroupAddress: igmpInfo.GroupAddress,
					},
				}
				service.Channel <- msg
			},
		},
	)

	return &service, nil
}

func (s *Service) UpdateStream(stream bbsimTypes.Stream) {
	s.Stream = stream
}

// HandleAuth is used to start EAPOL for a particular Service when the corresponding flow is received
func (s *Service) HandleAuth() {

	if !s.NeedsEapol {
		serviceLogger.WithFields(log.Fields{
			"OnuId":      s.UniPort.Onu.ID,
			"IntfId":     s.UniPort.Onu.PonPortID,
			"OnuSn":      s.UniPort.Onu.Sn(),
			"PortNo":     s.UniPort.PortNo,
			"UniId":      s.UniPort.ID,
			"Name":       s.Name,
			"NeedsEapol": s.NeedsEapol,
		}).Debug("Won't start authentication as EAPOL is not required")
		return
	}

	serviceLogger.WithFields(log.Fields{
		"OnuId":      s.UniPort.Onu.ID,
		"IntfId":     s.UniPort.Onu.PonPortID,
		"OnuSn":      s.UniPort.Onu.Sn(),
		"PortNo":     s.UniPort.PortNo,
		"UniId":      s.UniPort.ID,
		"Name":       s.Name,
		"NeedsEapol": s.NeedsEapol,
	}).Debug("Starting EAPOL for the service")
	if err := s.EapolState.Event(eapol.EventStartAuth); err != nil {
		serviceLogger.WithFields(log.Fields{
			"OnuId":  s.UniPort.Onu.ID,
			"IntfId": s.UniPort.Onu.PonPortID,
			"OnuSn":  s.UniPort.Onu.Sn(),
			"PortNo": s.UniPort.PortNo,
			"UniId":  s.UniPort.ID,
			"Name":   s.Name,
			"err":    err.Error(),
		}).Error("Can't start auth for this Service")
	}
}

// HandleDhcp is used to start DHCP for a particular Service when the corresponding flow is received
func (s *Service) HandleDhcp(oPbit uint8, oVid int) {
	var compareTag int
	var comparePbits uint8

	if s.Name == fttbDpuMgmtServiceName {
		compareTag = s.STag
		comparePbits = s.UsPonSTagPriority
	} else {
		compareTag = s.CTag
		comparePbits = s.UsPonCTagPriority
	}

	if compareTag != oVid || (comparePbits != oPbit && oPbit != 255) {
		serviceLogger.WithFields(log.Fields{
			"OnuId":        s.UniPort.Onu.ID,
			"IntfId":       s.UniPort.Onu.PonPortID,
			"OnuSn":        s.UniPort.Onu.Sn(),
			"PortNo":       s.UniPort.PortNo,
			"UniId":        s.UniPort.ID,
			"Name":         s.Name,
			"compareTag":   compareTag,
			"comparePbits": comparePbits,
			"oVid":         oVid,
			"oPbit":        oPbit,
		}).Debug("DHCP flow is not for this service, ignoring")
		return
	}

	if !s.NeedsDhcp {
		serviceLogger.WithFields(log.Fields{
			"OnuId":     s.UniPort.Onu.ID,
			"IntfId":    s.UniPort.Onu.PonPortID,
			"OnuSn":     s.UniPort.Onu.Sn(),
			"PortNo":    s.UniPort.PortNo,
			"UniId":     s.UniPort.ID,
			"Name":      s.Name,
			"NeedsDhcp": s.NeedsDhcp,
		}).Trace("Won't start DHCP as it is not required")
		return
	}

	serviceLogger.WithFields(log.Fields{
		"OnuId":      s.UniPort.Onu.ID,
		"IntfId":     s.UniPort.Onu.PonPortID,
		"OnuSn":      s.UniPort.Onu.Sn(),
		"PortNo":     s.UniPort.PortNo,
		"UniId":      s.UniPort.ID,
		"Name":       s.Name,
		"NeedsEapol": s.NeedsEapol,
	}).Debug("Starting DHCP for the service")
	if err := s.DHCPState.Event("start_dhcp"); err != nil {
		serviceLogger.WithFields(log.Fields{
			"OnuId":  s.UniPort.Onu.ID,
			"IntfId": s.UniPort.Onu.PonPortID,
			"OnuSn":  s.UniPort.Onu.Sn(),
			"PortNo": s.UniPort.PortNo,
			"UniId":  s.UniPort.ID,
			"Name":   s.Name,
			"err":    err.Error(),
		}).Error("Can't start DHCP for this Service")
	}
}

func (s *Service) HandlePackets() {
	serviceLogger.WithFields(log.Fields{
		"OnuId":     s.UniPort.Onu.ID,
		"IntfId":    s.UniPort.Onu.PonPortID,
		"OnuSn":     s.UniPort.Onu.Sn(),
		"GemPortId": s.GemPort,
		"PortNo":    s.UniPort.PortNo,
		"UniId":     s.UniPort.ID,
		"Name":      s.Name,
	}).Debug("Listening on Service Packet Channel")

	defer func() {
		serviceLogger.WithFields(log.Fields{
			"OnuId":     s.UniPort.Onu.ID,
			"IntfId":    s.UniPort.Onu.PonPortID,
			"OnuSn":     s.UniPort.Onu.Sn(),
			"GemPortId": s.GemPort,
			"PortNo":    s.UniPort.PortNo,
			"UniId":     s.UniPort.ID,
			"Name":      s.Name,
		}).Debug("Done Listening on Service Packet Channel")
	}()

	for msg := range s.PacketCh {
		serviceLogger.WithFields(log.Fields{
			"OnuId":       s.UniPort.Onu.ID,
			"IntfId":      s.UniPort.Onu.PonPortID,
			"OnuSn":       s.UniPort.Onu.Sn(),
			"GemPortId":   s.GemPort,
			"PortNo":      s.UniPort.PortNo,
			"UniId":       s.UniPort.ID,
			"Name":        s.Name,
			"messageType": msg.Type,
		}).Trace("Received message on Service Packet Channel")

		if msg.Type == packetHandlers.EAPOL {
			eapol.HandleNextPacket(msg.OnuId, msg.IntfId, s.GemPort, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.Id, s.UniPort.Onu.PonPort.Olt.ID, s.EapolState, msg.Packet, s.Stream, nil)
		} else if msg.Type == packetHandlers.DHCP {
			tag := int(s.CTag)
			priority := s.UsPonCTagPriority
			if s.Name == fttbDpuMgmtServiceName {
				tag = int(s.STag)
				priority = s.UsPonSTagPriority
			}

			_ = dhcp.HandleNextPacket(s.UniPort.Onu.ID, s.UniPort.Onu.PonPortID, s.Name, s.UniPort.Onu.Sn(), s.UniPort.PortNo, tag, s.GemPort, s.UniPort.ID, s.HwAddress, s.DHCPState, msg.Packet, priority, s.Stream)
		} else if msg.Type == packetHandlers.IGMP {
			log.Warn(hex.EncodeToString(msg.Packet.Data()))
			_ = igmp.HandleNextPacket(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, msg.Packet, s.CTag, s.UsPonCTagPriority, s.Stream)
		}
	}
}

func (s *Service) HandleChannel() {
	serviceLogger.WithFields(log.Fields{
		"OnuId":     s.UniPort.Onu.ID,
		"IntfId":    s.UniPort.Onu.PonPortID,
		"OnuSn":     s.UniPort.Onu.Sn(),
		"GemPortId": s.GemPort,
		"PortNo":    s.UniPort.PortNo,
		"UniId":     s.UniPort.ID,
		"Name":      s.Name,
	}).Debug("Listening on Service Channel")

	defer func() {
		serviceLogger.WithFields(log.Fields{
			"OnuId":     s.UniPort.Onu.ID,
			"IntfId":    s.UniPort.Onu.PonPortID,
			"OnuSn":     s.UniPort.Onu.Sn(),
			"GemPortId": s.GemPort,
			"PortNo":    s.UniPort.PortNo,
			"UniId":     s.UniPort.ID,
			"Name":      s.Name,
		}).Debug("Done Listening on Service Channel")
	}()
	for msg := range s.Channel {
		switch msg.Type {
		case bbsimTypes.StartEAPOL:
			if err := s.handleEapolStart(s.Stream); err != nil {
				serviceLogger.WithFields(log.Fields{
					"OnuId":     s.UniPort.Onu.ID,
					"IntfId":    s.UniPort.Onu.PonPortID,
					"OnuSn":     s.UniPort.Onu.Sn(),
					"GemPortId": s.GemPort,
					"PortNo":    s.UniPort.PortNo,
					"UniId":     s.UniPort.ID,
					"Name":      s.Name,
					"err":       err,
				}).Error("Error while sending EapolStart packet")
				_ = s.EapolState.Event(eapol.EventAuthFailed)
			}
		case bbsimTypes.StartDHCP:
			if err := s.handleDHCPStart(s.Stream); err != nil {
				serviceLogger.WithFields(log.Fields{
					"OnuId":     s.UniPort.Onu.ID,
					"IntfId":    s.UniPort.Onu.PonPortID,
					"OnuSn":     s.UniPort.Onu.Sn(),
					"GemPortId": s.GemPort,
					"PortNo":    s.UniPort.PortNo,
					"UniId":     s.UniPort.ID,
					"Name":      s.Name,
					"err":       err,
				}).Error("Error while sending DHCPDiscovery packet")
				_ = s.DHCPState.Event("dhcp_failed")

			}
		case bbsimTypes.IGMPMembershipReportV2:
			igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
			serviceLogger.WithFields(log.Fields{
				"OnuId":     s.UniPort.Onu.ID,
				"IntfId":    s.UniPort.Onu.PonPortID,
				"OnuSn":     s.UniPort.Onu.Sn(),
				"GemPortId": s.GemPort,
				"PortNo":    s.UniPort.PortNo,
				"UniId":     s.UniPort.ID,
				"Name":      s.Name,
			}).Debug("Received IGMPMembershipReportV2 message on ONU channel")
			_ = igmp.SendIGMPMembershipReportV2(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
		case bbsimTypes.IGMPLeaveGroup:
			igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
			serviceLogger.WithFields(log.Fields{
				"OnuId":     s.UniPort.Onu.ID,
				"IntfId":    s.UniPort.Onu.PonPortID,
				"OnuSn":     s.UniPort.Onu.Sn(),
				"GemPortId": s.GemPort,
				"PortNo":    s.UniPort.PortNo,
				"UniId":     s.UniPort.ID,
				"Name":      s.Name,
			}).Debug("Received IGMPLeaveGroupV2 message on ONU channel")
			_ = igmp.SendIGMPLeaveGroupV2(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)
		case bbsimTypes.IGMPMembershipReportV3:
			igmpInfo, _ := msg.Data.(bbsimTypes.IgmpMessage)
			serviceLogger.WithFields(log.Fields{
				"OnuId":     s.UniPort.Onu.ID,
				"IntfId":    s.UniPort.Onu.PonPortID,
				"OnuSn":     s.UniPort.Onu.Sn(),
				"GemPortId": s.GemPort,
				"PortNo":    s.UniPort.PortNo,
				"UniId":     s.UniPort.ID,
				"Name":      s.Name,
			}).Debug("Received IGMPMembershipReportV3 message on ONU channel")
			_ = igmp.SendIGMPMembershipReportV3(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.GemPort, s.HwAddress, s.CTag, s.UsPonCTagPriority, s.Stream, igmpInfo.GroupAddress)

		}
	}
}

func (s *Service) Initialize(stream bbsimTypes.Stream) {
	if err := s.InternalState.Event(ServiceTxInitialize, stream); err != nil {
		serviceLogger.WithFields(log.Fields{
			"OnuId":     s.UniPort.Onu.ID,
			"IntfId":    s.UniPort.Onu.PonPortID,
			"OnuSn":     s.UniPort.Onu.Sn(),
			"GemPortId": s.GemPort,
			"PortNo":    s.UniPort.PortNo,
			"UniId":     s.UniPort.ID,
			"Name":      s.Name,
			"Err":       err,
		}).Error("Cannot initialize service")
	}
}

func (s *Service) Disable() {
	if err := s.InternalState.Event(ServiceTxDisable); err != nil {
		serviceLogger.WithFields(log.Fields{
			"OnuId":     s.UniPort.Onu.ID,
			"IntfId":    s.UniPort.Onu.PonPortID,
			"OnuSn":     s.UniPort.Onu.Sn(),
			"GemPortId": s.GemPort,
			"PortNo":    s.UniPort.PortNo,
			"UniId":     s.UniPort.ID,
			"Name":      s.Name,
			"Err":       err,
		}).Error("Cannot disable service")
	}
}

func (s *Service) handleEapolStart(stream bbsimTypes.Stream) error {
	serviceLogger.WithFields(log.Fields{
		"OnuId":     s.UniPort.Onu.ID,
		"IntfId":    s.UniPort.Onu.PonPortID,
		"OnuSn":     s.UniPort.Onu.Sn(),
		"GemPortId": s.GemPort,
		"PortNo":    s.UniPort.PortNo,
		"UniId":     s.UniPort.ID,
		"GemPort":   s.GemPort,
		"Name":      s.Name,
	}).Trace("handleEapolStart")

	if err := eapol.SendEapStart(s.UniPort.Onu.ID, s.UniPort.Onu.PonPortID, s.UniPort.Onu.Sn(), s.UniPort.PortNo,
		s.HwAddress, s.GemPort, s.UniPort.ID, s.EapolState, stream); err != nil {
		serviceLogger.WithFields(log.Fields{
			"OnuId":   s.UniPort.Onu.ID,
			"IntfId":  s.UniPort.Onu.PonPortID,
			"OnuSn":   s.UniPort.Onu.Sn(),
			"GemPort": s.GemPort,
			"Name":    s.Name,
		}).Error("handleEapolStart")
		return err
	}
	return nil
}

func (s *Service) handleDHCPStart(stream bbsimTypes.Stream) error {
	serviceLogger.WithFields(log.Fields{
		"OnuId":     s.UniPort.Onu.ID,
		"IntfId":    s.UniPort.Onu.PonPortID,
		"OnuSn":     s.UniPort.Onu.Sn(),
		"Name":      s.Name,
		"GemPortId": s.GemPort,
		"PortNo":    s.UniPort.PortNo,
		"UniId":     s.UniPort.ID,
	}).Debugf("HandleDHCPStart")

	tag := int(s.CTag)
	priority := s.UsPonCTagPriority
	if s.Name == fttbDpuMgmtServiceName {
		tag = int(s.STag)
		priority = s.UsPonSTagPriority
	}

	if err := dhcp.SendDHCPDiscovery(s.UniPort.Onu.PonPortID, s.UniPort.Onu.ID, s.Name, tag, s.GemPort,
		s.UniPort.Onu.Sn(), s.UniPort.PortNo, s.UniPort.ID, s.DHCPState, s.HwAddress, priority, stream); err != nil {
		serviceLogger.WithFields(log.Fields{
			"OnuId":     s.UniPort.Onu.ID,
			"IntfId":    s.UniPort.Onu.PonPortID,
			"OnuSn":     s.UniPort.Onu.Sn(),
			"Name":      s.Name,
			"GemPortId": s.GemPort,
			"PortNo":    s.UniPort.PortNo,
			"UniId":     s.UniPort.ID,
		}).Error("HandleDHCPStart")
		return err
	}
	return nil
}

func (s *Service) logStateChange(stateMachine string, src string, dst string) {
	serviceLogger.WithFields(log.Fields{
		"OnuId":     s.UniPort.Onu.ID,
		"IntfId":    s.UniPort.Onu.PonPortID,
		"OnuSn":     s.UniPort.Onu.Sn(),
		"GemPortId": s.GemPort,
		"PortNo":    s.UniPort.PortNo,
		"UniId":     s.UniPort.ID,
		"Name":      s.Name,
	}).Debugf("Changing Service.%s InternalState from %s to %s", stateMachine, src, dst)
}
