/*
* 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 application

import (
	"context"
	"encoding/json"
	"net"
	"sync"
	"time"

	"github.com/google/gopacket/layers"

	cntlr "voltha-go-controller/internal/pkg/controller"
	"voltha-go-controller/internal/pkg/of"
	"voltha-go-controller/internal/pkg/util"
	"voltha-go-controller/log"
)

// IgmpGroupDevice : IGMP Group Device manages the IGMP group for all listerns on
// a single OLT. It aggregates reports received on a single group
// and performs the count. It is responsible for sending upstream
// report when the first listener joins and is responsible for
// sending responses to upstream queries
type IgmpGroupDevice struct {
        Device            string
        SerialNo          string
        GroupID           uint32
        GroupName         string
        GroupAddr         net.IP
        RecvVersion       uint8
        ServVersion       *uint8
        RecvVersionExpiry time.Time
        ServVersionExpiry time.Time
        Mvlan             of.VlanType
        PonVlan           of.VlanType
        IsPonVlanPresent  bool
        GroupInstalled    bool
        GroupChannels     sync.Map            `json:"-"` // [ipAddr]*IgmpGroupChannel
        PortChannelMap    sync.Map            `json:"-"` // [portName][]net.IP
        PonPortChannelMap *util.ConcurrentMap `json:"-"` // [ponPortId]*PonPortChannels
        proxyCfg          *IgmpProfile                   // IgmpSrcIp from IgmpProfile is not used, it is kept for backward compatibility
        IgmpProxyIP       *net.IP             `json:"-"`
        NextQueryTime     time.Time
        QueryExpiryTime   time.Time
}

// NewIgmpGroupDevice is constructor for a device. The default IGMP version is set to 3
// as the protocol defines the way to manage backward compatibility
// The implementation handles simultaneous presense of lower versioned
// receivers
func NewIgmpGroupDevice(name string, ig *IgmpGroup, id uint32, version uint8) *IgmpGroupDevice {
        var igd IgmpGroupDevice
        igd.Device = name
        igd.GroupID = id
        igd.GroupName = ig.GroupName
        igd.GroupAddr = ig.GroupAddr
        igd.Mvlan = ig.Mvlan
        igd.PonVlan = ig.PonVlan
        igd.IsPonVlanPresent = ig.IsPonVlanPresent
        igd.GroupInstalled = false
        igd.RecvVersion = version
        igd.RecvVersionExpiry = time.Now()
        igd.ServVersionExpiry = time.Now()
        igd.PonPortChannelMap = util.NewConcurrentMap()

        va := GetApplication()
        if vd := va.GetDevice(igd.Device); vd != nil {
                igd.SerialNo = vd.SerialNum
        } else {
                logger.Errorw(ctx, "Volt Device not found.  log.Fields", log.Fields{"igd.Device": igd.Device})
                return nil
        }
        mvp := GetApplication().GetMvlanProfileByTag(igd.Mvlan)
        igd.ServVersion = mvp.IgmpServVersion[igd.SerialNo]

        var mcastCfg *McastConfig
        igd.proxyCfg, igd.IgmpProxyIP, mcastCfg = getIgmpProxyCfgAndIP(ig.Mvlan, igd.SerialNo)

        // mvlan profile id + olt serial number---igmp group id
        //igmpgroup id
        igd.NextQueryTime = time.Now().Add(time.Duration(igd.proxyCfg.KeepAliveInterval) * time.Second)
        igd.QueryExpiryTime = time.Now().Add(time.Duration(igd.proxyCfg.KeepAliveInterval) * time.Second)

        if mcastCfg != nil {
                mcastCfg.IgmpGroupDevices.Store(id, &igd)
                logger.Debugw(ctx, "Igd added to mcast config", log.Fields{"mvlan": mcastCfg.MvlanProfileID, "groupId": id})
        }
        return &igd
}

// IgmpGroupDeviceReInit is re-initializer for a device. The default IGMP version is set to 3
// as the protocol defines the way to manage backward compatibility
func (igd *IgmpGroupDevice) IgmpGroupDeviceReInit(cntx context.Context, ig *IgmpGroup) {

        logger.Infow(ctx, "Reinitialize Igmp Group Device", log.Fields{"Device": igd.Device, "GroupID": ig.GroupID, "OldName": igd.GroupName, "Name": ig.GroupName, "OldAddr": igd.GroupAddr.String(), "GroupAddr": ig.GroupAddr.String()})

        if (igd.GroupName != ig.GroupName) || !igd.GroupAddr.Equal(ig.GroupAddr) {
                _ = db.DelIgmpDevice(cntx, igd.Mvlan, igd.GroupName, igd.GroupAddr, igd.Device)
                igd.GroupName = ig.GroupName
                igd.GroupAddr = ig.GroupAddr
        }
        igd.RecvVersionExpiry = time.Now()
        igd.ServVersionExpiry = time.Now()
        igd.PonPortChannelMap = util.NewConcurrentMap()

        var mcastCfg *McastConfig
        igd.proxyCfg, igd.IgmpProxyIP, mcastCfg = getIgmpProxyCfgAndIP(ig.Mvlan, igd.SerialNo)

        igd.NextQueryTime = time.Now().Add(time.Duration(igd.proxyCfg.KeepAliveInterval) * time.Second)
        igd.QueryExpiryTime = time.Now().Add(time.Duration(igd.proxyCfg.KeepAliveInterval) * time.Second)

        if mcastCfg != nil {
                mcastCfg.IgmpGroupDevices.Store(ig.GroupID, igd)
                logger.Debugw(ctx, "Igd added to mcast config", log.Fields{"mvlan": mcastCfg.MvlanProfileID, "groupId": ig.GroupID})
        }
        if err := igd.WriteToDb(cntx); err != nil {
                logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
        }
}

func getIgmpProxyCfgAndIP(mvlan of.VlanType, serialNo string) (*IgmpProfile, *net.IP, *McastConfig) {
        va := GetApplication()
        mVLANProfileID := va.GetMvlanProfileByTag(mvlan).Name
        var mcastCfg *McastConfig
        if mcastCfg = va.GetMcastConfig(serialNo, mVLANProfileID); mcastCfg == nil || (mcastCfg != nil && mcastCfg.IgmpProfileID == "") {
                logger.Debugw(ctx, "Default IGMP config to be used", log.Fields{"mVLANProfileID": mVLANProfileID, "OltSerialNo": serialNo})
                igmpProf := va.getIgmpProfileMap(DefaultIgmpProfID)
                return igmpProf, &igmpProf.IgmpSourceIP, mcastCfg
        }
        return va.getIgmpProfileMap(mcastCfg.IgmpProfileID), &mcastCfg.IgmpProxyIP, mcastCfg
}

// updateGroupName to update the group name
func (igd *IgmpGroupDevice) updateGroupName(cntx context.Context, newGroupName string) {

        oldName := igd.GroupName
        igd.GroupName = newGroupName
        updateGroupName := func(key, value interface{}) bool {
                igc := value.(*IgmpGroupChannel)
                igc.GroupName = newGroupName
                if err := igc.WriteToDb(cntx); err != nil {
                        logger.Errorw(ctx, "Igmp group channel Write to DB failed", log.Fields{"mvlan": igc.Mvlan, "GroupAddr": igc.GroupAddr})
                }
                _ = db.DelIgmpChannel(cntx, igc.Mvlan, oldName, igc.Device, igc.GroupAddr)
                return true
        }
        igd.GroupChannels.Range(updateGroupName)
        if err := igd.WriteToDb(cntx); err != nil {
                logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
        }
        _ = db.DelIgmpDevice(cntx, igd.Mvlan, oldName, igd.GroupAddr, igd.Device)
}

// NewIgmpGroupDeviceFromBytes is to create the IGMP group port from a byte slice
func NewIgmpGroupDeviceFromBytes(b []byte) (*IgmpGroupDevice, error) {
        var igd IgmpGroupDevice
        if err := json.Unmarshal(b, &igd); err != nil {
                return nil, err
        }
        return &igd, nil
}

// GetKey to get group name as key
func (igd *IgmpGroupDevice) GetKey() string {

        if !net.ParseIP("0.0.0.0").Equal(igd.GroupAddr) {
                return igd.GroupName + "_" + igd.GroupAddr.String()
        }
        return igd.GroupName

}

// RestoreChannel to restore channel
func (igd *IgmpGroupDevice) RestoreChannel(cntx context.Context, igmpGroupChannel []byte) {

        if igc, err := NewIgmpGroupChannelFromBytes(igmpGroupChannel); err == nil {
                igc.ServVersion = igd.ServVersion
                igc.IgmpProxyIP = &igd.IgmpProxyIP
                igc.proxyCfg = &igd.proxyCfg
                igd.GroupChannels.Store(igc.GroupAddr.String(), igc)
                igc.RestorePorts(cntx)

                for port, igp := range igc.NewReceivers {
                        ipsList := []net.IP{}
                        ipsIntf, _ := igd.PortChannelMap.Load(port)
                        if ipsIntf != nil {
                                ipsList = ipsIntf.([]net.IP)
                        }

                        ipsList = append(ipsList, igc.GroupAddr)
                        igd.PortChannelMap.Store(port, ipsList)
                        logger.Infow(ctx, "Group Channels Restored", log.Fields{"IGC": igc})
                        igd.AddChannelToChannelsPerPon(port, igc.GroupAddr, igp.PonPortID)
                }
        } else {
                logger.Warnw(ctx, "Failed to decode port from DB", log.Fields{"err": err})
        }
        logger.Info(ctx, "Group Device & Channels Restored")
        igd.PortChannelMap.Range(printPortChannel)
        igd.GroupChannels.Range(printChannel)

}

// RestoreChannels to restore channels
func (igd *IgmpGroupDevice) RestoreChannels(cntx context.Context) {

        igd.migrateIgmpChannels(cntx)
        channels, _ := db.GetIgmpChannels(cntx, igd.Mvlan, igd.GroupName, igd.Device)
        for _, channel := range channels {

                b, ok := channel.Value.([]byte)
                if !ok {
                        logger.Warn(ctx, "The value type is not []byte")
                        continue
                }
                igd.RestoreChannel(cntx, b)
        }

}


// WriteToDb is utility to write IGMP Group Device Info to the database
func (igd *IgmpGroupDevice) WriteToDb(cntx context.Context) error {
        b, err := json.Marshal(igd)
        if err != nil {
                return err
        }
        if err1 := db.PutIgmpDevice(cntx, igd.Mvlan, igd.GroupName, igd.GroupAddr, igd.Device, string(b)); err1 != nil {
                return err1
        }
        logger.Info(ctx, "IGD Updated")
        return nil
}

// Tick processes timing tick used to run timers within the device
func (igd *IgmpGroupDevice) Tick() uint8 {
        /* Not using RecvVersionExpiry as it is not used anywhere
        if time.Now().After(igd.RecvVersionExpiry) {
                igd.RecvVersion = IgmpVersion3
                return true
        }
        */
        return 0
}

