/*
 * Copyright 2018-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 device

import (
	"context"
	"fmt"

	fu "github.com/opencord/voltha-lib-go/v5/pkg/flows"
	"github.com/opencord/voltha-lib-go/v5/pkg/log"
	ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
)

// GetMeterConfig returns meters which which are used by the given flows
func (agent *LogicalAgent) GetMeterConfig(ctx context.Context, flows []*ofp.OfpFlowStats) (map[uint32]*ofp.OfpMeterConfig, error) {
	metersConfig := make(map[uint32]*ofp.OfpMeterConfig)
	for _, flow := range flows {
		if flowMeterID := fu.GetMeterIdFromFlow(flow); flowMeterID != 0 {
			if _, have := metersConfig[flowMeterID]; !have {
				// Meter is present in the flow, Get from logical device
				meterHandle, have := agent.meterCache.Lock(flowMeterID)
				if !have {
					logger.Errorw(ctx, "Meter-referred-by-flow-is-not-found-in-logicaldevice",
						log.Fields{"meterID": flowMeterID, "Available-meters": metersConfig, "flow": *flow})
					return nil, fmt.Errorf("Meter-referred-by-flow-is-not-found-in-logicaldevice.MeterId-%d", flowMeterID)
				}

				meter := meterHandle.GetReadOnly()
				metersConfig[flowMeterID] = meter.Config
				logger.Debugw(ctx, "Found meter in logical device", log.Fields{"meterID": flowMeterID, "meter-band": meter.Config})

				meterHandle.Unlock()
			}
		}
	}
	logger.Debugw(ctx, "meter-bands-for-flows", log.Fields{"flows": len(flows), "meters": metersConfig})
	return metersConfig, nil
}

// updateFlowCountOfMeterStats updates the number of flows associated with this meter
func (agent *LogicalAgent) updateFlowCountOfMeterStats(ctx context.Context, modCommand *ofp.OfpFlowMod, flow *ofp.OfpFlowStats, revertUpdate bool) bool {
	flowCommand := modCommand.GetCommand()
	meterID := fu.GetMeterIdFromFlow(flow)
	logger.Debugw(ctx, "Meter-id-in-flow-mod", log.Fields{"meterId": meterID})
	if meterID == 0 {
		logger.Debugw(ctx, "No-meter-present-in-the-flow", log.Fields{"flow": *flow})
		return true
	}

	if flowCommand != ofp.OfpFlowModCommand_OFPFC_ADD && flowCommand != ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
		return true
	}

	meterHandle, have := agent.meterCache.Lock(meterID)
	if !have {
		logger.Debugw(ctx, "Meter-is-not-present-in-logical-device", log.Fields{"meterID": meterID})
		return true
	}
	defer meterHandle.Unlock()

	oldMeter := meterHandle.GetReadOnly()
	// avoiding using proto.Clone by only copying what have changed (this assumes that the oldMeter will never be modified)
	newStats := *oldMeter.Stats
	if flowCommand == ofp.OfpFlowModCommand_OFPFC_ADD {
		if revertUpdate {
			newStats.FlowCount--
		} else {
			newStats.FlowCount++
		}
	} else if flowCommand == ofp.OfpFlowModCommand_OFPFC_DELETE_STRICT {
		if revertUpdate {
			newStats.FlowCount++
		} else {
			newStats.FlowCount--
		}
	}

	newMeter := &ofp.OfpMeterEntry{
		Config: oldMeter.Config,
		Stats:  &newStats,
	}
	if err := meterHandle.Update(ctx, newMeter); err != nil {
		logger.Debugw(ctx, "unable-to-update-meter-in-db", log.Fields{"logical-device-id": agent.logicalDeviceID, "meterID": meterID})
		return false
	}

	logger.Debugw(ctx, "updated-meter-flow-stats", log.Fields{"meterId": meterID})
	return true
}
