/*
 * 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/v7/pkg/flows"
	"github.com/opencord/voltha-lib-go/v7/pkg/log"
	ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

// listLogicalDeviceMeters returns logical device meters
func (agent *LogicalAgent) listLogicalDeviceMeters(ctx context.Context) map[uint32]*ofp.OfpMeterEntry {
	meterIDs := agent.meterLoader.ListIDs()
	meters := make(map[uint32]*ofp.OfpMeterEntry, len(meterIDs))
	for meterID := range meterIDs {
		if meterHandle, have := agent.meterLoader.Lock(meterID); have {
			meters[meterID] = meterHandle.GetReadOnly()
			meterHandle.Unlock()
		}
	}
	logger.Debugw(ctx, "list-logical-device-meters", log.Fields{"logical-device-id": agent.logicalDeviceID, "num-meters": len(meters)})
	return meters
}

// updateMeterTable updates the meter table of that logical device
func (agent *LogicalAgent) updateMeterTable(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
	logger.Debug(ctx, "updateMeterTable")
	if meterMod == nil {
		return nil
	}
	// This lock is necessary to ensure that logical-device-delete and meter operations are synchronized.
	// It was observed during tests that while meter cleanup was happening as part of logical-device delete,
	// ONOS was re-adding meters which became stale entries on the KV store.
	// It might look like a costly operation to lock the logical-device-agent for every meter operation,
	// but in practicality we have only handful number of meter profiles for a given deployment so we do
	// not expect too many meter operations.
	// We do not need such mechanism for flows, since flows are not stored on the KV store (it is only cached).
	if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
		return err
	}
	defer agent.requestQueue.RequestComplete()

	// If the logical-device-agent is stopped, return
	if agent.stopped {
		logger.Warnw(ctx, "logical-agent-stopped-not-handling-meter", log.Fields{"logical-device-id": agent.logicalDeviceID})
		return nil
	}

	switch meterMod.GetCommand() {
	case ofp.OfpMeterModCommand_OFPMC_ADD:
		return agent.meterAdd(ctx, meterMod)
	case ofp.OfpMeterModCommand_OFPMC_DELETE:
		return agent.meterDelete(ctx, meterMod)
	case ofp.OfpMeterModCommand_OFPMC_MODIFY:
		return agent.meterModify(ctx, meterMod)
	}
	return status.Errorf(codes.Internal,
		"unhandled-command: logical-device-id:%s, command:%s", agent.logicalDeviceID, meterMod.GetCommand())
}

func (agent *LogicalAgent) meterAdd(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
	if meterMod == nil {
		logger.Errorw(ctx, "failed-meterAdd-meterMod-is-nil", log.Fields{"logical-device-id": agent.logicalDeviceID})
		return nil
	}
	logger.Debugw(ctx, "meterAdd", log.Fields{"metermod": *meterMod, "logical-device-id": agent.logicalDeviceID})

	meterEntry := fu.MeterEntryFromMeterMod(ctx, meterMod)

	meterHandle, created, err := agent.meterLoader.LockOrCreate(ctx, meterEntry)
	if err != nil {
		return err
	}
	defer meterHandle.Unlock()

	if created {
		logger.Debugw(ctx, "Meter-added-successfully", log.Fields{"Added-meter": meterEntry, "logical-device-id": agent.logicalDeviceID})
	} else {
		logger.Infow(ctx, "Meter-already-exists", log.Fields{"meter": *meterMod, "logical-device-id": agent.logicalDeviceID})
	}
	return nil
}

func (agent *LogicalAgent) meterDelete(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
	if meterMod == nil {
		logger.Errorw(ctx, "failed-meterDelete-meterMod-is-nil", log.Fields{"logical-device-id": agent.logicalDeviceID})
		return nil
	}
	logger.Debug(ctx, "meterDelete", log.Fields{"meterMod": *meterMod, "logical-device-id": agent.logicalDeviceID})

	meterHandle, have := agent.meterLoader.Lock(meterMod.MeterId)
	if !have {
		logger.Warnw(ctx, "meter-not-found", log.Fields{"meterID": meterMod.MeterId, "logical-device-id": agent.logicalDeviceID})
		return nil
	}
	defer meterHandle.Unlock()

	//TODO: A meter lock is held here while flow lock(s) are acquired, if this is done in opposite order anywhere
	//      there's potential for deadlock.
	if err := agent.deleteFlowsHavingMeter(ctx, meterMod.MeterId); err != nil {
		return err
	}

	if err := meterHandle.Delete(ctx); err != nil {
		return err
	}

	logger.Debugw(ctx, "meterDelete-success", log.Fields{"meterID": meterMod.MeterId, "logical-device-id": agent.logicalDeviceID})
	return nil
}

func (agent *LogicalAgent) meterModify(ctx context.Context, meterMod *ofp.OfpMeterMod) error {
	logger.Debug(ctx, "meterModify")
	if meterMod == nil {
		logger.Errorw(ctx, "failed-meterModify-meterMod-is-nil", log.Fields{"logical-device-id": agent.logicalDeviceID})
		return nil
	}

	meterHandle, have := agent.meterLoader.Lock(meterMod.MeterId)
	if !have {
		return fmt.Errorf("no-meter-to-modify: %d, logical-device-id: %s", meterMod.MeterId, agent.logicalDeviceID)
	}
	defer meterHandle.Unlock()

	oldMeter := meterHandle.GetReadOnly()
	newMeter := fu.MeterEntryFromMeterMod(ctx, meterMod)
	newMeter.Stats.FlowCount = oldMeter.Stats.FlowCount

	if err := meterHandle.Update(ctx, newMeter); err != nil {
		return err
	}
	logger.Debugw(ctx, "replaced-with-new-meter", log.Fields{"oldMeter": oldMeter, "newMeter": newMeter, "logical-device-id": agent.logicalDeviceID})
	return nil
}