// GetSubscriberCountForChannelAndPonPort Gets the active subscriber count
// for the given channel for one particular PON port
func (igd *IgmpGroupDevice) GetSubscriberCountForChannelAndPonPort(ponPortID uint32, channelIP net.IP) uint64 {
        if portMapIntf, ok := igd.PonPortChannelMap.Get(ponPortID); ok {
                portChannelMap := portMapIntf.(*PonPortChannels)

                if channel, present := portChannelMap.ChannelList.Get(channelIP.String()); present {
                        return channel.(*UniPortList).UNIList.Length()
                }
        } else {
                logger.Warnw(ctx, "PON port not found in PortChannelMap", log.Fields{"PON": ponPortID, "channel": channelIP})
        }
        return 0
}

// AddChannelToChannelsPerPon Adds the new channel into the per Pon channel list
func (igd *IgmpGroupDevice) AddChannelToChannelsPerPon(uniPort string, channelIP net.IP, ponPortID uint32) bool {
        logger.Debugw(ctx, "Adding channel to ActiveChannelsPerPon list", log.Fields{"PonPort": ponPortID, "channelIP": channelIP})

        isNewChannel := bool(false)
        isNewReceiver := false
        if port, ok := igd.PonPortChannelMap.Get(ponPortID); !ok {
                // PON port not exists in igd. adding it.
                isNewReceiver = true
                ponPortChannels := NewPonPortChannels()
                isNewChannel = ponPortChannels.AddChannelToMap(uniPort, channelIP.String())
                igd.PonPortChannelMap.Set(ponPortID, ponPortChannels)
        } else {
                // PON port exists in igd. Appending the channel list
                // in the PON port.
                isNewChannel = port.(*PonPortChannels).AddChannelToMap(uniPort, channelIP.String())
                igd.PonPortChannelMap.Set(ponPortID, port)
                count := port.(*PonPortChannels).GetActiveChannelCount()

                logger.Debugw(ctx, "activeChannelCount", log.Fields{"count": count})
        }
        GetApplication().UpdateActiveChannelCountForPonPort(igd.Device, uniPort, ponPortID, true, isNewChannel, igd)
        return isNewReceiver
}

