// Copyright 2015 The Project Buendia Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License.  You may obtain a copy
// of the License at: http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distrib-
// uted under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
// OR CONDITIONS OF ANY KIND, either express or implied.  See the License for
// specific language governing permissions and limitations under the License.

package org.projectbuendia.client.net;

import com.android.volley.AuthFailureError;
import com.android.volley.NoConnectionError;
import com.android.volley.Response.ErrorListener;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;

import org.projectbuendia.client.App;
import org.projectbuendia.client.ui.BigToast;
import org.projectbuendia.client.utils.Logger;
import org.projectbuendia.client.utils.Utils;

public class OpenMrsErrorListener implements ErrorListener {

    private static final Logger LOG = Logger.create();

    /** Default error-handling behaviour; can be overridden to suit the situation. */
    @Override public void onErrorResponse(VolleyError error) {
        displayVolleyError(error);
    }

    /** Displays a VolleyError as a toast, if it can be made meaningful to the user. */
    public void displayVolleyError(VolleyError error) {
        // TODO(ping): Hand off to the HealthMonitor or use the snackbar.
        LOG.w(error.getClass().getSimpleName() + ": " + error.getMessage());
        if (error.networkResponse == null ||
            error instanceof NoConnectionError ||
            error instanceof AuthFailureError ||
            error instanceof TimeoutError) {
            // No toast needed; let the BuendiaApiHealthCheck catch these
            // and show a message in the snackbar.
            return;
        }

        int code = error.networkResponse.statusCode;
        String message = Utils.orDefault(
            extractMessageFromJson(error.networkResponse.data),
            "Sorry, there was a problem communicating with the server [code " + code + "]."
        );

        BigToast.show(App.getInstance().getApplicationContext(), message);
    }

    /** Parses a JSON-formatted error response from the OpenMRS server. **/
    public String extractMessageFromJson(byte[] data) {
        if (data == null) return null;
        String json = new String(data);
        LOG.i(json);
        String message = null;
        try {
            JsonObject result = new JsonParser().parse(json).getAsJsonObject();
            if (result.has("error")) {
                JsonObject errorObject = result.getAsJsonObject("error");
                JsonElement element = errorObject.get("message");
                if (element == null || element.isJsonNull()) {
                    element = errorObject.get("code");
                }
                if (element != null && element.isJsonPrimitive()) {
                    message = element.getAsString();
                }
            }
        } catch (JsonParseException | IllegalStateException | UnsupportedOperationException e) {
            LOG.w("Problem parsing error message: " + e.getMessage());
        }
        return message;
    }
}

@@ -666,24 +666,67 @@
 ilureError;%0A
+import com.android.volley.NetworkResponse;%0A
 import com.a
@@ -1171,54 +1171,8 @@
 ger;
-%0Aimport org.projectbuendia.client.utils.Utils;
 %0A%0Apu
@@ -2199,45 +2199,16 @@
 ge =
- Utils.orDefault(%0A           
  extract
 Mess
@@ -2203,31 +2203,28 @@
  extract
+Error
 Message
-FromJson
 (error.n
@@ -2241,120 +2241,11 @@
 onse
-.data),%0A            %22Sorry, there was a problem communicating with the server %5Bcode %22 + code + %22%5D.%22%0A        
 );%0A
-%0A
     
@@ -2427,38 +2427,148 @@
 ract
+Error
 Message
-FromJson(byte%5B%5D data) %7B
+(NetworkResponse response) %7B%0A        byte%5B%5D data = response.data;%0A        String problem = %22status code %22 + response.statusCode;
 %0A   
@@ -2585,17 +2585,17 @@
 ata 
-=
+!
 = null) 
 retu
@@ -2594,21 +2594,14 @@
 ll) 
-return null;%0A
+%7B%0A    
     
@@ -2636,16 +2636,20 @@
 (data);%0A
+    
         
@@ -2670,48 +2670,25 @@
     
-   String message = null;%0A
        
- 
 try %7B%0A
+    
     
@@ -2771,24 +2771,28 @@
             
+    
 if (result.h
@@ -2814,32 +2814,36 @@
                 
+    
 JsonObject error
@@ -2842,22 +2842,16 @@
 ct error
-Object
  = resul
@@ -2890,24 +2890,28 @@
             
+    
 JsonElement 
@@ -2910,31 +2910,31 @@
 Element 
-element
+message
  = error
 Object.g
@@ -2921,30 +2921,24 @@
 sage = error
-Object
 .get(%22messag
@@ -2962,110 +2962,345 @@
     
-if (element == null %7C%7C element.isJsonNull()) %7B%0A                    element = errorObject.get(%22code%22);%0A
+    if (message != null && message.isJsonPrimitive()) %7B%0A                        return message.getAsString();%0A                    %7D%0A                    JsonElement detail = error.get(%22detail%22);%0A                    if (detail != null && detail.isJsonPrimitive()) %7B%0A                        problem = detail.getAsString().split(%22%5Cn%22)%5B0%5D;%0A  
     
@@ -3303,32 +3303,34 @@
                 
+  
 %7D%0A              
@@ -3335,19 +3335,78 @@
     
-if (element
+    JsonElement code = error.get(%22code%22);%0A                    if (code
  != 
@@ -3413,23 +3413,20 @@
 null && 
-element
+code
 .isJsonP
@@ -3463,25 +3463,36 @@
     
-message = element
+    problem += %22 at %22 + code
 .get
@@ -3511,34 +3511,42 @@
                 
-%7D%0A
+    %7D%0A    
             %7D%0A  
@@ -3551,16 +3551,20 @@
         
+  
+  
 %7D catch 
@@ -3652,24 +3652,28 @@
             
+    
 LOG.w(%22Probl
@@ -3711,32 +3711,46 @@
 .getMessage());%0A
+            %7D%0A
         %7D%0A      
@@ -3758,23 +3758,92 @@
  return 
-message
+%22Sorry, there was a problem communicating with the server (%22 + problem + %22)%22
 ;%0A    %7D%0A

Improve server error reporting.