/*
 * Copyright 2020-2023 Open Networking Foundation (ONF) and the ONF Contributors
 *
 * 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 ponresourcemanager

import (
	"context"
	"encoding/json"
	"errors"
	"github.com/boljen/go-bitmap"
	"strings"
	"testing"
	"time"

	"github.com/opencord/voltha-lib-go/v7/pkg/db"
	"github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
	"github.com/opencord/voltha-lib-go/v7/pkg/log"
	"github.com/stretchr/testify/assert"
)

const (
	GEM_POOL_PATH        = "gemport_id_pool"
	RESERVED_GEM_PORT_ID = uint32(5)
)

// MockKVClient mocks the AdapterProxy interface.
type MockResKVClient struct {
	resourceMap map[string]interface{}
}

func newMockKvClient(ctx context.Context) *MockResKVClient {
	var mockResKVClient MockResKVClient
	mockResKVClient.resourceMap = make(map[string]interface{})
	return &mockResKVClient
}

// List function implemented for KVClient.
func (kvclient *MockResKVClient) List(ctx context.Context, key string) (map[string]*kvstore.KVPair, error) {
	return nil, errors.New("key didn't find")
}

// Get mock function implementation for KVClient
func (kvclient *MockResKVClient) Get(ctx context.Context, key string) (*kvstore.KVPair, error) {
	logger.Debugw(ctx, "Get of MockKVClient called", log.Fields{"key": key})
	if key != "" {
		if strings.Contains(key, RESERVED_GEMPORT_IDS_PATH) {
			logger.Debug(ctx, "Getting Key:", RESERVED_GEMPORT_IDS_PATH)
			reservedGemPorts := []uint32{RESERVED_GEM_PORT_ID}
			str, _ := json.Marshal(reservedGemPorts)
			return kvstore.NewKVPair(key, str, "mock", 3000, 1), nil
		}
		if strings.Contains(key, GEM_POOL_PATH) {
			logger.Debug(ctx, "Getting Key:", GEM_POOL_PATH)
			resource := kvclient.resourceMap[key]
			return kvstore.NewKVPair(key, resource, "mock", 3000, 1), nil
		}
		maps := make(map[string]*kvstore.KVPair)
		maps[key] = &kvstore.KVPair{Key: key}
		return maps[key], nil
	}
	return nil, errors.New("key didn't find")
}

// Put mock function implementation for KVClient
func (kvclient *MockResKVClient) Put(ctx context.Context, key string, value interface{}) error {
	if key != "" {
		if strings.Contains(key, GEMPORT_ID_POOL_PATH) && value != nil {
			kvclient.resourceMap[key] = value
		}
		return nil
	}
	return errors.New("key didn't find")
}

// Delete mock function implementation for KVClient
func (kvclient *MockResKVClient) Delete(ctx context.Context, key string) error {
	return nil
}

func (c *MockResKVClient) DeleteWithPrefix(ctx context.Context, prefixKey string) error {
	return nil
}

// Reserve mock function implementation for KVClient
func (kvclient *MockResKVClient) Reserve(ctx context.Context, key string, value interface{}, ttl time.Duration) (interface{}, error) {
	return nil, errors.New("key didn't find")
}

// ReleaseReservation mock function implementation for KVClient
func (kvclient *MockResKVClient) ReleaseReservation(ctx context.Context, key string) error {
	return nil
}

// ReleaseAllReservations mock function implementation for KVClient
func (kvclient *MockResKVClient) ReleaseAllReservations(ctx context.Context) error {
	return nil
}

// RenewReservation mock function implementation for KVClient
func (kvclient *MockResKVClient) RenewReservation(ctx context.Context, key string) error {
	return nil
}

// Watch mock function implementation for KVClient
func (kvclient *MockResKVClient) Watch(ctx context.Context, key string, withPrefix bool) chan *kvstore.Event {
	return nil
}

// AcquireLock mock function implementation for KVClient
func (kvclient *MockResKVClient) AcquireLock(ctx context.Context, lockName string, timeout time.Duration) error {
	return nil
}

// ReleaseLock mock function implementation for KVClient
func (kvclient *MockResKVClient) ReleaseLock(lockName string) error {
	return nil
}

// IsConnectionUp mock function implementation for KVClient
func (kvclient *MockResKVClient) IsConnectionUp(ctx context.Context) bool { // timeout in second
	return true
}

// CloseWatch mock function implementation for KVClient
func (kvclient *MockResKVClient) CloseWatch(ctx context.Context, key string, ch chan *kvstore.Event) {
}

// Close mock function implementation for KVClient
func (kvclient *MockResKVClient) Close(ctx context.Context) {
}

func TestExcludeReservedGemPortIdFromThePool(t *testing.T) {
	ctx := context.Background()
	PONRMgr, err := NewPONResourceManager(ctx, "gpon", "onu", "olt1",
		"etcd", "1:1", "service/voltha")
	if err != nil {
		return
	}
	PONRMgr.KVStore = &db.Backend{
		Client: newMockKvClient(ctx),
	}

	PONRMgr.KVStoreForConfig = &db.Backend{
		Client: newMockKvClient(ctx),
	}
	// create a pool in the range of [1,16]
	// and exclude id 5 from this pool
	StartIndex := uint32(1)
	EndIndex := uint32(16)

	reservedGemPortIds, defined := PONRMgr.getReservedGemPortIdsFromKVStore(ctx)
	if !defined {
		return
	}

	FormatResult, err := PONRMgr.FormatResource(ctx, 1, StartIndex, EndIndex, reservedGemPortIds)
	if err != nil {
		t.Error("Failed to format resource", err)
		return
	}

	// Add resource as json in kv store.
	err = PONRMgr.KVStore.Put(ctx, GEMPORT_ID_POOL_PATH, FormatResult)
	if err != nil {
		t.Error("Error in posting data to kv store", GEMPORT_ID_POOL_PATH)
		return
	}

	for i := StartIndex; i <= (EndIndex - uint32(len(reservedGemPortIds))); i++ {
		// get gem port id pool from the kv store
		resource, err := PONRMgr.GetResource(context.Background(), GEMPORT_ID_POOL_PATH)
		if err != nil {
			t.Error("Failed to get resource from gem port id pool", err)
			return
		}
		// get a gem port id from the pool
		nextID, err := PONRMgr.GenerateNextID(ctx, resource)
		if err != nil {
			t.Error("Failed to get gem port id from the pool", err)
			return
		}

		//given gem port id should not equal to the reserved gem port id
		assert.NotEqual(t, nextID, RESERVED_GEM_PORT_ID)
		// put updated gem port id pool into the kv store
		err = PONRMgr.UpdateResource(context.Background(), GEMPORT_ID_POOL_PATH, resource)
		if err != nil {
			t.Error("Failed to put updated gem port id pool into the kv store", err)
			return
		}
	}

}

func TestResourcePoolOverflow(t *testing.T) {
	ctx := context.Background()
	PONRMgr, err := NewPONResourceManager(ctx, "gpon", "onu", "olt1",
		"etcd", "1:1", "service/voltha")
	if err != nil {
		return
	}
	PONRMgr.KVStore = &db.Backend{
		Client: newMockKvClient(ctx),
	}

	PONRMgr.KVStoreForConfig = &db.Backend{
		Client: newMockKvClient(ctx),
	}
	// create a pool in the range of [1,16]
	StartIndex := uint32(1)
	EndIndex := uint32(16)

	FormatResult, err := PONRMgr.FormatResource(ctx, 1, StartIndex, EndIndex, []uint32{})
	if err != nil {
		t.Error("Failed to format resource", err)
		return
	}

	// Add resource as json in kv store.
	err = PONRMgr.KVStore.Put(ctx, GEMPORT_ID_POOL_PATH, FormatResult)
	if err != nil {
		t.Error("Error in posting data to kv store", GEMPORT_ID_POOL_PATH)
		return
	}

	for i := 1; i <= 20; i++ {
		// get gem port id pool from the kv store
		resource, err := PONRMgr.GetResource(context.Background(), GEMPORT_ID_POOL_PATH)
		if err != nil {
			t.Error("Failed to get resource from gem port id pool", err)
			return
		}
		// get a gem port id from the pool
		nextID, err := PONRMgr.GenerateNextID(ctx, resource)
		// all free ids in the pool will be consumed by the first 16 steps of the loop
		// resource-exhausted error is expected from the pool at the 17th step of the loop
		if i > int(EndIndex) {
			assert.NotNil(t, err)
		} else if err != nil {
			t.Error("Failed to get gem port id from the pool", err)
			return
		} else {
			assert.NotEqual(t, 0, nextID)
			// put updated gem port id pool into the kv store
			err = PONRMgr.UpdateResource(context.Background(), GEMPORT_ID_POOL_PATH, resource)
			if err != nil {
				t.Error("Failed to put updated gem port id pool into the kv store", err)
				return
			}
		}
	}
}

func TestPONResourceManager_ReleaseInvalidID(t *testing.T) {
	ctx := context.Background()
	PONRMgr, err := NewPONResourceManager(ctx, "gpon", "onu", "olt1",
		"etcd", "1:1", "service/voltha")
	if err != nil {
		return
	}
	PONRMgr.KVStore = &db.Backend{
		Client: newMockKvClient(ctx),
	}

	PONRMgr.KVStoreForConfig = &db.Backend{
		Client: newMockKvClient(ctx),
	}
	// create a pool in the range of [1,16]
	StartIndex := uint32(1)
	EndIndex := uint32(16)

	FormatResult, err := PONRMgr.FormatResource(ctx, 1, StartIndex, EndIndex, []uint32{})
	if err != nil {
		t.Error("Failed to format resource", err)
		return
	}

	// Add resource as json in kv store.
	err = PONRMgr.KVStore.Put(ctx, GEMPORT_ID_POOL_PATH, FormatResult)
	if err != nil {
		t.Error("Error in posting data to kv store", GEMPORT_ID_POOL_PATH)
		return
	}

	// get gem port id pool from the kv store
	resource, err := PONRMgr.GetResource(context.Background(), GEMPORT_ID_POOL_PATH)
	if err != nil {
		t.Error("Failed to get resource from gem port id pool", err)
		return
	}
	//try to release an ID whose value is out of the boundaries of the pool and expect false
	released := PONRMgr.ReleaseID(ctx, resource, uint32(EndIndex+1))
	assert.Equal(t, false, released)
}

func TestPONResourceManager_ReserveInvalidID(t *testing.T) {
	ctx := context.Background()
	PONRMgr, err := NewPONResourceManager(ctx, "gpon", "onu", "olt1",
		"etcd", "1:1", "service/voltha")
	if err != nil {
		return
	}
	PONRMgr.KVStore = &db.Backend{
		Client: newMockKvClient(ctx),
	}

	PONRMgr.KVStoreForConfig = &db.Backend{
		Client: newMockKvClient(ctx),
	}
	// create a pool in the range of [1,16]
	StartIndex := uint32(1)
	EndIndex := uint32(16)

	FormatResult, err := PONRMgr.FormatResource(ctx, 1, StartIndex, EndIndex, []uint32{})
	if err != nil {
		t.Error("Failed to format resource", err)
		return
	}

	// Add resource as json in kv store.
	err = PONRMgr.KVStore.Put(ctx, GEMPORT_ID_POOL_PATH, FormatResult)
	if err != nil {
		t.Error("Error in posting data to kv store", GEMPORT_ID_POOL_PATH)
		return
	}
	// get gem port id pool from the kv store
	resource, err := PONRMgr.GetResource(context.Background(), GEMPORT_ID_POOL_PATH)
	if err != nil {
		t.Error("Failed to get resource from gem port id pool", err)
		return
	}
	ByteArray, err := ToByte(resource[POOL])
	if err != nil {
		t.Error(ctx, "Failed to convert resource to byte array")
		return
	}
	Data := bitmap.TSFromData(ByteArray, false)
	if Data == nil {
		t.Error(ctx, "Failed to get resource pool")
		return
	}
	//try to reserve an ID whose value is out of the boundaries of the pool and expect false
	reserved := PONRMgr.reserveID(ctx, Data, StartIndex, EndIndex+1)
	assert.Equal(t, false, reserved)
}