// RemoveChannelFromChannelsPerPon removes the channel from the per pon channel list.
func (igd *IgmpGroupDevice) RemoveChannelFromChannelsPerPon(uniPort string, channelIP net.IP, ponPortID uint32) bool {
        logger.Debugw(ctx, "Removing channel from ActiveChannelsPerPon list", log.Fields{"PonPort": ponPortID, "channelIP": channelIP})
        var deleted bool
        ponRemoved := false

        if port, ok := igd.PonPortChannelMap.Get(ponPortID); ok {
                channelPortMap := port.(*PonPortChannels)
                deleted = channelPortMap.RemoveChannelFromMap(uniPort, channelIP.String())
                if deleted && channelPortMap.ChannelList.Length() == 0 {
                        igd.PonPortChannelMap.Remove(ponPortID)
                        ponRemoved = true
                }
                GetApplication().UpdateActiveChannelCountForPonPort(igd.Device, uniPort, ponPortID, false, deleted, igd)
        } else {
                logger.Warnw(ctx, "PON port doesn't exists in the igd", log.Fields{"PonPortID": ponPortID})
        }
        return ponRemoved
}

// printChannel to print channel info
func printChannel(key interface{}, value interface{}) bool {
        logger.Infow(ctx, "ChannelMap", log.Fields{"Channel": key.(string), "Igc": value.(*IgmpGroupChannel)})
        return true
}

