/*
 * 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 org.apache.camel.component.salesforce.api.dto.composite;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import org.apache.camel.component.salesforce.api.dto.AbstractDescribedSObjectBase;
import org.apache.camel.component.salesforce.api.dto.AbstractSObjectBase;
import org.apache.camel.component.salesforce.api.dto.RestError;
import org.apache.camel.component.salesforce.api.dto.SObjectDescription;
import org.apache.camel.util.ObjectHelper;

import static java.util.Objects.requireNonNull;

/**
 * Represents one node in the SObject tree request. SObject trees
 * ({@link SObjectTree}) are composed from instances of {@link SObjectNode}s.
 * Each {@link SObjectNode} contains the SObject ({@link AbstractSObjectBase})
 * and any child records linked to it. SObjects at root level are added to
 * {@link SObjectTree} using {@link SObjectTree#addObject(AbstractSObjectBase)},
 * then you can add child records on the {@link SObjectNode} returned by using
 * {@link #addChild(AbstractDescribedSObjectBase)},
 * {@link #addChildren(AbstractDescribedSObjectBase, AbstractDescribedSObjectBase...)}
 * or {@link #addChild(String, AbstractSObjectBase)} and
 * {@link #addChildren(String, AbstractSObjectBase, AbstractSObjectBase...)}.
 * <p/>
 * Upon submission to the Salesforce Composite API the {@link SObjectTree} and
 * the {@link SObjectNode}s in it might contain errors that you need to fetch
 * using {@link #getErrors()} method.
 *
 * @see SObjectTree
 * @see RestError
 */
@XStreamAlias("records")
@XStreamConverter(SObjectNodeXStreamConverter.class)
public final class SObjectNode implements Serializable {

    private static final String CHILD_PARAM = "child";

    private static final String SOBJECT_TYPE_PARAM = "type";

    private static final long serialVersionUID = 1L;

    @JsonUnwrapped
    final AbstractSObjectBase object;

    final Map<String, List<SObjectNode>> records = new HashMap<>();

    private List<RestError> errors;

    @XStreamOmitField
    private final ReferenceGenerator referenceGenerator;

    SObjectNode(final SObjectTree tree, final AbstractSObjectBase object) {
        this(tree.referenceGenerator, typeOf(object), object);
    }

    private SObjectNode(final ReferenceGenerator referenceGenerator, final String type, final AbstractSObjectBase object) {
        this.referenceGenerator = requireNonNull(referenceGenerator, "ReferenceGenerator cannot be null");
        this.object = requireNonNull(object, "Root SObject cannot be null");
        object.getAttributes().setReferenceId(referenceGenerator.nextReferenceFor(object));
    }

    static String pluralOf(final AbstractDescribedSObjectBase object) {
        final SObjectDescription description = object.description();

        return description.getLabelPlural();
    }

    static String typeOf(final AbstractDescribedSObjectBase object) {
        final SObjectDescription description = object.description();
        return description.getName();
    }

    static String typeOf(final AbstractSObjectBase object) {
        return object.getClass().getSimpleName();
    }

    /**
     * Add a described child with the metadata needed already present within it
     * to the this node.
     *
     * @param child to add
     * @return the newly created node, used in builder fashion to add more child
     *         objects to it (on the next level)
     */
    public SObjectNode addChild(final AbstractDescribedSObjectBase child) {
        ObjectHelper.notNull(child, CHILD_PARAM);

        return addChild(pluralOf(child), child);
    }

    /**
     * Add a child that does not contain the required metadata to the this node.
     * You need to specify the plural form of the child (e.g. `Account` its
     * `Accounts`).
     *
     * @param labelPlural plural form
     * @param child to add
     * @return the newly created node, used in builder fashion to add more child
     *         objects to it (on the next level)
     */
    public SObjectNode addChild(final String labelPlural, final AbstractSObjectBase child) {
        ObjectHelper.notNull(labelPlural, "labelPlural");
        ObjectHelper.notNull(child, CHILD_PARAM);

        final SObjectNode node = new SObjectNode(referenceGenerator, typeOf(child), child);

        return addChild(labelPlural, node);
    }

