#*
  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}Transformer" )
#
#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.Properties;
import java.util.Objects;
import java.util.function.BinaryOperator;
import java.util.function.UnaryOperator;
import java.util.function.Supplier;
import java.util.stream.Collectors;

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

@Generated
public class ${className} {

    private final UnaryOperator<String> transformer;

    public ${className}(UnaryOperator<String> transformer) {
        this.transformer = transformer;
    }

    /**
     * Transforms the given model
     */
    public ${root.name} visit(${root.name} target) {
        Objects.requireNonNull(target, "target cannot be null");
        return transform${root.name}(target);
    }

    /**
     * The transformation function.
     */
    protected String transform(String value) {
        return value != null ? transformer.apply(value) : null;
    }

#foreach ( $class in $model.allClasses )
  #if ( $class.name != "InputSource" && $class.name != "InputLocation" )
    #set ( $ancestors = $Helper.ancestors( $class ) )
    #set ( $allFields = $Helper.xmlFields( $class ) )
    protected ${class.name} transform${class.name}(${class.name} target) {
        if (target == null) {
            return null;
        }
        Supplier<${class.name}.Builder> creator = () -> ${class.name}.newBuilder(target);
        ${class.name}.Builder builder = null;
    #foreach ( $field in $allFields )
        builder = (${class.name}.Builder) transform${field.modelClass.name}_${Helper.capitalise($field.name)}(creator, builder, target);
    #end
        return builder != null ? builder.build() : target;
    }

    #foreach ( $field in $allFields )
      #set ( $capField = ${Helper.capitalise($field.name)} )
    protected ${class.name}.Builder transform${class.name}_${capField}(Supplier<? extends ${class.name}.Builder> creator, ${class.name}.Builder builder, ${class.name} target) {
      #if ( $field.type == "String" )
        String oldVal = target.get${capField}();
        String newVal = transform(oldVal);
        return newVal != oldVal ? (builder != null ? builder : creator.get()).${field.name}(newVal) : builder;
      #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" )
        List<String> oldVal = target.get${capField}();
        List<String> newVal = transform(oldVal, this::transform);
        return newVal != oldVal ? (builder != null ? builder : creator.get()).${field.name}(newVal) : builder;
      #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" )
        Map<String, String> props = target.get${capField}();
        Map<String, String> newProps = null;
        for (Map.Entry<String, String> entry : props.entrySet()) {
            String newVal = transform(entry.getValue());
            if (newVal != null && newVal != entry.getValue()) {
                if (newProps == null) {
                    newProps = new HashMap<>();
                    newProps.putAll(props);
                    builder = builder != null ? builder : creator.get();
                    builder.${field.name}(newProps);
                }
                newProps.put(entry.getKey(), newVal);
            }
        }
        return builder;
      #elseif ( $field.to && $field.multiplicity == "1" )
        ${field.to} oldVal = target.get${capField}();
        ${field.to} newVal = transform${field.to}(oldVal);
        return newVal != oldVal ? (builder != null ? builder : creator.get()).${field.name}(newVal) : builder;
      #elseif ( $field.to && $field.multiplicity == "*" )
        List<${field.to}> oldVal = target.get${capField}();
        List<${field.to}> newVal = transform(oldVal, this::transform${field.to});
        return newVal != oldVal ? (builder != null ? builder : creator.get()).${field.name}(newVal) : builder;
      #elseif ( $field.type == "DOM" )
        XmlNode oldVal = target.get${capField}();
        XmlNode newVal = transform(oldVal);
        return newVal != oldVal ? (builder != null ? builder : creator.get()).${field.name}(newVal) : builder;
      #elseif ( $field.type == "boolean" || $field.type == "int" || $field.type == "java.nio.file.Path" )
        // nothing to do, the transformer only handles strings
        return builder;
      #else
        // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity}
      #end
    }
    #end

  #end
#end
    protected <T> List<T> transform(List<T> list, UnaryOperator<T> transformer) {
        List<T> newList = list;
        for (int i = 0; i < list.size(); i++) {
            T oldVal = list.get(i);
            T newVal = transformer.apply(oldVal);
            if (newVal != oldVal) {
                if (newList == list) {
                    newList = new ArrayList<>(list);
                }
                newList.set(i, newVal);
            }
        }
        return newList;
    }

    protected <T> Map<String, T> transform(Map<String, T> map, UnaryOperator<T> transformer) {
        Map<String, T> newMap = map;
        for (String key : map.keySet()) {
            T oldVal = map.get(key);
            T newVal = transformer.apply(oldVal);
            if (newVal != oldVal) {
                if (newMap == map) {
                    newMap = new HashMap<>(map);
                }
                newMap.put(key, newVal);
            }
        }
        return newMap;
    }

    protected XmlNode transform(XmlNode node) {
        if (node != null) {
            String oldValue = node.value();
            String newValue = transform(oldValue);
            Map<String, String> oldAttrs = node.attributes();
            Map<String, String> newAttrs = transform(oldAttrs, this::transform);
            List<XmlNode> oldChildren = node.children();
            List<XmlNode> newChildren = transform(oldChildren, this::transform);
            if (oldValue != newValue || oldAttrs != newAttrs || oldChildren != newChildren) {
                return XmlNode.newBuilder()
                                .name(node.name())
                                .prefix(node.prefix())
                                .namespaceUri(node.namespaceUri())
                                .value(newValue)
                                .attributes(newAttrs)
                                .children(newChildren)
                                .inputLocation(node.inputLocation())
                                .build();
            }
        }
        return node;
    }
}