// printPortChannel to print port channel
func printPortChannel(key interface{}, value interface{}) bool {
        logger.Infow(ctx, "PortChannelMap", log.Fields{"Port": key.(string), "List": value.([]net.IP)})
        return true
}


// AddReceiver add the receiver to the device and perform other actions such as adding the group
// to the physical device, add members, add flows to point the MC packets to the
// group. Also, send a IGMP report upstream if there is a change in the group
func (igd *IgmpGroupDevice) AddReceiver(cntx context.Context, port string, groupAddr net.IP,
        group *layers.IGMPv3GroupRecord, version uint8, cvlan uint16, pbit uint8, ponPortID uint32) {

        var igc *IgmpGroupChannel
        logger.Debugw(ctx, "Processing receiver for device", log.Fields{"Channel": groupAddr, "Port": port, "Device": igd.Device})

        igcIntf, ok := igd.GroupChannels.Load(groupAddr.String())
        if !ok {
                igc = NewIgmpGroupChannel(igd, groupAddr, version)
                igd.GroupChannels.Store(groupAddr.String(), igc)
        } else {
                igc = igcIntf.(*IgmpGroupChannel)
        }

        if !igd.GroupInstalled {
                igd.AddNewReceiver(cntx, port, groupAddr, group, cvlan, pbit, ponPortID)
                return
        }

        isNewReceiver := igc.AddReceiver(cntx, port, group, cvlan, pbit)
        if isNewReceiver {
                ipsList := []net.IP{}
                ipsIntf, _ := igd.PortChannelMap.Load(port)
                if ipsIntf != nil {
                        ipsList = ipsIntf.([]net.IP)
                }
                ipsList = append(ipsList, groupAddr)
                igd.PortChannelMap.Store(port, ipsList)
                logger.Debugw(ctx, "Port Channel Updated", log.Fields{"Port": port, "AddedChannelList": ipsList, "Addr": groupAddr})

                isNewPonReceiver := igd.AddChannelToChannelsPerPon(port, groupAddr, ponPortID)
                //Modify group only if this is the first time the port is subscribing for the group
                if isNewPonReceiver {
                        igd.ModMcGroup()
                }
        }
        if err := igd.WriteToDb(cntx); err != nil {
                logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
        }
}

