/*
 * 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 (
	"bytes"
	"crypto/md5"
	"fmt"
	"reflect"
	"sort"
)

var (
	RevisionCache = make(map[string]interface{})
)

type Revision struct {
	Config   *DataRevision
	Children map[string][]*Revision
	Hash     string
	branch   *Branch
	WeakRef  string
}

func NewRevision(branch *Branch, data interface{}, children map[string][]*Revision) *Revision {
	cr := &Revision{}
	cr.branch = branch
	cr.Config = NewDataRevision(data)
	cr.Children = children
	cr.finalize()

	return cr
}

func (cr *Revision) finalize() {
	cr.Hash = cr.hashContent()

	if _, exists := RevisionCache[cr.Hash]; !exists {
		RevisionCache[cr.Hash] = cr
	}
	if _, exists := RevisionCache[cr.Config.Hash]; !exists {
		RevisionCache[cr.Config.Hash] = cr.Config
	} else {
		cr.Config = RevisionCache[cr.Config.Hash].(*DataRevision)
	}
}

func (cr *Revision) hashContent() string {
	var buffer bytes.Buffer
	var childrenKeys []string

	if cr.Config != nil {
		buffer.WriteString(cr.Config.Hash)
	}

	for key, _ := range cr.Children {
		childrenKeys = append(childrenKeys, key)
	}
	sort.Strings(childrenKeys)

	if cr.Children != nil && len(cr.Children) > 0 {
		// Loop through sorted Children keys
		for _, key := range childrenKeys {
			for _, child := range cr.Children[key] {
				buffer.WriteString(child.Hash)
			}
		}
	}

	return fmt.Sprintf("%x", md5.Sum(buffer.Bytes()))[:12]
}

func (cr *Revision) getData() interface{} {
	if cr.Config == nil {
		return nil
	}
	return cr.Config.Data
}

func (cr *Revision) getNode() *Node {
	return cr.branch.node
}

func (cr *Revision) getType() reflect.Type {
	// TODO: what is this returning really?
	return reflect.TypeOf(cr.getData())
}

func (cr *Revision) clearHash() {
	cr.Hash = ""
}

func (cr *Revision) Get(depth int) interface{} {
	originalData := cr.getData()
	data := Clone(originalData)

	if depth > 0 {
		for fieldName, field := range ChildrenFields(cr.getType()) {
			if field.IsContainer {
				for _, rev := range cr.Children[fieldName] {
					childData := rev.Get(depth - 1)
					childDataHolder := GetAttributeValue(data, fieldName, 0)
					// TODO: merge with childData
					fmt.Printf("data:%+v, dataHolder:%+v", childData, childDataHolder)
				}
			} else {
				rev := cr.Children[fieldName][0]
				childData := rev.Get(depth - 1)
				childDataHolder := GetAttributeValue(data, fieldName, 0)
				// TODO: merge with childData
				fmt.Printf("data:%+v, dataHolder:%+v", childData, childDataHolder)
			}
		}
	}
	return data
}

func (cr *Revision) UpdateData(data interface{}, branch *Branch) *Revision {
	newRev := Clone(cr).(*Revision)
	newRev.branch = branch
	newRev.Config = data.(*DataRevision)
	newRev.finalize()

	return newRev
}

func (cr *Revision) UpdateChildren(name string, children []*Revision, branch *Branch) *Revision {
	newChildren := Clone(cr.Children).(map[string][]*Revision)
	newChildren[name] = children
	newRev := Clone(cr).(*Revision)
	newRev.branch = branch
	newRev.Children = newChildren
	newRev.finalize()

	return newRev
}

func (cr *Revision) UpdateAllChildren(children map[string][]*Revision, branch *Branch) *Revision {
	newRev := Clone(cr).(*Revision)
	newRev.branch = branch
	newRev.Children = children
	newRev.finalize()

	return newRev
}
