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

import (
	"context"
	"errors"
	"fmt"
	"reflect"
	"strings"

	"github.com/gogo/protobuf/proto"
	"github.com/opencord/voltha-lib-go/v7/pkg/db"
	"github.com/opencord/voltha-lib-go/v7/pkg/log"
)

// RequestTimestamp attribute used to store a timestamp in the context object
const RequestTimestamp contextKey = "request-timestamp"

type contextKey string

// Path holds the information for a specific location within the data model
type Path struct {
	kvStore *db.Backend
	path    string
}

// NewDBPath returns a path to the default db location
func NewDBPath(kvStore *db.Backend) *Path {
	return &Path{kvStore: kvStore}
}

// SubPath returns a path which points to a more specific db location
func (p *Path) SubPath(path string) *Path {
	path = strings.TrimRight(strings.TrimLeft(path, "/"), "/")
	return &Path{
		kvStore: p.kvStore,
		path:    p.path + path + "/",
	}
}

// Proxy contains all the information needed to reference a specific resource within the kv
type Proxy Path

// Proxy returns a new proxy which references the specified resource
func (p *Path) Proxy(resource string) *Proxy {
	resource = strings.TrimRight(strings.TrimLeft(resource, "/"), "/")
	return &Proxy{
		kvStore: p.kvStore,
		path:    p.path + resource + "/",
	}
}

// List will retrieve information from the data model at the proxy's path location, and write it to the target slice
// target must be a type of the form *[]<proto.Message Type>  For example: *[]*voltha.Device
func (p *Proxy) KeyExists(ctx context.Context, id string) (bool, error) {
	completePath := p.path + id

	logger.Debugw(ctx, "proxy-key-exists", log.Fields{
		"path": completePath,
	})

	keyExists, err := p.kvStore.KeyExists(ctx, completePath)
	if err != nil {
		return false, fmt.Errorf("failed to retrieve %s from kvstore: %s", p.path, err)
	}
	return keyExists, nil
}

// List will retrieve information from the data model at the proxy's path location, and write it to the target slice
// target must be a type of the form *[]<proto.Message Type>  For example: *[]*voltha.Device
func (p *Proxy) List(ctx context.Context, target interface{}) error {
	logger.Debugw(ctx, "proxy-list", log.Fields{
		"path": p.path,
	})

	// verify type of target is *[]*<type>
	pointerType := reflect.TypeOf(target) // *[]*<type>
	if pointerType.Kind() != reflect.Ptr {
		return errors.New("target is not of type *[]*<type>")
	}
	sliceType := pointerType.Elem() // []*type
	if sliceType.Kind() != reflect.Slice {
		return errors.New("target is not of type *[]*<type>")
	}
	elemType := sliceType.Elem() // *type
	if sliceType.Implements(reflect.TypeOf((*proto.Message)(nil)).Elem()) {
		return errors.New("target slice does not contain elements of type proto.Message")
	}
	dataType := elemType.Elem() // type

	blobs, err := p.kvStore.List(ctx, p.path)
	if err != nil {
		return fmt.Errorf("failed to retrieve %s from kvstore: %s", p.path, err)
	}

	logger.Debugw(ctx, "parsing-data-blobs", log.Fields{
		"path": p.path,
		"size": len(blobs),
	})

	ret := reflect.MakeSlice(sliceType, len(blobs), len(blobs))
	i := 0
	for _, blob := range blobs {
		data := reflect.New(dataType)
		if err := proto.Unmarshal(blob.Value.([]byte), data.Interface().(proto.Message)); err != nil {
			return fmt.Errorf("failed to unmarshal %s: %s", blob.Key, err)
		}
		ret.Index(i).Set(data)
		i++
	}
	reflect.ValueOf(target).Elem().Set(ret)
	return nil
}

// Get will retrieve information from the data model at the proxy's path location, and write it to target
func (p *Proxy) Get(ctx context.Context, id string, target proto.Message) (bool, error) {
	completePath := p.path + id

	logger.Debugw(ctx, "proxy-get", log.Fields{
		"path": completePath,
	})

	blob, err := p.kvStore.Get(ctx, completePath)
	if err != nil {
		return false, fmt.Errorf("failed to retrieve %s from kvstore: %s", completePath, err)
	} else if blob == nil {
		return false, nil // this blob does not exist
	}

	logger.Debugw(ctx, "parsing-data-blobs", log.Fields{
		"path": completePath,
	})

	if err := proto.Unmarshal(blob.Value.([]byte), target); err != nil {
		return false, fmt.Errorf("failed to unmarshal %s: %s", blob.Key, err)
	}
	return true, nil
}

// Set will add new or update existing entry at the proxy's path location
func (p *Proxy) Set(ctx context.Context, id string, data proto.Message) error {
	completePath := p.path + id

	logger.Debugw(ctx, "proxy-add", log.Fields{
		"path": completePath,
	})

	blob, err := proto.Marshal(data)
	if err != nil {
		return fmt.Errorf("unable to save to kvStore, error marshaling: %s", err)
	}

	if err := p.kvStore.Put(ctx, completePath, blob); err != nil {
		return fmt.Errorf("unable to write to kvStore: %s", err)
	}
	return nil
}

// Remove will delete an entry at the proxy's path location
func (p *Proxy) Remove(ctx context.Context, id string) error {
	completePath := p.path + id

	logger.Debugw(ctx, "proxy-remove", log.Fields{
		"path": completePath,
	})

	if err := p.kvStore.Delete(ctx, completePath); err != nil {
		return fmt.Errorf("unable to delete %s in kvStore: %s", completePath, err)
	}
	return nil
}