// AddNewReceiver to add new receiver
func (igd *IgmpGroupDevice) AddNewReceiver(cntx context.Context, port string, groupAddr net.IP, group *layers.IGMPv3GroupRecord, cvlan uint16, pbit uint8, ponPortID uint32) {

        logger.Debugw(ctx, "Adding New Device Receiver", log.Fields{"Channel": groupAddr, "Port": port, "Device": igd.Device})
        igcIntf, _ := igd.GroupChannels.Load(groupAddr.String())
        if igcIntf == nil {
                logger.Warnw(ctx, "No Group Channel present for given channel", log.Fields{"Channel": groupAddr, "Port": port, "Device": igd.Device})
                return
        }

        igc := igcIntf.(*IgmpGroupChannel)
        ipsList := []net.IP{}
        ipsIntf, _ := igd.PortChannelMap.Load(port)
        if ipsIntf != nil {
                ipsList = ipsIntf.([]net.IP)
        }
        ipsList = append(ipsList, groupAddr)
        igd.PortChannelMap.Store(port, ipsList)
        igd.AddChannelToChannelsPerPon(port, groupAddr, ponPortID)
        logger.Debugw(ctx, "Port Channel Updated", log.Fields{"Port": port, "NewChannelList": ipsList, "Addr": groupAddr})

        igd.AddMcGroup()
        igc.AddReceiver(cntx, port, group, cvlan, pbit)
        if err := igd.WriteToDb(cntx); err != nil {
                logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
        }
}


// NumReceivers to get number of receivers
func (igd *IgmpGroupDevice) NumReceivers() int {
        var numReceivers int
        len := func(key interface{}, value interface{}) bool {
                numReceivers++
                return true
        }
        igd.PortChannelMap.Range(len)
        return numReceivers
}

// DelReceiver is called when Query expiry happened for a receiver. This removes the receiver from the
// the group
func (igd *IgmpGroupDevice) DelReceiver(cntx context.Context, groupAddr net.IP, port string, group *layers.IGMPv3GroupRecord, ponPortID uint32) {

        logger.Debugw(ctx, "Deleting Receiver for Device", log.Fields{"port": port, "GroupIP": groupAddr.String()})
        var igc *IgmpGroupChannel
        var igcIntf interface{}
        var ok bool
        var srcList []net.IP
        incl := false
        mvp := GetApplication().GetMvlanProfileByTag(igd.Mvlan)

        if _, ok := mvp.Proxy[igd.GroupName]; ok {
                incl = true
        } else if group != nil {
                srcList = group.SourceAddresses
                incl = isIncl(group.Type)
        }

        if igcIntf, ok = igd.GroupChannels.Load(groupAddr.String()); !ok {
                logger.Warnw(ctx, "Igmp Channel for group IP doesnt exist", log.Fields{"GroupAddr": groupAddr.String()})
                return
        }
        igc = igcIntf.(*IgmpGroupChannel)
        if ok := igc.DelReceiver(cntx, port, incl, srcList); !ok {
                return
        }

        if igc.NumReceivers() == 0 {
                igd.DelIgmpGroupChannel(cntx, igc)
        }
        igd.DelPortFromChannel(port, groupAddr)
        isGroupModified := igd.RemoveChannelFromChannelsPerPon(port, groupAddr, ponPortID)

        //Remove port from receiver if port has no subscription to any of the group channels
        if isGroupModified {
                igd.ModMcGroup()
        }
        if err := igd.WriteToDb(cntx); err != nil {
                logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
        }
}

