/*
 * 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);
    }

    private static DiscreteResources of(DiscreteResource parent, Map<Class<?>, EncodedDiscreteResources> map) {
        if (isEmpty(map)) {
            return DiscreteResources.empty();
        }
        return new EncodableDiscreteResources(parent, map);
    }

    private static boolean isEmpty(Map<Class<?>, EncodedDiscreteResources> map) {
        return map.values().stream().allMatch(EncodedDiscreteResources::isEmpty);
    }

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

    @Override
    public Optional<DiscreteResource> lookup(DiscreteResourceId id) {
        if (!id.parent().filter(parent.id()::equals).isPresent()) {
            return Optional.empty();
        }
        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 = new LinkedHashMap<>();
            for (Class<?> key : this.map.keySet()) {
                EncodedDiscreteResources thisValues = this.map.get(key);
                if (!cast.map.containsKey(key)) {
                    newMap.put(key, thisValues);
                    continue;
                }
                EncodedDiscreteResources otherValues = cast.map.get(key);
                EncodedDiscreteResources diff = thisValues.difference(otherValues);
                // omit empty resources from a new resource set
                // empty EncodedDiscreteResources can't deserialize due to
                // inability to reproduce a Class<?> instance from the serialized data
                if (diff.isEmpty()) {
                    continue;
                }
                newMap.put(key, diff);
            }

            return of(parent, newMap);
        } else if (other instanceof EmptyDiscreteResources) {
            return this;
        }

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

    @Override
    public boolean isEmpty() {
        return isEmpty(map);
    }

    @Override
    public boolean containsAny(Set<DiscreteResource> other) {
        return other.stream()
                .filter(x -> map.containsKey(getClass(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 of(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();
    }
}
