/*
 * 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 (
	desc "github.com/golang/protobuf/descriptor"
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/protoc-gen-go/descriptor"
	"github.com/opencord/voltha-go/common/log"
	"github.com/opencord/voltha-go/protos/common"
	"reflect"
	"strconv"
	"sync"
)

type singleton struct {
	ChildrenFieldsCache map[interface{}]map[string]*ChildType
}

var instance *singleton
var once sync.Once

func GetInstance() *singleton {
	once.Do(func() {
		instance = &singleton{}
	})
	return instance
}

type ChildType struct {
	ClassModule string
	ClassType   reflect.Type
	IsContainer bool
	Key         string
	KeyFromStr  func(s string) interface{}
}

func ChildrenFields(cls interface{}) map[string]*ChildType {
	if cls == nil {
		return nil
	}
	var names map[string]*ChildType
	var names_exist bool

	if GetInstance().ChildrenFieldsCache == nil {
		GetInstance().ChildrenFieldsCache = make(map[interface{}]map[string]*ChildType)
	}

	msgType := reflect.TypeOf(cls)

	inst := GetInstance()

	if names, names_exist = inst.ChildrenFieldsCache[msgType.String()]; !names_exist {
		names = make(map[string]*ChildType)

		_, md := desc.ForMessage(cls.(desc.Message))

		// TODO: Do we need to validate MD for nil, panic or exception?
		for _, field := range md.Field {
			if options := field.GetOptions(); options != nil {
				if proto.HasExtension(options, common.E_ChildNode) {
					isContainer := *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
					meta, _ := proto.GetExtension(options, common.E_ChildNode)

					var keyFromStr func(string) interface{}
					var ct ChildType

					parentType := FindOwnerType(reflect.ValueOf(cls), field.GetName(), 0, false)
					if meta.(*common.ChildNode).GetKey() != "" {
						keyType := FindKeyOwner(reflect.New(parentType).Elem().Interface(), meta.(*common.ChildNode).GetKey(), 0)

						switch keyType.(reflect.Type).Name() {
						case "string":
							keyFromStr = func(s string) interface{} {
								return s
							}
						case "int32":
							keyFromStr = func(s string) interface{} {
								i, _ := strconv.Atoi(s)
								return int32(i)
							}
						case "int64":
							keyFromStr = func(s string) interface{} {
								i, _ := strconv.Atoi(s)
								return int64(i)
							}
						case "uint32":
							keyFromStr = func(s string) interface{} {
								i, _ := strconv.Atoi(s)
								return uint32(i)
							}
						case "uint64":
							keyFromStr = func(s string) interface{} {
								i, _ := strconv.Atoi(s)
								return uint64(i)
							}
						default:
							log.Errorf("Key type not implemented - type: %s\n", keyType.(reflect.Type))
						}
					}

					ct = ChildType{
						ClassModule: parentType.String(),
						ClassType:   parentType,
						IsContainer: isContainer,
						Key:         meta.(*common.ChildNode).GetKey(),
						KeyFromStr:  keyFromStr,
					}

					names[field.GetName()] = &ct
				}
			}
		}

		GetInstance().ChildrenFieldsCache[msgType.String()] = names
	}

	return names
}