// DelChannelReceiver is called when Query expiry happened for a receiver. This removes the receiver from the
// the group
func (igd *IgmpGroupDevice) DelChannelReceiver(cntx context.Context, groupAddr net.IP) map[string]*IgmpGroupPort {

        portsRemoved := make(map[string]*IgmpGroupPort)
        groupModified := false
        // ifEmpty := true
        igcIntf, _ := igd.GroupChannels.Load(groupAddr.String())

        if igcIntf == nil {
                return portsRemoved
        }
        igc := igcIntf.(*IgmpGroupChannel)

        for port, igp := range igc.NewReceivers {
                _ = db.DelIgmpRcvr(cntx, igc.Mvlan, igc.GroupAddr, igc.Device, port) //TODO: Y not here
                igd.DelPortFromChannel(port, igc.GroupAddr)
                ponPortID := GetApplication().GetPonPortID(igd.Device, port)
                groupModified = igd.RemoveChannelFromChannelsPerPon(port, igc.GroupAddr, ponPortID)
                delete(igc.NewReceivers, port)
                portsRemoved[port] = igp
        }
        for port, igp := range igc.CurReceivers {
                _ = db.DelIgmpRcvr(cntx, igc.Mvlan, igc.GroupAddr, igc.Device, port)
                igd.DelPortFromChannel(port, igc.GroupAddr)
                ponPortID := GetApplication().GetPonPortID(igd.Device, port)
                groupModified = igd.RemoveChannelFromChannelsPerPon(port, igc.GroupAddr, ponPortID)
                delete(igc.CurReceivers, port)
                portsRemoved[port] = igp
        }

        igc.DelMcFlow(cntx)
        igd.DelIgmpGroupChannel(cntx, igc)
        igc.Exclude = 0
        igc.SendLeaveToServer()

        if groupModified {
                igd.ModMcGroup()
        }
        if err := igd.WriteToDb(cntx); err != nil {
                logger.Errorw(ctx, "Igmp group device Write to DB failed", log.Fields{"Device": igd.Device, "GroupName": igd.GroupName, "GroupAddr": igd.GroupAddr.String()})
        }
        logger.Debugw(ctx, "Deleted the receiver Flow", log.Fields{"Num Receivers": igc.NumReceivers()})
        return portsRemoved
}

// DelIgmpGroupChannel to delete igmp group channel
func (igd *IgmpGroupDevice) DelIgmpGroupChannel(cntx context.Context, igc *IgmpGroupChannel) {

        if igc.NumReceivers() != 0 {
                igc.DelAllReceivers(cntx)
        }
        _ = db.DelIgmpChannel(cntx, igc.Mvlan, igc.GroupName, igc.Device, igc.GroupAddr)
        igd.GroupChannels.Delete(igc.GroupAddr.String())
        logger.Infow(ctx, "Deleted the Channel from Device", log.Fields{"Channel": igc.GroupAddr.String()})
        isLenZero := true
        checkIfEmpty := func(key interface{}, value interface{}) bool {
                isLenZero = false
                return false
        }
        igd.GroupChannels.Range(checkIfEmpty)
        if isLenZero {
                logger.Infow(ctx, "No more active channels. Deleting MC Group", log.Fields{"Device": igd.Device, "Group": igd.GroupName})
                igd.DelMcGroup(false)
        }
}

// func (igd *IgmpGroupDevice) DelIgmpChannel(igc *IgmpGroupChannel) {
//      db.DelIgmpChannel(igc.GroupName, igc.Device, igc.GroupAddr)
//      delete(igd.GroupChannels, igc.GroupAddr.String())
//      logger.Debugw(ctx, "Deleted the Channel", log.Fields{"Num Receivers": igc.NumReceivers()})
// }

