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

import (
	"context"
	"fmt"
	"strconv"
	"sync"

	"github.com/opencord/voltha-go/db/model"
	"github.com/opencord/voltha-lib-go/v3/pkg/log"
	ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

// Loader hides all low-level locking & synchronization related to flow state updates
type Loader struct {
	// this lock protects the flows map, it does not protect individual flows
	lock  sync.RWMutex
	flows map[uint64]*chunk

	dbProxy         *model.Proxy
	logicalDeviceID string // TODO: dbProxy should already have the logicalDeviceID component of the path internally
}

// chunk keeps a flow and the lock for this flow
type chunk struct {
	// this lock is used to synchronize all access to the flow, and also to the "deleted" variable
	lock    sync.Mutex
	deleted bool

	flow *ofp.OfpFlowStats
}

func NewLoader(dataProxy *model.Proxy, logicalDeviceID string) *Loader {
	return &Loader{
		flows:           make(map[uint64]*chunk),
		dbProxy:         dataProxy,
		logicalDeviceID: logicalDeviceID,
	}
}

// Load queries existing flows from the kv,
// and should only be called once when first created.
func (loader *Loader) Load(ctx context.Context) {
	loader.lock.Lock()
	defer loader.lock.Unlock()

	var flows []*ofp.OfpFlowStats
	if err := loader.dbProxy.List(ctx, "logical_flows/"+loader.logicalDeviceID, &flows); err != nil {
		logger.Errorw("failed-to-list-flows-from-cluster-data-proxy", log.Fields{"error": err})
		return
	}
	for _, flow := range flows {
		loader.flows[flow.Id] = &chunk{flow: flow}
	}
}

// LockOrCreate locks this flow if it exists, or creates a new flow if it does not.
// In the case of flow creation, the provided "flow" must not be modified afterwards.
func (loader *Loader) LockOrCreate(ctx context.Context, flow *ofp.OfpFlowStats) (*Handle, bool, error) {
	// try to use read lock instead of full lock if possible
	if handle, have := loader.Lock(flow.Id); have {
		return handle, false, nil
	}

	loader.lock.Lock()
	entry, have := loader.flows[flow.Id]
	if !have {
		entry := &chunk{flow: flow}
		loader.flows[flow.Id] = entry
		entry.lock.Lock()
		loader.lock.Unlock()

		flowID := strconv.FormatUint(uint64(flow.Id), 10)
		if err := loader.dbProxy.AddWithID(ctx, "logical_flows/"+loader.logicalDeviceID, flowID, flow); err != nil {
			logger.Errorw("failed-adding-flow-to-db", log.Fields{"deviceID": loader.logicalDeviceID, "flowID": flowID, "err": err})

			// revert the map
			loader.lock.Lock()
			delete(loader.flows, flow.Id)
			loader.lock.Unlock()

			entry.deleted = true
			entry.lock.Unlock()
			return nil, false, err
		}
		return &Handle{loader: loader, chunk: entry}, true, nil
	}
	loader.lock.Unlock()

	entry.lock.Lock()
	if entry.deleted {
		entry.lock.Unlock()
		return loader.LockOrCreate(ctx, flow)
	}
	return &Handle{loader: loader, chunk: entry}, false, nil
}

// Lock acquires the lock for this flow, and returns a handle which can be used to access the meter until it's unlocked.
// This handle ensures that the flow cannot be accessed if the lock is not held.
// Returns false if the flow is not present.
// TODO: consider accepting a ctx and aborting the lock attempt on cancellation
func (loader *Loader) Lock(id uint64) (*Handle, bool) {
	loader.lock.RLock()
	entry, have := loader.flows[id]
	loader.lock.RUnlock()

	if !have {
		return nil, false
	}

	entry.lock.Lock()
	if entry.deleted {
		entry.lock.Unlock()
		return loader.Lock(id)
	}
	return &Handle{loader: loader, chunk: entry}, true
}

type Handle struct {
	loader *Loader
	chunk  *chunk
}

// GetReadOnly returns an *ofp.OfpFlowStats which MUST NOT be modified externally, but which is safe to keep indefinitely
func (h *Handle) GetReadOnly() *ofp.OfpFlowStats {
	return h.chunk.flow
}

// Update updates an existing flow in the kv.
// The provided "flow" must not be modified afterwards.
func (h *Handle) Update(ctx context.Context, flow *ofp.OfpFlowStats) error {
	path := fmt.Sprintf("logical_flows/%s/%d", h.loader.logicalDeviceID, flow.Id)
	if err := h.loader.dbProxy.Update(ctx, path, flow); err != nil {
		return status.Errorf(codes.Internal, "failed-update-flow:%s:%d %s", h.loader.logicalDeviceID, flow.Id, err)
	}
	h.chunk.flow = flow
	return nil
}

// Delete removes the device from the kv
func (h *Handle) Delete(ctx context.Context) error {
	path := fmt.Sprintf("logical_flows/%s/%d", h.loader.logicalDeviceID, h.chunk.flow.Id)
	if err := h.loader.dbProxy.Remove(ctx, path); err != nil {
		return fmt.Errorf("couldnt-delete-flow-from-store-%s", path)
	}
	h.chunk.deleted = true

	h.loader.lock.Lock()
	delete(h.loader.flows, h.chunk.flow.Id)
	h.loader.lock.Unlock()

	h.Unlock()
	return nil
}

// Unlock releases the lock on the flow
func (h *Handle) Unlock() {
	if h.chunk != nil {
		h.chunk.lock.Unlock()
		h.chunk = nil // attempting to access the flow through this handle in future will panic
	}
}

// List returns a snapshot of all the managed flow IDs
// TODO: iterating through flows safely is expensive now, since all flows are stored & locked separately
//       should avoid this where possible
func (loader *Loader) List() map[uint64]struct{} {
	loader.lock.RLock()
	defer loader.lock.RUnlock()
	// copy the IDs so caller can safely iterate
	ret := make(map[uint64]struct{}, len(loader.flows))
	for id := range loader.flows {
		ret[id] = struct{}{}
	}
	return ret
}
