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

import (
	"crypto/md5"
	"errors"
	"fmt"
	"github.com/opencord/voltha-go/common/log"
	"reflect"
	"runtime"
	"strings"
)

type OperationContext struct {
	Path      string
	Data      interface{}
	FieldName string
	ChildKey  string
}

func NewOperationContext(path string, data interface{}, fieldName string, childKey string) *OperationContext {
	oc := &OperationContext{
		Path:      path,
		Data:      data,
		FieldName: fieldName,
		ChildKey:  childKey,
	}
	return oc
}

func (oc *OperationContext) Update(data interface{}) *OperationContext {
	oc.Data = data
	return oc
}

type Proxy struct {
	Root      *Root
	Node      *Node
	Path      string
	Exclusive bool
	Callbacks map[CallbackType]map[string]CallbackTuple
}

func NewProxy(root *Root, node *Node, path string, exclusive bool) *Proxy {
	callbacks := make(map[CallbackType]map[string]CallbackTuple)
	p := &Proxy{
		Root:      root,
		Node:      node,
		Exclusive: exclusive,
		Path:      path,
		Callbacks: callbacks,
	}
	return p
}

func (p *Proxy) Get(path string, depth int, deep bool, txid string) interface{} {
	return p.Node.Get(path, "", depth, deep, txid)
}

func (p *Proxy) Update(path string, data interface{}, strict bool, txid string) interface{} {
	if !strings.HasPrefix(path, "/") {
		fmt.Errorf("invalid path: %s", path)
		return nil
	}
	var fullPath string
	if path == "/" {
		fullPath = p.Path
	} else {
		fullPath = p.Path + path
	}
	return p.Root.Update(fullPath, data, strict, txid, nil)
}

func (p *Proxy) Add(path string, data interface{}, txid string) interface{} {
	if !strings.HasPrefix(path, "/") {
		fmt.Errorf("invalid path: %s", path)
		return nil
	}
	var fullPath string
	if path == "/" {
		fullPath = p.Path
	} else {
		fullPath = p.Path + path
	}
	return p.Root.Add(fullPath, data, txid, nil)
}

func (p *Proxy) Remove(path string, txid string) interface{} {
	if !strings.HasPrefix(path, "/") {
		fmt.Errorf("invalid path: %s", path)
		return nil
	}
	var fullPath string
	if path == "/" {
		fullPath = p.Path
	} else {
		fullPath = p.Path + path
	}
	return p.Root.Remove(fullPath, txid, nil)
}

func (p *Proxy) OpenTransaction() *Transaction {
	txid := p.Root.MakeTxBranch()
	return NewTransaction(p, txid)
}

func (p *Proxy) commitTransaction(txid string) {
	p.Root.FoldTxBranch(txid)
}

func (p *Proxy) cancelTransaction(txid string) {
	p.Root.DeleteTxBranch(txid)
}

//type CallbackFunction func(context context.Context, args ...interface{})
type CallbackFunction func(args ...interface{}) interface{}
type CallbackTuple struct {
	callback CallbackFunction
	args     []interface{}
}

func (tuple *CallbackTuple) Execute(context interface{}) interface{} {
	newArgs := []interface{}{}
	if context != nil {
		newArgs = append(newArgs, context)
	}
	newArgs = append(newArgs, tuple.args...)
	return tuple.callback(newArgs...)
}

func (p *Proxy) RegisterCallback(callbackType CallbackType, callback CallbackFunction, args ...interface{}) {
	if _, exists := p.Callbacks[callbackType]; !exists {
		p.Callbacks[callbackType] = make(map[string]CallbackTuple)
	}
	funcName := runtime.FuncForPC(reflect.ValueOf(callback).Pointer()).Name()
	log.Debugf("value of function: %s", funcName)
	funcHash := fmt.Sprintf("%x", md5.Sum([]byte(funcName)))[:12]

	p.Callbacks[callbackType][funcHash] = CallbackTuple{callback, args}
}

func (p *Proxy) UnregisterCallback(callbackType CallbackType, callback CallbackFunction, args ...interface{}) {
	if _, exists := p.Callbacks[callbackType]; !exists {
		log.Errorf("no such callback type - %s", callbackType.String())
		return
	}
	// TODO: Not sure if this is the best way to do it.
	funcName := runtime.FuncForPC(reflect.ValueOf(callback).Pointer()).Name()
	log.Debugf("value of function: %s", funcName)
	funcHash := fmt.Sprintf("%x", md5.Sum([]byte(funcName)))[:12]
	if _, exists := p.Callbacks[callbackType][funcHash]; !exists {
		log.Errorf("function with hash value: '%s' not registered with callback type: '%s'", funcHash, callbackType)
		return
	}
	delete(p.Callbacks[callbackType], funcHash)
}

func (p *Proxy) invoke(callback CallbackTuple, context interface{}) (result interface{}, err error) {
	defer func() {
		if r := recover(); r != nil {
			errStr := fmt.Sprintf("callback error occurred: %+v", r)
			err = errors.New(errStr)
			log.Error(errStr)
		}
	}()

	result = callback.Execute(context)

	return result, err
}

//func (p *Proxy) InvokeCallbacks(callbackType CallbackType, context context.Context, proceedOnError bool) {
func (p *Proxy) InvokeCallbacks(args ...interface{}) interface{} {
	callbackType := args[0].(CallbackType)
	context := args[1]
	proceedOnError := args[2].(bool)

	var err error

	if _, exists := p.Callbacks[callbackType]; exists {
		for _, callback := range p.Callbacks[callbackType] {
			if context, err = p.invoke(callback, context); err != nil {
				if !proceedOnError {
					log.Info("An error occurred.  Stopping callback invocation")
					break
				}
				log.Info("An error occurred.  Invoking next callback")
			}
		}
	}
	return context
}