// DelPortFromChannel to delete port from channel
func (igd *IgmpGroupDevice) DelPortFromChannel(port string, groupAddr net.IP) bool {
        ipsList := []net.IP{}
        ipsListIntf, _ := igd.PortChannelMap.Load(port)
        if ipsListIntf != nil {
                ipsList = ipsListIntf.([]net.IP)
        }
        for i, addr := range ipsList {
                if addr.Equal(groupAddr) {
                        ipsList = append(ipsList[:i], ipsList[i+1:]...)
                        //Remove port from receiver if port has no subscription to any of the group channels
                        if len(ipsList) == 0 {
                                igd.PortChannelMap.Delete(port)
                        } else {
                                //Update the map with modified ips list
                                igd.PortChannelMap.Store(port, ipsList)
                        }
                        logger.Debugw(ctx, "Port Channel Updated", log.Fields{"Port": port, "DelChannelList": ipsList, "Addr": groupAddr.String()})
                        return true
                }
        }
        return false
}

// DelAllChannels deletes all receiver for the provided igmp device
func (igd *IgmpGroupDevice) DelAllChannels(cntx context.Context) {
        logger.Infow(ctx, "Deleting All Channel for Device", log.Fields{"Device": igd.Device, "Group": igd.GroupName})
        delGroupChannels := func(key interface{}, value interface{}) bool {
                igc := value.(*IgmpGroupChannel)
                igd.DelIgmpGroupChannel(cntx, igc)
                return true
        }
        igd.GroupChannels.Range(delGroupChannels)
}

// ProcessQuery process query received from the upstream IGMP server
func (igd *IgmpGroupDevice) ProcessQuery(cntx context.Context, groupAddr net.IP, ver uint8) {
        logger.Debugw(ctx, "Received Query From Server", log.Fields{"Version": ver})
        if ver != *igd.ServVersion {
                igd.ServVersionExpiry = time.Now().Add(time.Duration(2*igd.proxyCfg.KeepAliveInterval) * time.Second)
                *igd.ServVersion = ver
                mvp := GetApplication().GetMvlanProfileByTag(igd.Mvlan)
                if err := mvp.WriteToDb(cntx); err != nil {
                        logger.Errorw(ctx, "Mvlan profile write to DB failed", log.Fields{"ProfileName": mvp.Name})
                }
        }
        if igc, ok := igd.GroupChannels.Load(groupAddr.String()); ok {
                igc.(*IgmpGroupChannel).SendReport(true)
                return
        }
        logger.Infow(ctx, "No Members for Channel. Dropping Igmp Query", log.Fields{"Group": igd.GroupName, "Channel": groupAddr.String()})
}

// AddMcGroup add the new group on the device when a receiver joins the group
func (igd *IgmpGroupDevice) AddMcGroup() {
        if !igd.GroupInstalled {
                group := &of.Group{}
                group.Command = of.GroupCommandAdd
                group.GroupID = igd.GroupID
                group.Device = igd.Device
                group.SetVlan = igd.PonVlan
                group.IsPonVlanPresent = igd.IsPonVlanPresent

                addbuckets := func(key interface{}, value interface{}) bool {
                        port := key.(string)
                        var portID uint32
                        if d := GetApplication().GetDevice(group.Device); d != nil {
                                GetApplication().portLock.Lock()
                                p := d.GetPort(port)
                                GetApplication().portLock.Unlock()
                                portID = p.ID
                        }
                        //ponPortID := key.(uint32)
                        if portID != 0xFF {
                                group.Buckets = append(group.Buckets, portID)
                        }
                        return true
                }
                igd.PortChannelMap.Range(addbuckets)

                port, _ := GetApplication().GetNniPort(igd.Device)
                _ = cntlr.GetController().GroupUpdate(port, igd.Device, group)
                igd.GroupInstalled = true
        }
}

