package io.github.jonestimd.mockito;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.swing.event.TableModelEvent;

import com.google.common.base.Joiner;
import org.hamcrest.Description;
import org.mockito.ArgumentMatcher;
import org.mockito.Mockito;

public class Matchers {
    public static <T> Collection<T> containsOnly(final Collection<T> items) {
        final Set<T> uniqueItems = new HashSet<T>(items);
        return Mockito.argThat(new ArgumentMatcher<Collection<T>>() {
            @Override
            @SuppressWarnings("unchecked")
            public boolean matches(Object obj) {
                Set<T> arg = new HashSet<T>((Collection<T>) obj);
                return arg.size() == uniqueItems.size() && arg.containsAll(uniqueItems);
            }

            @Override
            public void describeTo(Description description) {
                description.appendText(items.toString());
            }
        });
    }

    public static <T> Stream<T> emptyStream() {
        return streamOf(Collections.emptyList());
    }

    public static <T> Stream<T> streamOf(List<T> items) {
        return Mockito.argThat(new ArgumentMatcher<Stream<T>>() {
            private final Map<Stream<T>, List<T>> streamItems = new HashMap<>();

            @Override
            @SuppressWarnings("unchecked")
            public boolean matches(Object obj) {
                List<T> arg = streamItems.computeIfAbsent((Stream<T>) obj, Matchers::collect);
                return items.equals(arg);
            }

            @Override
            public void describeTo(Description description) {
                description.appendText("Stream{" + Joiner.on(',').join(items) + "}");
            }
        });
    }

    private static <T> List<T> collect(Stream<T> stream) {
        return stream.collect(Collectors.toList());
    }

    public static TableModelEvent matches(final TableModelEvent example) {
        return Mockito.argThat(new ArgumentMatcher<TableModelEvent>() {
            @Override
            public boolean matches(Object argument) {
                TableModelEvent actual = (TableModelEvent) argument;
                return actual.getSource() == example.getSource() &&
                        actual.getType() == example.getType() &&
                        actual.getColumn() == example.getColumn() &&
                        actual.getFirstRow() == example.getFirstRow() &&
                        actual.getLastRow() == example.getLastRow();
            }
        });
    }
}

@@ -81,206 +81,37 @@
 til.
-Collections;%0Aimport java.util.HashMap;%0Aimport java.util.HashSet;%0Aimport java.util.List;%0Aimport java.util.Map;%0Aimport java.util.Set;%0Aimport java.util.stream.Collectors;%0Aimport java.util.stream.Stream
+HashSet;%0Aimport java.util.Set
 ;%0A%0Ai
@@ -156,46 +156,8 @@
 t;%0A%0A
-import com.google.common.base.Joiner;%0A
 impo
@@ -399,17 +399,16 @@
 HashSet%3C
-T
 %3E(items)
@@ -634,17 +634,16 @@
 HashSet%3C
-T
 %3E((Colle
@@ -941,906 +941,8 @@
  %7D%0A%0A
-    public static %3CT%3E Stream%3CT%3E emptyStream() %7B%0A        return streamOf(Collections.emptyList());%0A    %7D%0A%0A    public static %3CT%3E Stream%3CT%3E streamOf(List%3CT%3E items) %7B%0A        return Mockito.argThat(new ArgumentMatcher%3CStream%3CT%3E%3E() %7B%0A            private final Map%3CStream%3CT%3E, List%3CT%3E%3E streamItems = new HashMap%3C%3E();%0A%0A            @Override%0A            @SuppressWarnings(%22unchecked%22)%0A            public boolean matches(Object obj) %7B%0A                List%3CT%3E arg = streamItems.computeIfAbsent((Stream%3CT%3E) obj, Matchers::collect);%0A                return items.equals(arg);%0A            %7D%0A%0A            @Override%0A            public void describeTo(Description description) %7B%0A                description.appendText(%22Stream%7B%22 + Joiner.on(',').join(items) + %22%7D%22);%0A            %7D%0A        %7D);%0A    %7D%0A%0A    private static %3CT%3E List%3CT%3E collect(Stream%3CT%3E stream) %7B%0A        return stream.collect(Collectors.toList());%0A    %7D%0A%0A
     

Clean up unused code