/*
 * Copyright (C) 2004-2017, GoodData(R) Corporation. All rights reserved.
 * This source code is licensed under the BSD-style license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */
package com.gooddata.util;

import com.gooddata.GoodData;
import com.gooddata.GoodDataRestException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.io.IOException;

import static com.gooddata.util.ResourceUtils.OBJECT_MAPPER;
import static com.gooddata.util.ResourceUtils.readFromResource;
import static java.util.Collections.singletonList;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class ResponseErrorHandlerTest {

    private ResponseErrorHandler responseErrorHandler;

    @BeforeMethod
    public void setUp() throws Exception {
        responseErrorHandler = new ResponseErrorHandler(singletonList(new MappingJackson2HttpMessageConverter(OBJECT_MAPPER)));
    }

    @Test
    public void testHandleGdcError() throws Exception {
        final ClientHttpResponse response = prepareResponse("/gdc/gdcError.json");

        final GoodDataRestException exc = assertException(response);

        assertThat("GoodDataRestException should have been thrown!", exc, is(notNullValue()));
        assertThat(exc.getStatusCode(), is(500));
        assertThat(exc.getRequestId(), is("REQ"));
        assertThat(exc.getComponent(), is("COMPONENT"));
        assertThat(exc.getErrorClass(), is("CLASS"));
        assertThat(exc.getErrorCode(), is("CODE"));
        assertThat(exc.getText(), is("MSG"));
    }

    @Test
    public void testHandleErrorStructure() throws Exception {
        final ClientHttpResponse response = prepareResponse("/gdc/errorStructure.json");

        final GoodDataRestException exc = assertException(response);

        assertThat("GoodDataRestException should have been thrown!", exc, is(notNullValue()));
        assertThat(exc.getStatusCode(), is(500));
        assertThat(exc.getRequestId(), is("REQ"));
        assertThat(exc.getComponent(), is("COMPONENT"));
        assertThat(exc.getErrorClass(), is("CLASS"));
        assertThat(exc.getErrorCode(), is("CODE"));
        assertThat(exc.getText(), is("MSG PARAM1 PARAM2 3"));
    }

    @Test
    public void testHandleInvalidError() throws Exception {
        final ClientHttpResponse response = prepareResponse("/gdc/invalidError.json");

        final GoodDataRestException exc = assertException(response);

        assertThat("GoodDataRestException should have been thrown!", exc, is(notNullValue()));
        assertThat(exc.getStatusCode(), is(500));
        assertThat(exc.getRequestId(), is("requestId"));
        assertThat(exc.getComponent(), is(nullValue()));
        assertThat(exc.getErrorClass(), is(nullValue()));
        assertThat(exc.getErrorCode(), is(nullValue()));
        assertThat(exc.getText(), is(nullValue()));
    }

    private ClientHttpResponse prepareResponse(String resourcePath) throws IOException {
        final ClientHttpResponse response = mock(ClientHttpResponse.class);
        when(response.getStatusCode()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR);
        when(response.getRawStatusCode()).thenReturn(500);
        final HttpHeaders headers = new HttpHeaders();
        headers.set(GoodData.GDC_REQUEST_ID_HEADER, "requestId");
        headers.setContentType(MediaType.APPLICATION_JSON);
        when(response.getHeaders()).thenReturn(headers);
        when(response.getBody()).thenReturn(readFromResource(resourcePath));

        return response;
    }

    private GoodDataRestException assertException(ClientHttpResponse response) {
        try {
            responseErrorHandler.handleError(response);
            throw new AssertionError("Expected GoodDataRestException");
        } catch (GoodDataRestException e) {
            return e;
        }
    }

}
@@ -1687,80 +1687,55 @@
 hat(
-%22GoodDataRestException should have been thrown!%22, exc, is(notNullValue()
+exc.getMessage(), is(%22500: %5BrequestId=REQ%5D MSG%22
 ));%0A
@@ -2306,80 +2306,71 @@
 hat(
-%22GoodDataRestException should have been thrown!%22, exc, is(notNullValue()
+exc.getMessage(), is(%22500: %5BrequestId=REQ%5D MSG PARAM1 PARAM2 3%22
 ));%0A
@@ -2953,80 +2953,71 @@
 hat(
-%22GoodDataRestException should have been thrown!%22, exc, is(notNullValue()
+exc.getMessage(), is(%22500: %5BrequestId=requestId%5D Unknown error%22
 ));%0A
@@ -3362,70 +3362,41 @@
     
-private ClientHttpResponse prepareResponse(String resourcePath
+@Test%0A    public void shouldName(
 ) th
@@ -3400,18 +3400,16 @@
  throws 
-IO
 Exceptio
@@ -3460,31 +3460,199 @@
 e = 
-mock(ClientHttpResponse
+prepareResponse();%0A        final HttpHeaders headers = new HttpHeaders();%0A        when(response.getHeaders()).thenReturn(headers);%0A        when(response.getStatusText()).thenThrow(IOException
 .cla
@@ -3677,24 +3677,27 @@
 response.get
+Raw
 StatusCode()
@@ -3706,161 +3706,764 @@
 then
-Return(HttpStatus.INTERNAL_SERVER_ERROR);%0A        when(response.getRawStatusCode()).thenReturn(500);%0A        final HttpHeaders headers = new HttpHeaders(
+Throw(IOException.class);%0A%0A        final GoodDataRestException exc = assertException(response);%0A%0A        assertThat(exc.getMessage(), is(%220: Unknown error%22));%0A        assertThat(exc.getStatusCode(), is(0));%0A        assertThat(exc.getRequestId(), is(nullValue()));%0A        assertThat(exc.getComponent(), is(nullValue()));%0A        assertThat(exc.getErrorClass(), is(nullValue()));%0A        assertThat(exc.getErrorCode(), is(nullValue()));%0A        assertThat(exc.getText(), is(nullValue()));%0A    %7D%0A%0A    private ClientHttpResponse prepareResponse(String resourcePath) throws IOException %7B%0A        final ClientHttpResponse response = prepareResponse();%0A        final HttpHeaders headers = new HttpHeaders();%0A        when(response.getHeaders()).thenReturn(headers
 );%0A 
@@ -4591,65 +4591,8 @@
 N);%0A
-        when(response.getHeaders()).thenReturn(headers);%0A
     
@@ -4664,16 +4664,337 @@
 Path));%0A
+        return response;%0A    %7D%0A%0A    private ClientHttpResponse prepareResponse() throws IOException %7B%0A        final ClientHttpResponse response = mock(ClientHttpResponse.class);%0A        when(response.getStatusCode()).thenReturn(HttpStatus.INTERNAL_SERVER_ERROR);%0A        when(response.getRawStatusCode()).thenReturn(500);
 %0A       

enhance tests for error handler