/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * 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.resource.impl;

import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.onosproject.net.resource.DiscreteResource;
import org.onosproject.net.resource.DiscreteResourceCodec;
import org.onosproject.net.resource.DiscreteResourceId;
import org.onosproject.net.resource.Resources;

import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * A set of discrete resources that can be encoded as integers.
 */
final class EncodableDiscreteResources implements DiscreteResources {
    private static final Codecs CODECS = Codecs.getInstance();
    private final DiscreteResource parent;
    private final Map<Class<?>, EncodedDiscreteResources> map;

    private static Class<?> getClass(DiscreteResource resource) {
        return resource.valueAs(Object.class).map(Object::getClass).get();
    }

    static DiscreteResources of(Set<DiscreteResource> resources) {
        if (resources.isEmpty()) {
            return DiscreteResources.empty();
        }

        DiscreteResource parent = resources.iterator().next().parent().get();
        return of(parent, resources);
    }

    static EncodableDiscreteResources of(DiscreteResource parent, Set<DiscreteResource> resources) {
        Map<Class<?>, Set<DiscreteResource>> grouped = resources.stream()
                .collect(Collectors.groupingBy(x -> getClass(x), Collectors.toCollection(LinkedHashSet::new)));

        Map<Class<?>, EncodedDiscreteResources> values = new LinkedHashMap<>();
        for (Map.Entry<Class<?>, Set<DiscreteResource>> entry : grouped.entrySet()) {
            DiscreteResourceCodec<?> codec = CODECS.getCodec(entry.getKey());
            values.put(entry.getKey(), EncodedDiscreteResources.of(entry.getValue(), codec));
        }

        return new EncodableDiscreteResources(parent, values);
    }

    EncodableDiscreteResources(DiscreteResource parent, Map<Class<?>, EncodedDiscreteResources> map) {
        this.parent = parent;
        this.map = map;
    }

    @Override
    public Optional<DiscreteResource> lookup(DiscreteResourceId id) {
        DiscreteResource resource = Resources.discrete(id).resource();
        Class<?> cls = getClass(resource);
        return Optional.ofNullable(map.get(cls))
                .filter(x -> x.contains(resource))
                .map(x -> resource);
    }

    @Override
    public DiscreteResources difference(DiscreteResources other) {
        if (other instanceof EncodableDiscreteResources) {
            EncodableDiscreteResources cast = (EncodableDiscreteResources) other;
            Map<Class<?>, EncodedDiscreteResources> newMap =
                    Stream.concat(this.map.entrySet().stream(), cast.map.entrySet().stream())
                            .filter(entry -> this.map.containsKey(entry.getKey()))
                            .collect(Collectors.toMap(
                                    Map.Entry::getKey,
                                    Map.Entry::getValue,
                                    EncodedDiscreteResources::difference,
                                    LinkedHashMap::new));
            return new EncodableDiscreteResources(parent, newMap);
        } else if (other instanceof EmptyDiscreteResources) {
            return this;
        }

        return DiscreteResources.of(Sets.difference(values(), other.values()));
    }

    @Override
    public boolean isEmpty() {
        return map.values().stream()
                .allMatch(x -> x.isEmpty());
    }

    @Override
    public boolean containsAny(Set<DiscreteResource> other) {
        return other.stream()
                .filter(x -> !map.containsKey(x))
                .anyMatch(x -> map.get(getClass(x)).contains(x));
    }

    @Override
    public DiscreteResources add(DiscreteResources other) {
        if (other instanceof EncodableDiscreteResources) {
            EncodableDiscreteResources cast = (EncodableDiscreteResources) other;
            LinkedHashMap<Class<?>, EncodedDiscreteResources> newMap =
                    Stream.concat(this.map.entrySet().stream(), cast.map.entrySet().stream())
                            .collect(Collectors.toMap(
                                    Map.Entry::getKey,
                                    Map.Entry::getValue,
                                    EncodedDiscreteResources::add,
                                    LinkedHashMap::new
                            ));
            return new EncodableDiscreteResources(parent, newMap);
        } else if (other instanceof EmptyDiscreteResources) {
            return this;
        }

        return DiscreteResources.of(Sets.union(this.values(), other.values()));
    }

    @Override
    public Set<DiscreteResource> values() {
        return map.values().stream()
                .flatMap(x -> x.values(parent.id()).stream())
                .collect(Collectors.toCollection(LinkedHashSet::new));
    }

    @Override
    public <T> Set<DiscreteResource> valuesOf(Class<T> cls) {
        return Optional.ofNullable(map.get(cls))
                .map(x -> x.values(parent.id()))
                .orElse(ImmutableSet.of());
    }

    DiscreteResource parent() {
        return parent;
    }

    Map<Class<?>, EncodedDiscreteResources> rawValues() {
        return map;
    }

    @Override
    public int hashCode() {
        return Objects.hash(parent, map);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        final EncodableDiscreteResources other = (EncodableDiscreteResources) obj;
        return Objects.equals(this.parent, other.parent)
                && Objects.equals(this.map, other.map);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("values", values())
                .toString();
    }
}