// ModMcGroup updates the group on the device when either a receiver leaves
// or joins the group
func (igd *IgmpGroupDevice) ModMcGroup() {
        if igd.GroupInstalled {
                group := &of.Group{}
                group.Command = of.GroupCommandMod
                group.GroupID = igd.GroupID
                group.Device = igd.Device
                group.SetVlan = igd.PonVlan
                group.IsPonVlanPresent = igd.IsPonVlanPresent

                addbuckets := func(key interface{}, value interface{}) bool {
                       port := key.(string)
                       var portID uint32
                       if d := GetApplication().GetDevice(group.Device); d != nil {
                               GetApplication().portLock.Lock()
                               p := d.GetPort(port)
                               GetApplication().portLock.Unlock()
                               portID = p.ID
                       }
                       //ponPortID := key.(uint32)
                       if portID != 0xFF {
                               group.Buckets = append(group.Buckets, portID)
                        }
                        return true
                }
                igd.PortChannelMap.Range(addbuckets)

                port, _ := GetApplication().GetNniPort(igd.Device)
                _ = cntlr.GetController().GroupUpdate(port, igd.Device, group)
        } else {
                logger.Warnw(ctx, "Update Group Failed. Group not yet created", log.Fields{"Igd": igd.Device})
        }
}

// DelMcGroup : The group is deleted when the last receiver leaves the group
func (igd *IgmpGroupDevice) DelMcGroup(forceDelete bool) {

        logger.Infow(ctx, "Delete Mc Group Request", log.Fields{"Device": igd.Device, "GroupID": igd.GroupID, "ForceFlag": forceDelete, "GroupInstalled": igd.GroupInstalled})
        /*
        if !forceDelete && !checkIfForceGroupRemove(igd.Device) {
                if success := AddToPendingPool(igd.Device, igd.getKey()); success {
                        return
                }
        }*/
        if igd.GroupInstalled {
                logger.Debugw(ctx, "Deleting Group", log.Fields{"Device": igd.Device, "Id": igd.GroupID})
                group := &of.Group{}
                group.Command = of.GroupCommandDel
                group.GroupID = igd.GroupID
                group.Device = igd.Device
                group.ForceAction = true

                port, _ := GetApplication().GetNniPort(igd.Device)
                _ = cntlr.GetController().GroupUpdate(port, igd.Device, group)
                igd.GroupInstalled = false
        }
}

// QueryExpiry processes query expiry. Upon expiry, take stock of the situation
// add either retain/release the group based on number of receivers left
func (igd *IgmpGroupDevice) QueryExpiry(cntx context.Context) {
        logger.Debugw(ctx, "Query Expiry", log.Fields{"Device": igd.Device})


        // Delete the IGMP flow added for this port if port state is down or query count exceeded
        handleQueryExp := func(key interface{}, value interface{}) bool {
                igc := value.(*IgmpGroupChannel)
                for portKey, port := range igc.CurReceivers {

                        if portKey == StaticPort {
                                continue
                        }

                        logger.Warnw(ctx, "Expired Receiver Port", log.Fields{"PortKey": portKey, "IGP": port, "GroupAddr": igc.GroupAddr,
                                "Count": port.QueryTimeoutCount})
                        state, err := cntlr.GetController().GetPortState(igc.Device, portKey)
                        logger.Debugw(ctx, "Expired Member Port State", log.Fields{"state": state})
                        ponPortID := GetApplication().GetPonPortID(igd.Device, portKey)
                        if err == nil && state == cntlr.PortStateDown {
                                igd.DelReceiver(cntx, igc.GroupAddr, portKey, nil, ponPortID)
                        }

                        port.QueryTimeoutCount++
                        logger.Debugw(ctx, "Expired Port TimeoutCount", log.Fields{"count": port.QueryTimeoutCount})
                        if port.QueryTimeoutCount >= (*igc.proxyCfg).KeepAliveCount {
                                logger.Errorw(ctx, "Expiry Timeout count exceeded. Trigger delete receiver", log.Fields{"PortKey": portKey,
                                        "GroupAddr": igc.GroupAddr, "Count": port.QueryTimeoutCount})
                                igd.DelReceiver(cntx, igc.GroupAddr, portKey, nil, ponPortID)
                                SendQueryExpiredEventGroupSpecific(portKey, igd, igc)
                        } else {
                                _ = port.WriteToDb(cntx, igc.Mvlan, igc.GroupAddr, igc.Device)
                        }
                }
                return true
        }
        igd.GroupChannels.Range(handleQueryExp)
}
