package de.fu_berlin.cdv.chasingpictures.api;

import android.app.Application;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.test.ApplicationTestCase;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.DefaultResponseErrorHandler;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;

/**
 * @author Simon
 */
public class LocationRequestTest extends ApplicationTestCase<Application> {

    private static final String TAG = "LocationRequestTest";

    public LocationRequestTest() {
        super(Application.class);
    }

    ResponseErrorHandler responseErrorHandler;
    LocationManager mLocationManager;
    //region MockLocation
    private static final String MOCK_LOCATION_PROVIDER = "MockLocationProvider";
    private static final double MOCK_LOCATION_LAT = 52.517072;
    private static final double MOCK_LOCATION_LON = 13.388873;
    //endregion

    @Override
    public void setUp() throws Exception {
        responseErrorHandler = new ResponseErrorHandler();
        mLocationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
    }

    @Override
    public void tearDown() throws Exception {

    }

    public void testLocationRequest() throws Exception {
        // Register first
        LoginRequestTest.registerUser(
                getContext(),
                "Tom",
                LoginRequestTest.getUniqueEmail(),
                "12345678"
        );

        setMockLocation(MOCK_LOCATION_LAT, MOCK_LOCATION_LON);
        Location location = mLocationManager.getLastKnownLocation(MOCK_LOCATION_PROVIDER);

        LocationRequest locationRequest = new LocationRequest(getContext(), location);
        responseErrorHandler.setExpectedStatusCode(200);
        locationRequest.getRestTemplate().setErrorHandler(responseErrorHandler);

        ResponseEntity<PlacesApiResult> result = locationRequest.sendRequest();

        List<Place> places = result.getBody().getPlaces();
        assertNotNull(places);

        // This only works if the mock location is set properly
        assertFalse(places.isEmpty());
    }

    private class ResponseErrorHandler extends DefaultResponseErrorHandler {
        private int expectedStatusCode = -1;

        public int getExpectedStatusCode() {
            return expectedStatusCode;
        }

        public void setExpectedStatusCode(int expectedStatusCode) {
            this.expectedStatusCode = expectedStatusCode;
        }

        @Override
        public void handleError(ClientHttpResponse response) throws IOException {
            HttpStatus statusCode = response.getStatusCode();
            if (expectedStatusCode != -1) // only check if we want to
                assertEquals("Invalid status code.", expectedStatusCode, statusCode.value());
        }
    }

    //region MockLocation
    public void setMockLocation(double latitude, double longitude) {
        if (mLocationManager.getProvider(MOCK_LOCATION_PROVIDER) != null) {
            mLocationManager.removeTestProvider(MOCK_LOCATION_PROVIDER);
        }

        mLocationManager.addTestProvider(
                MOCK_LOCATION_PROVIDER,
                false, // requires network
                false, // requires satellite
                false, // requires cell
                false, // has monetary cost
                false, // supports altitude
                false, // supports speed
                false, // supports bearing
                Criteria.POWER_LOW,
                Criteria.ACCURACY_FINE
        );

        Location mockLocation = new Location(MOCK_LOCATION_PROVIDER);
        mockLocation.setLatitude(latitude);
        mockLocation.setLongitude(longitude);
        mockLocation.setAccuracy(100);
        mockLocation.setTime(System.currentTimeMillis());

        //region Complete Mock Location
        Method locationJellyBeanFixMethod = null;
        try {
            locationJellyBeanFixMethod = Location.class.getMethod("makeComplete");
            if (locationJellyBeanFixMethod != null) {
                locationJellyBeanFixMethod.invoke(mockLocation);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //endregion

        mLocationManager.setTestProviderEnabled(MOCK_LOCATION_PROVIDER, true);

        mLocationManager.setTestProviderStatus(
                MOCK_LOCATION_PROVIDER,
                LocationProvider.AVAILABLE,
                null,
                System.currentTimeMillis()
        );

        mLocationManager.setTestProviderLocation(
                MOCK_LOCATION_PROVIDER,
                mockLocation
        );
    }
    //endregion
}
@@ -892,46 +892,8 @@
 er;%0A
-    LocationManager mLocationManager;%0A
     
@@ -910,24 +910,24 @@
 ockLocation%0A
+
     private 
@@ -1258,110 +1258,8 @@
 ();%0A
-        mLocationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);%0A
     
@@ -1606,43 +1606,95 @@
     
-setMockLocation(MOCK_LOCATION_LAT, 
+Location location = new Location(MOCK_LOCATION_PROVIDER);%0A        location.setLatitude(
 MOCK
@@ -1704,18 +1704,18 @@
 CATION_L
-ON
+AT
 );%0A     
@@ -1712,33 +1712,24 @@
 AT);%0A       
- 
-Location
  location = 
@@ -1729,48 +1729,21 @@
 tion
- = mLocationManager.getLastKnownLocation
+.setLongitude
 (MOC
@@ -1753,24 +1753,19 @@
 OCATION_
-PROVIDER
+LON
 );%0A%0A    
@@ -2969,1845 +2969,6 @@
   %7D%0A
-%0A    //region MockLocation%0A    public void setMockLocation(double latitude, double longitude) %7B%0A        if (mLocationManager.getProvider(MOCK_LOCATION_PROVIDER) != null) %7B%0A            mLocationManager.removeTestProvider(MOCK_LOCATION_PROVIDER);%0A        %7D%0A%0A        mLocationManager.addTestProvider(%0A                MOCK_LOCATION_PROVIDER,%0A                false, // requires network%0A                false, // requires satellite%0A                false, // requires cell%0A                false, // has monetary cost%0A                false, // supports altitude%0A                false, // supports speed%0A                false, // supports bearing%0A                Criteria.POWER_LOW,%0A                Criteria.ACCURACY_FINE%0A        );%0A%0A        Location mockLocation = new Location(MOCK_LOCATION_PROVIDER);%0A        mockLocation.setLatitude(latitude);%0A        mockLocation.setLongitude(longitude);%0A        mockLocation.setAccuracy(100);%0A        mockLocation.setTime(System.currentTimeMillis());%0A%0A        //region Complete Mock Location%0A        Method locationJellyBeanFixMethod = null;%0A        try %7B%0A            locationJellyBeanFixMethod = Location.class.getMethod(%22makeComplete%22);%0A            if (locationJellyBeanFixMethod != null) %7B%0A                locationJellyBeanFixMethod.invoke(mockLocation);%0A            %7D%0A        %7D catch (Exception e) %7B%0A            e.printStackTrace();%0A        %7D%0A        //endregion%0A%0A        mLocationManager.setTestProviderEnabled(MOCK_LOCATION_PROVIDER, true);%0A%0A        mLocationManager.setTestProviderStatus(%0A                MOCK_LOCATION_PROVIDER,%0A                LocationProvider.AVAILABLE,%0A                null,%0A                System.currentTimeMillis()%0A        );%0A%0A        mLocationManager.setTestProviderLocation(%0A                MOCK_LOCATION_PROVIDER,%0A                mockLocation%0A        );%0A    %7D%0A    //endregion%0A
 %7D
+%0A

Make LocationRequestTest use directly generated location instead of Android mock location