/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You 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 patch

import (
	"reflect"

	jsonpatch "github.com/evanphx/json-patch"

	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/json"
)

func PositiveMergePatch(source runtime.Object, target runtime.Object) ([]byte, error) {
	sourceJSON, err := json.Marshal(source)
	if err != nil {
		return nil, err
	}

	targetJSON, err := json.Marshal(target)
	if err != nil {
		return nil, err
	}

	mergePatch, err := jsonpatch.CreateMergePatch(sourceJSON, targetJSON)
	if err != nil {
		return nil, err
	}

	var positivePatch map[string]interface{}
	err = json.Unmarshal(mergePatch, &positivePatch)
	if err != nil {
		return nil, err
	}

	// The following is a work-around to remove null fields from the JSON merge patch,
	// so that values defaulted by controllers server-side are not deleted.
	// It's generally acceptable as these values are orthogonal to the values managed
	// by the traits.
	removeNilValues(reflect.ValueOf(positivePatch), reflect.Value{})

	// Return an empty patch if no keys remain
	if len(positivePatch) == 0 {
		return make([]byte, 0), nil
	}

	return json.Marshal(positivePatch)
}

func removeNilValues(v reflect.Value, parent reflect.Value) {
	for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
		v = v.Elem()
	}
	switch v.Kind() {
	case reflect.Array, reflect.Slice:
		for i := 0; i < v.Len(); i++ {
			removeNilValues(v.Index(i), v)
		}
	case reflect.Map:
		for _, k := range v.MapKeys() {
			switch c := v.MapIndex(k); {
			case !c.IsValid():
				// Skip keys previously deleted
				continue
			case c.IsNil(), c.Elem().Kind() == reflect.Map && len(c.Elem().MapKeys()) == 0:
				v.SetMapIndex(k, reflect.Value{})
			default:
				removeNilValues(c, v)
			}
		}
		// Back process the parent map in case it has been emptied so that it's deleted as well
		if len(v.MapKeys()) == 0 && parent.Kind() == reflect.Map {
			removeNilValues(parent, reflect.Value{})
		}
	}
}