    /**
     * Add multiple described children with the metadata needed already present
     * within them to the this node..
     *
     * @param first first child to add
     * @param others any other children to add
     */
    public void addChildren(final AbstractDescribedSObjectBase first, final AbstractDescribedSObjectBase... others) {
        ObjectHelper.notNull(first, "first");
        ObjectHelper.notNull(others, "others");

        addChild(pluralOf(first), first);

        Arrays.stream(others).forEach(this::addChild);
    }

    /**
     * Add a child that does not contain the required metadata to the this node.
     * You need to specify the plural form of the child (e.g. `Account` its
     * `Accounts`).
     *
     * @param labelPlural plural form
     * @param first first child to add
     * @param others any other children to add
     */
    public void addChildren(final String labelPlural, final AbstractSObjectBase first, final AbstractSObjectBase... others) {
        ObjectHelper.notNull(labelPlural, "labelPlural");
        ObjectHelper.notNull(first, "first");
        ObjectHelper.notNull(others, "others");

        addChild(labelPlural, first);

        Arrays.stream(others).forEach(c -> addChild(labelPlural, c));
    }

    /**
     * Returns all children of this node (one level deep).
     *
     * @return children of this node
     */
    @JsonIgnore
    public Stream<SObjectNode> getChildNodes() {
        return records.values().stream().flatMap(List::stream);
    }

    /**
     * Returns all children of this node (one level deep) of certain type (in
     * plural form).
     *
     * @param type type of child requested in plural form (e.g for `Account` is
     *            `Accounts`)
     * @return children of this node of specified type
     */
    public Stream<SObjectNode> getChildNodesOfType(final String type) {
        ObjectHelper.notNull(type, SOBJECT_TYPE_PARAM);

        return records.getOrDefault(type, Collections.emptyList()).stream();
    }

    /**
     * Returns child SObjects of this node (one level deep).
     *
     * @return child SObjects of this node
     */
    @JsonIgnore
    public Stream<AbstractSObjectBase> getChildren() {
        return records.values().stream().flatMap(List::stream).map(SObjectNode::getObject);
    }

    /**
     * Returns child SObjects of this node (one level deep) of certain type (in
     * plural form)
     *
     * @param type type of child requested in plural form (e.g for `Account` is
     *            `Accounts`)
     * @return child SObjects of this node
     */
    public Stream<AbstractSObjectBase> getChildrenOfType(final String type) {
        ObjectHelper.notNull(type, SOBJECT_TYPE_PARAM);

        return records.getOrDefault(type, Collections.emptyList()).stream().map(SObjectNode::getObject);
    }

    /**
     * Errors reported against this this node received in response to the
     * SObject tree being submitted.
     *
     * @return errors for this node
     */
    @JsonIgnore
    public List<RestError> getErrors() {
        return Optional.ofNullable(errors).orElse(Collections.emptyList());
    }

    /**
     * SObject at this node.
     *
     * @return SObject
     */
    @JsonIgnore
    public AbstractSObjectBase getObject() {
        return object;
    }

    /**
     * Are there any errors resulted from the submission on this node?
     *
     * @return true if there are errors
     */
    public boolean hasErrors() {
        return errors != null && !errors.isEmpty();
    }

    /**
     * Size of the branch beginning with this node (number of SObjects in it).
     *
     * @return number of objects within this branch
     */
    public int size() {
        return 1 + records.values().stream().flatMapToInt(r -> r.stream().mapToInt(SObjectNode::size)).sum();
    }

    @Override
    public String toString() {
        return "Node<" + getObjectType() + ">";
    }

    SObjectNode addChild(final String labelPlural, final SObjectNode node) {
        List<SObjectNode> children = records.get(labelPlural);
        if (children == null) {
            children = new ArrayList<>();
            records.put(labelPlural, children);
        }

        children.add(node);

        return node;
    }

    @JsonAnyGetter
    Map<String, Map<String, List<SObjectNode>>> children() {
        return records.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> Collections.singletonMap("records", e.getValue())));
    }

    @JsonIgnore
    String getObjectType() {
        return object.getAttributes().getType();
    }

    Stream<Class> objectTypes() {
        return Stream.concat(Stream.of((Class)object.getClass()), getChildNodes().flatMap(SObjectNode::objectTypes));
    }

    void setErrors(final List<RestError> errors) {
        this.errors = errors;
    }
}
