/*
 * 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.DiscreteDomain;
import com.google.common.collect.Range;
import com.google.common.collect.RangeSet;
import com.google.common.collect.TreeRangeSet;
import org.onlab.util.Tools;
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.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

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

/**
 * Represents discrete resources encoded by a codec.
 */
final class EncodedDiscreteResources {
    private final RangeSet<Integer> rangeSet;
    private final DiscreteResourceCodec codec;

    EncodedDiscreteResources(RangeSet<Integer> rangeSet, DiscreteResourceCodec codec) {
        this.rangeSet = rangeSet;
        this.codec = codec;
    }

    static EncodedDiscreteResources of(Set<DiscreteResource> resources, DiscreteResourceCodec codec) {
        RangeSet<Integer> rangeSet = TreeRangeSet.create();
        resources.stream()
                .map(x -> x.valueAs(Object.class))
                .flatMap(Tools::stream)
                .map(x -> codec.encode(x))
                .map(Range::singleton)
                .map(x -> x.canonical(DiscreteDomain.integers()))
                .forEach(rangeSet::add);

        return new EncodedDiscreteResources(rangeSet, codec);
    }

    RangeSet<Integer> rangeSet() {
        return rangeSet;
    }

    DiscreteResourceCodec codec() {
        return codec;
    }

    Set<DiscreteResource> values(DiscreteResourceId parent) {
        return rangeSet.asRanges().stream()
                .flatMapToInt(x1 -> IntStream.range(x1.lowerEndpoint(), x1.upperEndpoint()))
                .boxed()
                .map(x -> codec.decode(x))
                .map(x -> Resources.discrete(parent, x).resource())
                .collect(Collectors.toCollection(LinkedHashSet::new));
    }

    @SuppressWarnings("unchecked")
    boolean contains(DiscreteResource resource) {
        return resource.valueAs(Object.class)
                .map(x -> codec.encode(x))
                .map(rangeSet::contains)
                .orElse(false);
    }

    EncodedDiscreteResources difference(EncodedDiscreteResources other) {
        checkArgument(this.codec.getClass() == other.codec.getClass());

        RangeSet<Integer> newRangeSet = TreeRangeSet.create(this.rangeSet);
        newRangeSet.removeAll(other.rangeSet);

        return new EncodedDiscreteResources(newRangeSet, this.codec);
    }

    boolean isEmpty() {
        return rangeSet.isEmpty();
    }

    @Override
    public int hashCode() {
        return Objects.hash(rangeSet, codec);
    }

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

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