/*
 * 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 (
	"github.com/opencord/voltha-go/common/log"
	"reflect"
)

func revisionsAreEqual(a, b []Revision) bool {
	// If one is nil, the other must also be nil.
	if (a == nil) != (b == nil) {
		return false
	}

	if len(a) != len(b) {
		return false
	}

	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}

	return true
}

type changeAnalysis struct {
	KeyMap1     map[reflect.Value]int
	KeyMap2     map[reflect.Value]int
	AddedKeys   map[reflect.Value]struct{}
	RemovedKeys map[reflect.Value]struct{}
	ChangedKeys map[reflect.Value]struct{}
}

func newChangeAnalysis(lst1, lst2 []Revision, keyName string) *changeAnalysis {
	changes := &changeAnalysis{}

	changes.KeyMap1 = make(map[reflect.Value]int)
	changes.KeyMap2 = make(map[reflect.Value]int)

	changes.AddedKeys = make(map[reflect.Value]struct{})
	changes.RemovedKeys = make(map[reflect.Value]struct{})
	changes.ChangedKeys = make(map[reflect.Value]struct{})

	for i, rev := range lst1 {
		_, v := GetAttributeValue(rev.GetData(), keyName, 0)
		changes.KeyMap1[v] = i
	}
	for i, rev := range lst2 {
		_, v := GetAttributeValue(rev.GetData(), keyName, 0)
		changes.KeyMap2[v] = i
	}
	for v, _ := range changes.KeyMap2 {
		if _, ok := changes.KeyMap1[v]; !ok {
			changes.AddedKeys[v] = struct{}{}
		}
	}
	for v, _ := range changes.KeyMap1 {
		if _, ok := changes.KeyMap2[v]; !ok {
			changes.RemovedKeys[v] = struct{}{}
		}
	}
	for v, _ := range changes.KeyMap1 {
		if _, ok := changes.KeyMap2[v]; ok && lst1[changes.KeyMap1[v]].GetHash() != lst2[changes.KeyMap2[v]].GetHash() {
			changes.ChangedKeys[v] = struct{}{}
		}
	}

	return changes
}

func Merge3Way(
	forkRev, srcRev, dstRev Revision,
	mergeChildFunc func(Revision) Revision,
	dryRun bool) (rev Revision, changes []ChangeTuple) {

	var configChanged bool

	if dstRev.GetConfig() == forkRev.GetConfig() {
		configChanged = dstRev.GetConfig() != srcRev.GetConfig()
	} else {
		if dstRev.GetConfig().Hash != srcRev.GetConfig().Hash {
			log.Error("config-collision")
		}
		configChanged = true
	}

	newChildren := reflect.ValueOf(dstRev.GetChildren()).Interface().(map[string][]Revision)
	childrenFields := ChildrenFields(forkRev.GetData())

	for fieldName, field := range childrenFields {
		forkList := forkRev.GetChildren()[fieldName]
		srcList := srcRev.GetChildren()[fieldName]
		dstList := dstRev.GetChildren()[fieldName]

		if revisionsAreEqual(dstList, srcList) {
			for _, rev := range srcList {
				mergeChildFunc(rev)
			}
			continue
		}

		if field.Key == "" {
			if revisionsAreEqual(dstList, forkList) {
				if !revisionsAreEqual(srcList, forkList) {
					log.Error("we should not be here")
				} else {
					for _, rev := range srcList {
						newChildren[fieldName] = append(newChildren[fieldName], mergeChildFunc(rev))
					}
					if field.IsContainer {
						changes = append(
							changes, ChangeTuple{POST_LISTCHANGE,
								NewOperationContext("", nil, fieldName, "")},
						)
					}
				}
			} else {
				if !revisionsAreEqual(srcList, forkList) {
					log.Error("cannot merge - single child node or un-keyed children list has changed")
				}
			}
		} else {
			if revisionsAreEqual(dstList, forkList) {
				src := newChangeAnalysis(forkList, srcList, field.Key)

				newList := reflect.ValueOf(srcList).Interface().([]Revision)

				for key, _ := range src.AddedKeys {
					idx := src.KeyMap2[key]
					newRev := mergeChildFunc(newList[idx])

					// FIXME: newRev may come back as nil... exclude those entries for now
					if newRev != nil {
						newList[idx] = newRev
						changes = append(changes, ChangeTuple{POST_ADD, newRev.GetData()})
					}
				}
				for key, _ := range src.RemovedKeys {
					oldRev := forkList[src.KeyMap1[key]]
					changes = append(changes, ChangeTuple{POST_REMOVE, oldRev.GetData()})
				}
				for key, _ := range src.ChangedKeys {
					idx := src.KeyMap2[key]
					newRev := mergeChildFunc(newList[idx])

					// FIXME: newRev may come back as nil... exclude those entries for now
					if newRev != nil {
						newList[idx] = newRev
					}
				}

				newChildren[fieldName] = newList
			} else {
				src := newChangeAnalysis(forkList, srcList, field.Key)
				dst := newChangeAnalysis(forkList, dstList, field.Key)

				newList := reflect.ValueOf(dstList).Interface().([]Revision)

				for key, _ := range src.AddedKeys {
					if _, exists := dst.AddedKeys[key]; exists {
						childDstRev := dstList[dst.KeyMap2[key]]
						childSrcRev := srcList[src.KeyMap2[key]]
						if childDstRev.GetHash() == childSrcRev.GetHash() {
							mergeChildFunc(childDstRev)
						} else {
							log.Error("conflict error - revision has been added is different")
						}
					} else {
						newRev := mergeChildFunc(srcList[src.KeyMap2[key]])
						newList = append(newList, newRev)
						changes = append(changes, ChangeTuple{POST_ADD, newRev.GetData()})
					}
				}
				for key, _ := range src.ChangedKeys {
					if _, removed := dst.RemovedKeys[key]; removed {
						log.Error("conflict error - revision has been removed")
					} else if _, changed := dst.ChangedKeys[key]; changed {
						childDstRev := dstList[dst.KeyMap2[key]]
						childSrcRev := srcList[src.KeyMap2[key]]
						if childDstRev.GetHash() == childSrcRev.GetHash() {
							mergeChildFunc(childSrcRev)
						} else if childDstRev.GetConfig().Hash != childSrcRev.GetConfig().Hash {
							log.Error("conflict error - revision has been changed and is different")
						} else {
							newRev := mergeChildFunc(srcList[src.KeyMap2[key]])
							newList[dst.KeyMap2[key]] = newRev
						}
					} else {
						newRev := mergeChildFunc(srcList[src.KeyMap2[key]])
						newList[dst.KeyMap2[key]] = newRev
					}
				}

				// TODO: how do i sort this map in reverse order?
				for key, _ := range src.RemovedKeys {
					if _, changed := dst.ChangedKeys[key]; changed {
						log.Error("conflict error - revision has changed")
					}
					if _, removed := dst.ChangedKeys[key]; !removed {
						dstIdx := dst.KeyMap2[key]
						oldRev := newList[dstIdx]

						copy(newList[dstIdx:], newList[dstIdx+1:])
						newList[len(newList)-1] = nil
						newList = newList[:len(newList)-1]

						changes = append(changes, ChangeTuple{POST_REMOVE, oldRev.GetData()})
					}
				}

				newChildren[fieldName] = newList

			}
		}
	}

	if !dryRun {
		if configChanged {
			rev = srcRev
		} else {
			rev = dstRev
		}

		rev = rev.UpdateAllChildren(newChildren, dstRev.GetBranch())

		if configChanged {
			changes = append(changes, ChangeTuple{POST_UPDATE, rev.GetData()})
		}
		return rev, changes
	} else {
		return nil, nil

	}
}
