package org.batfish.datamodel.matchers;

import static org.hamcrest.Matchers.hasItem;

import com.fasterxml.jackson.core.type.TypeReference;
import java.util.Collection;
import java.util.Optional;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.batfish.datamodel.table.Row;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeDiagnosingMatcher;

final class RowMatchersImpl {

  static final class HasColumn<V> extends TypeSafeDiagnosingMatcher<Row> {
    private final Matcher<? super String> _keyMatcher;
    private final Matcher<? super V> _valueMatcher;
    private final TypeReference<V> _valueTypeReference;

    public HasColumn(
        @Nonnull Matcher<? super String> keyMatcher,
        @Nonnull Matcher<? super V> valueMatcher,
        TypeReference<V> valueTypeReference) {
      _keyMatcher = keyMatcher;
      _valueMatcher = valueMatcher;
      _valueTypeReference = valueTypeReference;
    }

    @Override
    public void describeTo(Description description) {
      description
          .appendText("A row with a column with name matching: ")
          .appendDescriptionOf(_keyMatcher)
          .appendText(" and value matching: ")
          .appendDescriptionOf(_valueMatcher);
    }

    @Override
    protected boolean matchesSafely(Row item, Description mismatchDescription) {
      Collection<String> columnNames = item.getColumnNames();
      Optional<String> columnNameOption =
          columnNames.stream().filter(_keyMatcher::matches).findFirst();
      if (!columnNameOption.isPresent()) {
        mismatchDescription.appendText("No column of row matched: ");
        hasItem(_keyMatcher).describeMismatch(columnNames, mismatchDescription);
        return false;
      }
      String columnName = columnNameOption.get();
      V value;
      try {
        value = (V) item.get(columnName, _valueTypeReference);
      } catch (Exception e) {
        mismatchDescription.appendText(
            String.format(
                "Value for column '%s' could not be converted to a '%s': %s",
                columnName,
                _valueTypeReference.getType().getTypeName(),
                ExceptionUtils.getStackTrace(e)));
        return false;
      }
      if (!_valueMatcher.matches(value)) {
        mismatchDescription.appendText(
            String.format("Value for column '%s' did not match: ", columnName));
        _valueMatcher.describeMismatch(value, mismatchDescription);
        return false;
      }
      return true;
    }
  }

  private RowMatchersImpl() {}
}

@@ -1885,12 +1885,8 @@
 ue =
- (V)
  ite

remove redundant cast