package com.atlassian.bitbucket.util;

import org.junit.Test;

import java.util.Arrays;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;

import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

public class WeightedTest {

    private Weighted heavy = new WeightedItem(100);
    private Weighted medium = new WeightedItem(50);
    private Weighted light = new WeightedItem(10);
    private Weighted alsoLight = new WeightedItem(10);

    private Weighted weightless = new WeightedItem(-10);
    private Weighted superHeavy = new WeightedItem(Integer.MAX_VALUE);

    @Test
    public void shouldCompareLightItemLessThanHeavyItem() throws Exception {
        assertTrue(Weighted.COMPARABLE.compare(light, heavy) < 0);
    }

    @Test
    public void shouldCompareHeavyItemGreaterThanLightItem() throws Exception {
        assertTrue(Weighted.COMPARABLE.compare(heavy, light) > 0);
    }

    @Test
    public void shouldCompareEqualItemsAsEqual() throws Exception {
        assertTrue(Weighted.COMPARABLE.compare(light, alsoLight) == 0);
    }

    @Test
    public void shouldHandleExtremeWeights() throws Exception {
        // we tried an implementation that just returned weight1 - weight2, it can overflow:
        assertTrue(Weighted.COMPARABLE.compare(weightless, superHeavy) < 0);
        assertTrue(Weighted.COMPARABLE.compare(superHeavy, weightless) > 0);
    }

    @Test
    public void shouldSortFromLightestToHeaviestWhenUsedAsSortCriteria() throws Exception {
        SortedSet<Weighted> sortedSet = new TreeSet<Weighted>(Weighted.COMPARABLE);
        sortedSet.addAll(Arrays.asList(medium, heavy, light));
        Iterator<Weighted> iterator = sortedSet.iterator();

        assertSame(light, iterator.next());
        assertSame(medium, iterator.next());
        assertSame(heavy, iterator.next());
    }

    private static class WeightedItem implements Weighted {
        private final int weight;

        public WeightedItem(int weight) {
            this.weight = weight;
        }

        @Override
        public int getWeight() {
            return weight;
        }
    }
}
