/*
 * 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 resourcemanager provides the utility for managing resources
package core

import (
	"github.com/opencord/voltha-lib-go/v7/pkg/log"
	ponrmgr "github.com/opencord/voltha-lib-go/v7/pkg/ponresourcemanager"
	"github.com/opencord/voltha-lib-go/v7/pkg/techprofile"
	"github.com/opencord/voltha-protos/v5/go/openolt"
	"golang.org/x/net/context"
	"sync"
)

const (
	basePathKvStore = "service/voltha"
)

// OpenOltResourceMgr holds resource related information as provided below for each field
type OpenOltResourceMgr struct {
	deviceInfo *openolt.DeviceInfo

	intfID uint32 // pon interface id

	// array of pon resource managers per interface technology
	PonRsrMgr      *ponrmgr.PONResourceManager
	TechprofileRef techprofile.TechProfileIf

	FlowIDMgmtLock sync.RWMutex

	flow_id uint64
}

// NewResourceMgr init a New resource manager instance which in turn instantiates pon resource manager
// instances according to technology. Initializes the default resource ranges for all
// the resources.
func NewResourceMgr(deviceID string, KVStoreHostPort string, kvStoreType string, deviceType string, ponID uint32, devInfo *openolt.DeviceInfo) *OpenOltResourceMgr {
	var ResourceMgr OpenOltResourceMgr
	logger.Debugf(nil, "Init new resource manager")

	ResourceMgr.deviceInfo = devInfo
	ResourceMgr.intfID = ponID
	ctx := context.Background()
	newCtx := context.WithValue(ctx, "ponIf", ponID)
	// Create a separate Resource Manager instance for each range. This assumes that
	// each technology is represented by only a single range
	for _, TechRange := range devInfo.Ranges {
		for _, intfID := range TechRange.IntfIds {
			if intfID == ponID {
				technology := TechRange.Technology
				logger.Debugf(context.Background(), "Device info technology %s, intf-id %v", technology, ponID)
				rsrMgr, err := ponrmgr.NewPONResourceManager(newCtx, technology, deviceType, deviceID,
					kvStoreType, KVStoreHostPort, basePathKvStore)
				if err != nil {
					logger.Errorf(context.Background(), "Failed to create pon resource manager instance for technology %s", technology)
					return nil
				}
				ResourceMgr.PonRsrMgr = rsrMgr
				// self.initialize_device_resource_range_and_pool(resource_mgr, global_resource_mgr, arange)
				InitializeDeviceResourceRangeAndPool(rsrMgr, TechRange, devInfo)
				if err := ResourceMgr.PonRsrMgr.InitDeviceResourcePoolForIntf(context.Background(), intfID); err != nil {
					logger.Fatal(context.Background(), "failed-to-initialize-device-resource-pool-intf-id-%v-device-id", ResourceMgr.intfID)
					return nil
				}
			}
		}
	}
	var err error
	ResourceMgr.TechprofileRef, err = techprofile.NewTechProfile(newCtx, ResourceMgr.PonRsrMgr, ResourceMgr.PonRsrMgr.Backend,
		ResourceMgr.PonRsrMgr.Address, basePathKvStore)
	if err != nil || ResourceMgr.TechprofileRef == nil {
		logger.Errorw(nil, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": ponID, "err": err})
		return nil
	}

	logger.Info(nil, "Initialization of  resource manager success!")
	return &ResourceMgr
}

// InitializeDeviceResourceRangeAndPool initializes the resource range pool according to the sharing type, then apply
// device specific information. If KV doesn't exist
// or is broader than the device, the device's information will
// dictate the range limits
func InitializeDeviceResourceRangeAndPool(ponRMgr *ponrmgr.PONResourceManager,
	techRange *openolt.DeviceInfo_DeviceResourceRanges, devInfo *openolt.DeviceInfo) {
	// var ONUIDShared, AllocIDShared, GEMPortIDShared openolt.DeviceInfo_DeviceResourceRanges_Pool_SharingType
	var ONUIDStart, ONUIDEnd, AllocIDStart, AllocIDEnd, GEMPortIDStart, GEMPortIDEnd uint32
	var ONUIDShared, AllocIDShared, GEMPortIDShared, FlowIDShared uint32

	// The below variables are just dummy and needed to pass as arguments to InitDefaultPONResourceRanges function.
	// The openolt adapter does not need flowIDs to be managed as it is managed on the OLT device
	// The UNI IDs are dynamically generated by openonu adapter for every discovered UNI.
	var flowIDDummyStart, flowIDDummyEnd uint32 = 1, 2
	var uniIDDummyStart, uniIDDummyEnd uint32 = 0, 1

	// init the resource range pool according to the sharing type
	logger.Debugw(nil, "Device info init", log.Fields{"technology": techRange.Technology,
		"onu_id_start": ONUIDStart, "onu_id_end": ONUIDEnd,
		"alloc_id_start": AllocIDStart, "alloc_id_end": AllocIDEnd,
		"gemport_id_start": GEMPortIDStart, "gemport_id_end": GEMPortIDEnd,
		"intf_ids": techRange.IntfIds,
	})
	for _, RangePool := range techRange.Pools {
		// FIXME: Remove hardcoding
		if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID {
			ONUIDStart = RangePool.Start
			ONUIDEnd = RangePool.End
			ONUIDShared = uint32(RangePool.Sharing)
		} else if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID {
			AllocIDStart = RangePool.Start
			AllocIDEnd = RangePool.End
			AllocIDShared = uint32(RangePool.Sharing)
		} else if RangePool.Type == openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID {
			GEMPortIDStart = RangePool.Start
			GEMPortIDEnd = RangePool.End
			GEMPortIDShared = uint32(RangePool.Sharing)
		}
	}

	ponRMgr.InitDefaultPONResourceRanges(nil, ONUIDStart, ONUIDEnd, ONUIDShared,
		AllocIDStart, AllocIDEnd, AllocIDShared,
		GEMPortIDStart, GEMPortIDEnd, GEMPortIDShared,
		flowIDDummyStart, flowIDDummyEnd, FlowIDShared, uniIDDummyStart, uniIDDummyEnd,
		devInfo.PonPorts, techRange.IntfIds)

}

// Delete clears used resources for the particular olt device being deleted
func (RsrcMgr *OpenOltResourceMgr) Delete() error {
	if err := RsrcMgr.PonRsrMgr.ClearDeviceResourcePool(context.Background()); err != nil {
		logger.Debug(nil, "Failed to clear device resource pool")
		return err
	}
	logger.Debug(nil, "Cleared device resource pool")
	return nil
}

// GetONUID returns the available OnuID for the given pon-port
func (RsrcMgr *OpenOltResourceMgr) GetONUID(ponIntfID uint32) (uint32, error) {
	ctx := context.Background()
	newCtx := context.WithValue(ctx, "ponIf", ponIntfID)
	// Get ONU id for a provided pon interface ID.
	onuID, err := RsrcMgr.TechprofileRef.GetResourceID(newCtx, ponIntfID,
		ponrmgr.ONU_ID, 1)
	if err != nil {
		logger.Errorf(nil, "Failed to get resource for interface %d for type %s",
			ponIntfID, ponrmgr.ONU_ID)
		return 0, err
	}
	if len(onuID) > 0 {
		return onuID[0], err
	}

	return 0, err // return onuID 0 on error
}

// GetFlowID return flow ID for a given pon interface id, onu id and uni id
func (RsrcMgr *OpenOltResourceMgr) GetFlowID(ctx context.Context, ponIntfID uint32) (uint64, error) {
	RsrcMgr.FlowIDMgmtLock.Lock()
	defer RsrcMgr.FlowIDMgmtLock.Unlock()
	RsrcMgr.flow_id++
	return RsrcMgr.flow_id, nil
}
