/*
 * Copyright 2019-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 meters

import (
	"context"
	"fmt"

	"github.com/opencord/voltha-lib-go/v7/pkg/log"
	ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
	tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
)

// GetTrafficShapingInfo returns CIR,PIR and GIR values
func GetTrafficShapingInfo(ctx context.Context, meterConfig *ofp.OfpMeterConfig) (*tp_pb.TrafficShapingInfo, error) {
	switch meterBandSize := len(meterConfig.Bands); {
	case meterBandSize == 1:
		band := meterConfig.Bands[0]
		if band.BurstSize == 0 { // GIR = PIR, Burst Size = 0, tcont type 1
			return &tp_pb.TrafficShapingInfo{Pir: band.Rate, Gir: band.Rate}, nil
		}
		return &tp_pb.TrafficShapingInfo{Pir: band.Rate, Pbs: band.BurstSize}, nil // PIR, tcont type 4
	case meterBandSize == 2:
		firstBand, secondBand := meterConfig.Bands[0], meterConfig.Bands[1]
		if firstBand.BurstSize == 0 && secondBand.BurstSize == 0 &&
			firstBand.Rate == secondBand.Rate { // PIR = GIR, tcont type 1
			return &tp_pb.TrafficShapingInfo{Pir: firstBand.Rate, Gir: secondBand.Rate}, nil
		}
		if firstBand.BurstSize > 0 && secondBand.BurstSize > 0 { // PIR, CIR, tcont type 2 or 3
			if firstBand.Rate > secondBand.Rate { // always PIR >= CIR
				return &tp_pb.TrafficShapingInfo{Pir: firstBand.Rate, Pbs: firstBand.BurstSize, Cir: secondBand.Rate, Cbs: secondBand.BurstSize}, nil
			}
			return &tp_pb.TrafficShapingInfo{Pir: secondBand.Rate, Pbs: secondBand.BurstSize, Cir: firstBand.Rate, Cbs: firstBand.BurstSize}, nil
		}
	case meterBandSize == 3: // PIR,CIR,GIR, tcont type 5
		var count, girIndex int
		for i, band := range meterConfig.Bands {
			if band.BurstSize == 0 { // find GIR
				count = count + 1
				girIndex = i
			}
		}
		if count == 1 {
			bands := make([]*ofp.OfpMeterBandHeader, len(meterConfig.Bands))
			copy(bands, meterConfig.Bands)
			pirCirBands := append(bands[:girIndex], bands[girIndex+1:]...)
			firstBand, secondBand := pirCirBands[0], pirCirBands[1]
			if firstBand.Rate > secondBand.Rate {
				return &tp_pb.TrafficShapingInfo{Pir: firstBand.Rate, Pbs: firstBand.BurstSize, Cir: secondBand.Rate, Cbs: secondBand.BurstSize, Gir: meterConfig.Bands[girIndex].Rate}, nil
			}
			return &tp_pb.TrafficShapingInfo{Pir: secondBand.Rate, Pbs: secondBand.BurstSize, Cir: firstBand.Rate, Cbs: firstBand.BurstSize, Gir: meterConfig.Bands[girIndex].Rate}, nil
		}
	default:
		logger.Errorw(ctx, "invalid-meter-config", log.Fields{"meter-config": meterConfig})
		return nil, fmt.Errorf("invalid-meter-config: %v", meterConfig)
	}
	return nil, fmt.Errorf("invalid-meter-config: %v", meterConfig)
}
