package com.amplify.hiccup.service;

import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.robolectric.RobolectricTestRunner;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

@RunWith(RobolectricTestRunner.class)
public class HiccupServiceTest {

    private static final String AUTHORITY = "com.authority.name";
    private static final String ROUTE_ONE_PATH = "path/to/collection";
    private static final String ROUTE_TWO_PATH = "path/to/collection/resource";
    private static final Uri ROUTE_ONE_URI = Uri.parse("content://" + AUTHORITY + "/" + ROUTE_ONE_PATH);
    private static final Uri ROUTE_TWO_URI = Uri.parse("content://" + AUTHORITY + "/" + ROUTE_TWO_PATH);
    private static final String METHOD = "method";

    private HiccupService hiccupService;

    @Mock
    private Controller controller1;
    @Mock
    private Controller controller2;
    @Mock
    private ContentAdapter<DomainModelTest> contentAdapter;

    @Before
    public void setUp() {
        initMocks(this);
        hiccupService = new HiccupService(AUTHORITY);
    }

    @Test
    public void addMultipleRoutes() {
        hiccupService.newRoute(ROUTE_ONE_PATH, controller1);
        hiccupService.newRoute(ROUTE_TWO_PATH, controller2);

        Controller actualController1 = hiccupService.getControllerInfo(ROUTE_ONE_URI).controller;
        Controller actualController2 = hiccupService.getControllerInfo(ROUTE_TWO_URI).controller;
        assertThat(actualController1).isEqualTo(controller1);
        assertThat(actualController2).isEqualTo(controller2);
    }

    @Test
    public void addMultipleRoutesWithoutLeadingSlashToSupportPreJellyBeanMR2UriMatcher() {
        hiccupService.newRoute("/" + ROUTE_ONE_PATH, controller1);
        hiccupService.newRoute("/" + ROUTE_TWO_PATH, controller2);

        Controller actualController1 = hiccupService.getControllerInfo(ROUTE_ONE_URI).controller;
        Controller actualController2 = hiccupService.getControllerInfo(ROUTE_TWO_URI).controller;
        assertThat(actualController1).isEqualTo(controller1);
        assertThat(actualController2).isEqualTo(controller2);
    }

    @Test(expected = UnsupportedOperationException.class)
    public void throwUnsupportedOperationExceptionForNonMatchingRoute() {
        hiccupService.delegateQuery(Uri.parse("content://com.fake.authority/some/fake/path"));
    }

    @Test
    public void delegateGetRequestToMatchingControllerForRoute() {
        Cursor expectedCursor = mock(Cursor.class);
        hiccupService.newRoute(ROUTE_ONE_PATH, controller1);
        when(controller1.get(ROUTE_ONE_URI)).thenReturn(expectedCursor);

        Cursor actualCursor = hiccupService.delegateQuery(ROUTE_ONE_URI);

        assertThat(actualCursor).isEqualTo(expectedCursor);
    }

    @Test
    public void delegatePostRequestToMatchingControllerForRoute() {
        hiccupService.newRoute(ROUTE_ONE_PATH, controller1);
        ContentValues contentValues = contentValuesForPost();
        Uri expectedUri = mock(Uri.class);
        when(controller1.post(ROUTE_ONE_URI, contentValues)).thenReturn(expectedUri);

        Uri actualUri = hiccupService.delegateInsert(ROUTE_ONE_URI, contentValues);

        verify(controller1).post(ROUTE_ONE_URI, contentValues);
        assertThat(actualUri).isEqualTo(expectedUri);
    }

    @Test(expected = UnsupportedOperationException.class)
    public void throwUnsupportedOperationExceptionForUnknownMethod() {
        ContentValues contentValues = contentValuesForPost();
        contentValues.put(METHOD, "ASDF");

        hiccupService.delegateInsert(ROUTE_ONE_URI, contentValues);
    }

    private ContentValues contentValuesForPost() {
        ContentValues contentValues = new ContentValues();
        contentValues.put("method", "POST");
        return contentValues;
    }

    private static class DomainModelTest {}
}

@@ -1017,59 +1017,8 @@
 TH);
-%0A    private static final String METHOD = %22method%22;
 %0A%0A  
@@ -1186,16 +1186,20 @@
 Adapter%3C
+Some
 DomainMo
@@ -1201,20 +1201,16 @@
 ainModel
-Test
 %3E conten
@@ -3214,33 +3214,37 @@
 contentValues = 
-c
+new C
 ontentValuesForP
@@ -3231,39 +3231,32 @@
 ew ContentValues
-ForPost
 ();%0A        Uri 
@@ -3591,510 +3591,8 @@
     
-@Test(expected = UnsupportedOperationException.class)%0A    public void throwUnsupportedOperationExceptionForUnknownMethod() %7B%0A        ContentValues contentValues = contentValuesForPost();%0A        contentValues.put(METHOD, %22ASDF%22);%0A%0A        hiccupService.delegateInsert(ROUTE_ONE_URI, contentValues);%0A    %7D%0A%0A    private ContentValues contentValuesForPost() %7B%0A        ContentValues contentValues = new ContentValues();%0A        contentValues.put(%22method%22, %22POST%22);%0A        return contentValues;%0A    %7D%0A%0A    
 priv
@@ -3608,16 +3608,20 @@
 c class 
+Some
 DomainMo
@@ -3623,18 +3623,14 @@
 ainModel
-Test
  %7B%7D%0A%7D%0A

Clean up HiccupServiceTest, eg, remove useless/invalid test for HTTP METHOD