/*
 * Copyright 2015 Hewlett-Packard Development Company, L.P.
 * Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
 */

package com.hp.autonomy.hod.client.error;

import com.hp.autonomy.hod.client.job.Action;
import lombok.extern.slf4j.Slf4j;
import retrofit.ErrorHandler;
import retrofit.RetrofitError;
import retrofit.client.Response;

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

@Slf4j
public class HodErrorHandler implements ErrorHandler {
    @Override
    public Throwable handleError(final RetrofitError cause) {
        final RetrofitError.Kind kind = cause.getKind();

        if (kind == RetrofitError.Kind.HTTP) {
            // HOD returned an unsuccessful status code, parse the JSON response and throw something better
            HodError hodError = (HodError) cause.getBodyAs(HodError.class);

            // HOD errors are tediously non standard
            // if it has message (rather than reason, it's probably an API key error)
            final String message = hodError.getMessage();

            // if has actions, pull the error out of the action as it will be more useful
            final List<Action<?>> actions = hodError.getActions();

            if (message != null && hodError.getErrorCode() == null) {
                // HOD has given us an API key error
                final Map<String, Object> detail = (Map<String, Object>) hodError.getDetail();
                final HodErrorCode errorCode = HodErrorCode.fromCode((Integer) detail.get("error"));

                hodError = new HodError.Builder()
                        .setErrorCode(errorCode)
                        .setReason(message)
                        .build();
            }
            else if (actions != null && !actions.isEmpty()) {
                // HOD has given us job style output
                hodError = actions.get(0).getErrors().get(0);
            }

            // may be null if no response body
            if (hodError != null) {
                if (hodError.getErrorCode() == HodErrorCode.UNKNOWN_ERROR_CODE) {
                    // a code we've not seen before has been returned, log it
                    log.error("UNKNOWN ERROR CODE {}", hodError.getErrorCode());
                }

                final Response response = cause.getResponse();
                final int status = response.getStatus();

                log.error("{} error communicating with HP Haven OnDemand", status);

                log.error("Detail was : {}", hodError.getDetail());

                return new HodErrorException(hodError, status);
            }
            else {
                // no response body, not much we can do
                return cause;
            }
        }
        else {
            // something unusual went wrong, just rethrow the cause
            return cause;
        }
    }
}

@@ -1221,24 +1221,70 @@
 Actions();%0A%0A
+            int error = hodError.getError();%0A%0A
             
@@ -1485,24 +1485,79 @@
 etDetail();%0A
+                error = (Integer) detail.get(%22error%22);%0A
             
@@ -1617,37 +1617,13 @@
 ode(
-(Integer) detail.get(%22
 error
-%22)
 );%0A%0A
@@ -2303,39 +2303,21 @@
 DE %7B%7D%22, 
-hodError.getErrorCode()
+error
 );%0A     

Fix a small bug in the error handler which would print out the UNKNOWN_ERROR_CODE enum constant instead of the actual integer for which there was no enum constant. [rev: matthew.gordon]