package com.atlassian.bitbucket.internal.scm.git.lfs.rest.model;

import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.i18n.SimpleI18nService;
import com.atlassian.bitbucket.internal.scm.git.lfs.BadBatchRequestException;
import com.atlassian.bitbucket.internal.scm.git.lfs.model.BatchRequest;
import com.atlassian.bitbucket.internal.scm.git.lfs.model.OperationType;
import com.atlassian.bitbucket.internal.scm.git.lfs.model.RequestObject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.junit.Test;

import java.util.List;
import java.util.Map;

import static org.junit.Assert.*;

/**
 * Deep test (i.e. tests the whole JSON document) for the RestBatchRequest
 */
public class RestBatchRequestTest {

    private static final String TEST_OID1 = "7a6df2e0c99ff38b23405f28ccb092b6455975cbbc7cef1c51dc17a9f52de413";
    private static final long TEST_SIZE1 = Long.MAX_VALUE;
    private static final String TEST_OID2 = "d4fd625dfd37377fa497408df01e4bd572e3078e9c094be9fbea18c97d7e1711";
    private static final long TEST_SIZE2 = 1;

    private final I18nService i18nService = new SimpleI18nService();

    @Test
    public void testFromRest() {
        // Setup
        RestBatchRequest restRequest = createRequest();

        // Execute
        BatchRequest request = restRequest.fromRest(i18nService);

        // Verify
        assertEquals("download", request.getType().toString().toLowerCase());
        assertEquals(2, request.getObjects().size());
        RequestObject first = request.getObjects().iterator().next();
        assertEquals(TEST_OID1, first.getOid());
        assertEquals(TEST_SIZE1, first.getSize());
    }

    @Test (expected = BadBatchRequestException.class)
    public void testFromRestMissingOperation() {
        // Setup
        RestBatchRequest restRequest = createRequest();
        restRequest.remove("operation");

        // Execute
        restRequest.fromRest(i18nService);
    }

    @Test (expected = BadBatchRequestException.class)
    public void testFromRestMissingOid() {
        // Setup
        RestBatchRequest restRequest = createRequestWithObjects(ImmutableList.of(
                ImmutableMap.of("size", TEST_SIZE1)
        ));

        // Execute
        restRequest.fromRest(i18nService);
    }

    @Test (expected = BadBatchRequestException.class)
    public void testFromRestMissingSize() {
        // Setup
        RestBatchRequest restRequest = createRequestWithObjects(ImmutableList.of(
                ImmutableMap.of("oid", TEST_OID1)
        ));

        // Execute
        restRequest.fromRest(i18nService);
    }

    @SuppressWarnings({"unchecked", "MismatchedQueryAndUpdateOfCollection"})
    @Test
    public void testToRest() {
        // Setup
        BatchRequest request = new BatchRequest(OperationType.DOWNLOAD,
                ImmutableList.of(
                        new RequestObject(TEST_OID1, TEST_SIZE1),
                        new RequestObject(TEST_OID2, TEST_SIZE2)
                ));

        // Execute
        RestBatchRequest restRequest = new RestBatchRequest(request);

        // Verify
        assertEquals("download", restRequest.get("operation"));
        List<Map<String, Object>> objects = (List<Map<String, Object>>) restRequest.get("objects");
        assertEquals(2, objects.size());

        Map<String, Object> first = objects.get(0);
        assertEquals(TEST_OID1, first.get("oid"));
        assertEquals(TEST_SIZE1, first.get("size"));

        Map<String, Object> second = objects.get(1);
        assertEquals(TEST_OID2, second.get("oid"));
        assertEquals(TEST_SIZE2, second.get("size"));
    }

    private static RestBatchRequest createRequest() {
        return createRequestWithObjects(ImmutableList.of(
                ImmutableMap.of(
                        "oid", TEST_OID1,
                        "size", TEST_SIZE1),
                ImmutableMap.of(
                        "oid", TEST_OID2,
                        "size", TEST_SIZE2)
        ));
    }

    private static RestBatchRequest createRequestWithObjects(List<Map<String, Object>> objects) {
        RestBatchRequest request = new RestBatchRequest();
        request.put("operation", "download");
        request.put("objects", objects);
        return request;
    }
}