/*
 * Copyright 2016-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 org.onosproject.store.primitives.resources.impl;

import static com.google.common.base.Preconditions.checkArgument;

import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;

import org.onosproject.store.service.DocumentPath;
import org.onosproject.store.service.DocumentTree;
import org.onosproject.store.service.DocumentTreeListener;
import org.onosproject.store.service.DocumentTreeNode;
import org.onosproject.store.service.IllegalDocumentModificationException;
import org.onosproject.store.service.NoSuchDocumentPathException;
import org.onosproject.store.service.Ordering;
import org.onosproject.store.service.Versioned;

import com.google.common.base.Supplier;
import com.google.common.collect.Maps;

/**
 * Simple implementation of a {@link DocumentTree}.
 *
 * @param <V> tree node value type
 */
public class DefaultDocumentTree<V> implements DocumentTree<V> {

    private static final DocumentPath ROOT_PATH = DocumentPath.from("root");
    final DefaultDocumentTreeNode<V> root;
    private final Supplier<Long> versionSupplier;

    public DefaultDocumentTree() {
        AtomicLong versionCounter = new AtomicLong(0);
        versionSupplier = versionCounter::incrementAndGet;
        root = new DefaultDocumentTreeNode<>(ROOT_PATH, null, versionSupplier.get(), Ordering.NATURAL, null);
    }

    public DefaultDocumentTree(Supplier<Long> versionSupplier, Ordering ordering) {
        root = new DefaultDocumentTreeNode<>(ROOT_PATH, null, versionSupplier.get(), ordering, null);
        this.versionSupplier = versionSupplier;
    }

    DefaultDocumentTree(Supplier<Long> versionSupplier, DefaultDocumentTreeNode<V> root) {
        this.root = root;
        this.versionSupplier = versionSupplier;
    }

    @Override
    public String name() {
        return null;
    }

    @Override
    public DocumentPath root() {
        return ROOT_PATH;
    }

    @Override
    public Map<String, Versioned<V>> getChildren(DocumentPath path) {
        DocumentTreeNode<V> node = getNode(path);
        if (node != null) {
            Map<String, Versioned<V>> childrenValues = Maps.newLinkedHashMap();
            node.children().forEachRemaining(n -> childrenValues.put(simpleName(n.path()), n.value()));
            return childrenValues;
        }
        throw new NoSuchDocumentPathException();
    }

    @Override
    public Versioned<V> get(DocumentPath path) {
        DocumentTreeNode<V> currentNode = getNode(path);
        return currentNode != null ? currentNode.value() : null;
    }

    @Override
    public Versioned<V> set(DocumentPath path, V value) {
        checkRootModification(path);
        DefaultDocumentTreeNode<V> node = getNode(path);
        if (node != null) {
            return node.update(value, versionSupplier.get());
        } else {
            create(path, value);
            return null;
        }
    }

    @Override
    public boolean create(DocumentPath path, V value) {
        checkRootModification(path);
        DocumentTreeNode<V> node = getNode(path);
        if (node != null) {
            return false;
        }
        DocumentPath parentPath = path.parent();
        DefaultDocumentTreeNode<V> parentNode =  getNode(parentPath);
        if (parentNode == null) {
            throw new IllegalDocumentModificationException();
        }
        parentNode.addChild(simpleName(path), value, versionSupplier.get());
        return true;
    }

    @Override
    public boolean createRecursive(DocumentPath path, V value) {
        checkRootModification(path);
        DocumentTreeNode<V> node = getNode(path);
        if (node != null) {
            return false;
        }
        DocumentPath parentPath = path.parent();
        if (getNode(parentPath) == null) {
            createRecursive(parentPath, null);
        }
        DefaultDocumentTreeNode<V> parentNode =  getNode(parentPath);
        if (parentNode == null) {
            throw new IllegalDocumentModificationException();
        }
        parentNode.addChild(simpleName(path), value, versionSupplier.get());
        return true;
    }

    @Override
    public boolean replace(DocumentPath path, V newValue, long version) {
        checkRootModification(path);
        DocumentTreeNode<V> node = getNode(path);
        if (node != null && node.value() != null && node.value().version() == version) {
            set(path, newValue);
            return true;
        }
        return false;
    }

    @Override
    public boolean replace(DocumentPath path, V newValue, V expectedValue) {
        checkRootModification(path);
        if (Objects.equals(newValue, expectedValue)) {
            return false;
        }
        DocumentTreeNode<V> node = getNode(path);
        V prevValue = Optional.ofNullable(node)
                    .map(DocumentTreeNode::value)
                    .map(Versioned::valueOrNull)
                    .orElse(null);
        if (Objects.equals(prevValue, expectedValue)) {
            set(path, newValue);
            return true;
        }
        return false;
    }

    @Override
    public Versioned<V> removeNode(DocumentPath path) {
        checkRootModification(path);
        DefaultDocumentTreeNode<V> nodeToRemove = getNode(path);
        if (nodeToRemove == null) {
            throw new NoSuchDocumentPathException();
        }
        if (nodeToRemove.hasChildren()) {
            throw new IllegalDocumentModificationException();
        }
        DefaultDocumentTreeNode<V> parent = (DefaultDocumentTreeNode<V>) nodeToRemove.parent();
        parent.removeChild(simpleName(path));
        return nodeToRemove.value();
    }

    @Override
    public void addListener(DocumentPath path, DocumentTreeListener<V> listener) {
        // TODO Auto-generated method stub
    }

    @Override
    public void removeListener(DocumentTreeListener<V> listener) {
        // TODO Auto-generated method stub
    }

    private DefaultDocumentTreeNode<V> getNode(DocumentPath path) {
        Iterator<String> pathElements = path.pathElements().iterator();
        DefaultDocumentTreeNode<V> currentNode = root;
        checkArgument("root".equals(pathElements.next()), "Path should start with root: %s", path);
        while (pathElements.hasNext() &&  currentNode != null) {
            currentNode = (DefaultDocumentTreeNode<V>) currentNode.child(pathElements.next());
        }
        return currentNode;
    }

    private String simpleName(DocumentPath path) {
        return path.pathElements().get(path.pathElements().size() - 1);
    }

    private void checkRootModification(DocumentPath path) {
        if (ROOT_PATH.equals(path)) {
            throw new IllegalDocumentModificationException();
        }
    }
}