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

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

// IgmpGroupPort : IGMP port implements a port which is associated with an IGMP
// version and the list of sources it implements for a given IGMP
// channel. We may improve this to have all IGMP channels so that
// we can implement per subscriber IGMP channel registration limits
// As a rule a single port cannot have both include and exclude
// lists. If we receive a include list we should purge the other
// list which is TODO
type IgmpGroupPort struct {
	Port              string
	ExcludeList       []net.IP
	IncludeList       []net.IP
	QueryTimeoutCount uint32
	PonPortID         uint32
	CVlan             uint16
	Pbit              uint8
	Version           uint8
	Exclude           bool
}

// NewIgmpGroupPort is constructor for a port
func NewIgmpGroupPort(port string, cvlan uint16, pbit uint8, version uint8, incl bool, ponPortID uint32) *IgmpGroupPort {
	var igp IgmpGroupPort
	igp.Port = port
	igp.CVlan = cvlan
	igp.Pbit = pbit
	igp.Version = version
	igp.Exclude = !incl
	igp.QueryTimeoutCount = 0
	igp.PonPortID = ponPortID
	return &igp
}

// InclSourceIsIn checks if a source is in include list
func (igp *IgmpGroupPort) InclSourceIsIn(src net.IP) bool {
	return IsIPPresent(src, igp.IncludeList)
}

// ExclSourceIsIn checks if a source is in exclude list
func (igp *IgmpGroupPort) ExclSourceIsIn(src net.IP) bool {
	return IsIPPresent(src, igp.ExcludeList)
}

// AddInclSource adds a source is in include list
func (igp *IgmpGroupPort) AddInclSource(src net.IP) {
	logger.Debugw(ctx, "Adding Include Source", log.Fields{"Port": igp.Port, "Src": src})
	igp.IncludeList = append(igp.IncludeList, src)
}

// AddExclSource adds a source is in exclude list
func (igp *IgmpGroupPort) AddExclSource(src net.IP) {
	logger.Debugw(ctx, "Adding Exclude Source", log.Fields{"Port": igp.Port, "Src": src})
	igp.ExcludeList = append(igp.ExcludeList, src)
}

// DelInclSource deletes a source is in include list
func (igp *IgmpGroupPort) DelInclSource(src net.IP) {
	logger.Debugw(ctx, "Deleting Include Source", log.Fields{"Port": igp.Port, "Src": src})
	for i, addr := range igp.IncludeList {
		if addr.Equal(src) {
			igp.IncludeList = append(igp.IncludeList[:i], igp.IncludeList[i+1:]...)
			return
		}
	}
}

// DelExclSource deletes a source is in exclude list
func (igp *IgmpGroupPort) DelExclSource(src net.IP) {
	logger.Debugw(ctx, "Deleting Exclude Source", log.Fields{"Port": igp.Port, "Src": src})
	for i, addr := range igp.ExcludeList {
		if addr.Equal(src) {
			igp.ExcludeList = append(igp.ExcludeList[:i], igp.ExcludeList[i+1:]...)
			return
		}
	}
}

// WriteToDb is utility to write IGMP Group Port Info to database
func (igp *IgmpGroupPort) WriteToDb(cntx context.Context, mvlan of.VlanType, gip net.IP, device string) error {
	b, err := json.Marshal(igp)
	if err != nil {
		return err
	}
	if err1 := db.PutIgmpRcvr(cntx, mvlan, gip, device, igp.Port, string(b)); err1 != nil {
		return err1
	}
	return nil
}

// NewIgmpGroupPortFromBytes create the IGMP group port from a byte slice
func NewIgmpGroupPortFromBytes(b []byte) (*IgmpGroupPort, error) {
	var igp IgmpGroupPort
	if err := json.Unmarshal(b, &igp); err != nil {
		logger.Warnw(ctx, "Decode of port failed", log.Fields{"str": string(b)})
		return nil, err
	}
	return &igp, nil
}
