#*
  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.
*#
#parse ( "common.vm" )
#
#set ( $package = "${packageToolV4}" )
#set ( $className = "${model.name}Merger" )
#
#set ( $root = $model.getClass( $model.getRoot($version), $version ) )
#
#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java
// =================== DO NOT EDIT THIS FILE ====================
//  Generated by Modello Velocity from ${template}
//  template, any modifications will be overwritten.
// ==============================================================
package ${package};

import java.io.ObjectStreamException;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.maven.api.annotations.Generated;
import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.api.xml.XmlService;
#foreach ( $class in $model.allClasses )
import ${packageModelV4}.${class.Name};
#end

@Generated
public class ${className} {

    private final boolean deepMerge;

    public ${className}() {
        this(true);
    }

    public ${className}(boolean deepMerge) {
        this.deepMerge = deepMerge;
    }

    /**
     * Merges the specified source object into the given target object.
     *
     * @param target The target object whose existing contents should be merged with the source, must not be
     *            <code>null</code>.
     * @param source The (read-only) source object that should be merged into the target object, may be
     *            <code>null</code>.
     * @param sourceDominant A flag indicating whether either the target object or the source object provides the
     *            dominant data.
     * @param hints A set of key-value pairs that customized merger implementations can use to carry domain-specific
     *            information along, may be <code>null</code>.
     */
    public ${root.name} merge(${root.name} target, ${root.name} source, boolean sourceDominant, Map<?, ?> hints) {
        Objects.requireNonNull(target, "target cannot be null");
        if (source == null) {
            return target;
        }
        Map<Object, Object> context = new HashMap<>();
        if (hints != null) {
            context.putAll(hints);
        }
        return merge${root.name}(target, source, sourceDominant, context);
    }

#foreach ( $class in $model.allClasses )
  #if ( $class.name != "InputSource" && $class.name != "InputLocation" )
    #set ( $ancestors = $Helper.ancestors( $class ) )
    #set ( $allFields = [] )
    #foreach ( $cl in $ancestors )
      #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) )
    #end
    protected ${class.name} merge${class.name}(${class.name} target, ${class.name} source, boolean sourceDominant, Map<Object, Object> context) {
        ${class.name}.Builder builder = ${class.name}.newBuilder(target);
        merge${class.name}(builder, target, source, sourceDominant, context);
        return builder.build();
    }

