package it.com.atlassian.stash.rest.admin.backups;

import com.atlassian.bitbucket.test.DefaultFuncTestData;
import com.jayway.restassured.RestAssured;
import it.com.atlassian.stash.BaseRestTest;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.Test;

import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class BackupControllerTest extends BaseRestTest {

    @Test
    public void getFeaturesTest() {
        RestAssured
            .given()
                .auth().preemptive().basic(DefaultFuncTestData.getAdminUser(), DefaultFuncTestData.getAdminPassword())
                .contentType(MediaType.APPLICATION_JSON)
            .expect()
                .statusCode(200)
                .content("", hasFeature("core", "backup-support", "BACKUP"))
                .content("", hasFeature("web", "json", "BACKUP"))
                .content("", hasFeature("forks", "alternates", "BOTH"))
                .content("", hasFeature("database", "FillInRootCommentsChange", "RESTORE"))
                .content("", doesNotHaveFeature("database", "AbstractCustomChange", "RESTORE"))
            .when()
                .get(DefaultFuncTestData.getBaseURL() + "/admin/backups?features");
    }

    private static Matcher<?> hasFeature(final String group, final String name, final String mode) {
        return new BaseMatcher<Object>() {
            @Override
            public boolean matches(Object item) {
                @SuppressWarnings("unchecked")
                ArrayList<Map<String, String>> features = (ArrayList<Map<String, String>>) item;
                return listHasFeature(features, group, name, mode);
            }

            @Override
            public void describeTo(Description description) {
                description.appendText("lacks the feature " + name + ", " + mode);
            }
        };
    }

    private static Matcher<?> doesNotHaveFeature(final String group, final String name, final String mode) {
        return new BaseMatcher<Object>() {
            @Override
            public boolean matches(Object item) {
                @SuppressWarnings("unchecked")
                ArrayList<Map<String, String>> features = (ArrayList<Map<String, String>>) item;
                return !listHasFeature(features, group, name, mode);
            }

            @Override
            public void describeTo(Description description) {
                description.appendText("includes the illegal feature " + name + ", " + mode);
            }
        };
    }

    private static boolean listHasFeature(List<Map<String, String>> features, String group, String name, String mode) {
        for (Map<String, String> feature : features) {
            if (feature.get("group").equals(group) && feature.get("name").equals(name) && feature.get("mode").equals(mode)) {
                return true;
            }
        }
        return false;
    }
}
