package com.atlassian.stash.internal.scm.git.protocol.http;

import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.scm.http.HttpScmRequest;
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

import javax.annotation.Nonnull;

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

/**
 * Type-safe Hamcrest matchers for {@link HttpScmRequest} instances.
 */
public class HttpScmRequestMatchers {
    @Factory
    public static Matcher<HttpScmRequest> smartWrite() {
        return new IsSmartWrite();
    }

    static class IsSmartWrite extends TypeSafeMatcher<HttpScmRequest> {
        @Override
        public boolean matchesSafely(HttpScmRequest request) {
            return (request instanceof GitSmartRequest) && asSmartRequest(request).isWrite();
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("a 'smart' write operation");
        }
    }

    @Factory
    public static Matcher<HttpScmRequest> smartRead() {
        return new IsSmartRead();
    }

    static class IsSmartRead extends TypeSafeMatcher<HttpScmRequest> {
        @Override
        public boolean matchesSafely(HttpScmRequest request) {
            return (request instanceof GitSmartRequest) && !asSmartRequest(request).isWrite();
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("a 'smart' read operation");
        }
    }

    @Factory
    public static Matcher<HttpScmRequest> hasRepo(@Nonnull Repository repository) {
        return new HasRepo(repository);
    }

    static class HasRepo extends TypeSafeMatcher<HttpScmRequest> {
        @Nonnull private final Repository repository;

        HasRepo(@Nonnull Repository repository) {
            this.repository = checkNotNull(repository, "repository");
        }

        @Override
        public boolean matchesSafely(HttpScmRequest request) {
            return repository.equals(request.getRepository());
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("has repository");
        }
    }

    /** Just to put the yucky cast out of the way */
    private static GitSmartRequest asSmartRequest(HttpScmRequest scmRequest) {
        return (GitSmartRequest) scmRequest;
    }
}