    protected void merge${class.name}(${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map<Object, Object> context) {
    #if ( $class.superClass )
        merge${class.superClass}(builder, target, source, sourceDominant, context);
    #end
    #foreach ( $field in $class.getFields($version) )
        merge${field.modelClass.name}_${Helper.capitalise($field.name)}(builder, target, source, sourceDominant, context);
    #end
    }

    #foreach ( $field in $allFields )
      #set ( $capField = ${Helper.capitalise($field.name)} )
    protected void merge${class.name}_${capField}(${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map<Object, Object> context) {
      #if ( $field.type == "String" )
        String src = source.get${capField}();
        String tgt = target.get${capField}();
        if (src != null && (sourceDominant || tgt == null)) {
            builder.${field.name}(src);
        #if ( $locationTracking )
            builder.location("${field.name}", source.getLocation("${field.name}"));
        #end
        }
      #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" )
        builder.${field.name}(merge(target.get${capField}(), source.get${capField}(), sourceDominant, e -> e));
      #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" )
        Map<String, String> src = source.get${capField}();
        if (!src.isEmpty()) {
            Map<String, String> tgt = target.get${capField}();
            if (tgt.isEmpty()) {
                builder.${field.name}(src);
        #if ( $locationTracking )
                builder.location("${field.name}", source.getLocation("${field.name}"));
        #end
            } else {
                Map<String, String> merged = new HashMap<>();
                merged.putAll(sourceDominant ? target.get${capField}() : source.get${capField}());
                merged.putAll(sourceDominant ? source.get${capField}() : target.get${capField}());
                builder.${field.name}(merged);
        #if ( $locationTracking )
                builder.location("${field.name}", InputLocation.merge(target.getLocation("${field.name}"), source.getLocation("${field.name}"), sourceDominant));
        #end
            }
        }
      #elseif ( $field.to && $field.multiplicity == "1" )
        ${field.to} src = source.get${capField}();
        if (src != null) {
            ${field.to} tgt = target.get${capField}();
            if (tgt == null) {
                tgt = ${field.to}.newInstance(false);
            }
            ${field.to} merged = merge${field.to}(tgt, src, sourceDominant, context);
            builder.${field.name}(merged);
        #if ( $locationTracking )
            if (target.get${capField}() == null) {
                builder.location("${field.name}", source.getLocation("${field.name}"));
            } else if (merged != tgt) {
                builder.location("${field.name}", InputLocation.of());
            }
        #end
        }
      #elseif ( $field.to && $field.multiplicity == "*" )
        if (deepMerge) {
            builder.${field.name}(merge(target.get${capField}(), source.get${capField}(), get${field.to}Key(),
                    (t, s) -> merge${field.to}(t, s, sourceDominant, context)));
        } else {
            builder.${field.name}(merge(target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key()));
        }
      #elseif ( $field.type == "DOM" )
        XmlNode src = source.getConfiguration();
        if (src != null) {
            XmlNode tgt = target.getConfiguration();
            if (tgt == null) {
                builder.configuration(src);
        #if ( $locationTracking )
                builder.location("${field.name}", source.getLocation("configuration"));
        #end
            } else if (sourceDominant) {
                builder.configuration(XmlService.merge(src, tgt));
        #if ( $locationTracking )
                builder.location("${field.name}", target.getLocation("configuration"));
        #end
            } else {
                builder.configuration(XmlService.merge(tgt, src));
        #if ( $locationTracking )
                builder.location("${field.name}", null);
        #end
            }
        }
      #elseif ($field.type == "boolean")
        if (sourceDominant) {
            builder.${field.name}(source.is${capField}());
        }
      #elseif ($field.type == "int" || $field.type == "java.nio.file.Path")
        if (sourceDominant) {
            builder.${field.name}(source.get${capField}());
        }
      #else
        // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity}
      #end
    }
    #end

  #end
#end

#foreach ( $class in $model.allClasses )
  #if ( $class.name != "InputSource" && $class.name != "InputLocation" )
    protected KeyComputer<${class.name}> get${class.name}Key() {
        return v -> v;
    }
  #end
#end

    /**
     * Use to compute keys for data structures
     * @param <T> the data structure type
     */
    @FunctionalInterface
    public interface KeyComputer<T> extends Function<T, Object> {
    }

    /**
     * Merge two lists
     */
    public static <T> List<T> merge(List<T> tgt, List<T> src, boolean sourceDominant, KeyComputer<T> computer) {
        return merge(tgt, src, computer, (t, s) -> sourceDominant ? s : t);
    }

    public static <T> List<T> merge(List<T> tgt, List<T> src, KeyComputer<T> computer, BinaryOperator<T> remapping) {
        if (src.isEmpty()) {
            return tgt;
        }

        MergingList<T> list;
        if (tgt instanceof MergingList) {
            list = (MergingList<T>) tgt;
        } else {
            list = new MergingList<>(computer, src.size() + tgt.size());
            list.mergeAll(tgt, (t, s) -> s);
        }

        list.mergeAll(src, remapping);
        return list;
    }

    /**
     * Merging list
     * @param <V>
     */
    private static class MergingList<V> extends AbstractList<V> implements java.io.Serializable {

        private final KeyComputer<V> keyComputer;
        private Map<Object, V> map;
        private List<V> list;

        MergingList(KeyComputer<V> keyComputer, int initialCapacity) {
            this.map = new LinkedHashMap<>(initialCapacity);
            this.keyComputer = keyComputer;
        }

        Object writeReplace() throws ObjectStreamException {
            return new ArrayList<>(this);
        }

        @Override
        public Iterator<V> iterator() {
            if (map != null) {
                return map.values().iterator();
            } else {
                return list.iterator();
            }
        }

        void mergeAll(Collection<V> vs, BinaryOperator<V> remapping) {
            if (map == null) {
                map = list.stream().collect(Collectors.toMap(keyComputer,
                    Function.identity(),
                    null,
                    LinkedHashMap::new));
                list = null;
            }

            if (vs instanceof MergingList mergingList && ((MergingList<V>) vs).map != null) {
                for (Map.Entry<Object, V> e : ((MergingList<V>) vs).map.entrySet()) {
                    Object key = e.getKey();
                    V v = e.getValue();
                    map.merge(key, v, remapping);
                }
            } else {
                for (V v : vs) {
                    Object key = keyComputer.apply(v);
                    map.merge(key, v, remapping);
                }
            }
        }

        @Override
        public boolean contains(Object o) {
            if (map != null) {
                return map.containsValue(o);
            } else {
                return list.contains(o);
            }
        }

        private List<V> asList() {
            if (list == null) {
                list = new ArrayList<>(map.values());
                map = null;
            }
            return list;
        }

        @Override
        public void add(int index, V element) {
            asList().add(index, element);
        }

        @Override
        public V remove(int index) {
            return asList().remove(index);
        }

        @Override
        public V get(int index) {
            return asList().get(index);
        }

        @Override
        public int size() {
            if (map != null) {
                return map.size();
            } else {
                return list.size();
            }
        }
    }
}
