content: //
  //  Copyright (c) 2014 VK.com
  //
  //  Permission is hereby granted, free of charge, to any person obtaining a copy of
  //  this software and associated documentation files (the "Software"), to deal in
  //  the Software without restriction, including without limitation the rights to
  //  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  //  the Software, and to permit persons to whom the Software is furnished to do so,
  //  subject to the following conditions:
  //
  //  The above copyright notice and this permission notice shall be included in all
  //  copies or substantial portions of the Software.
  //
  //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  //  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  //  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  //  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  //  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  
  package com.vk.sdk.api;
  
  import android.net.Uri;
  
  import com.vk.sdk.VKObject;
  import com.vk.sdk.util.VKJsonHelper;
  
  import org.json.JSONException;
  import org.json.JSONObject;
  
  import java.util.ArrayList;
  import java.util.Map;
  
  /**
   * Class for presenting VK SDK and VK API errors
   */
  public class VKError extends VKObject {
  	public static final int VK_API_ERROR = -101;
      /**
       * @deprecated Use VK_CANCELED instead
       */
      public static final int VK_API_CANCELED = -102;
      public static final int VK_CANCELED = -102;
  
      /**
       * @deprecated Use VK_REQUEST_NOT_PREPARED instead
       */
      public static final int VK_API_REQUEST_NOT_PREPARED = -103;
      public static final int VK_REQUEST_NOT_PREPARED = -103;
  
      /**
       * @deprecated Use VK_JSON_FAILED instead
       */
      public static final int VK_API_JSON_FAILED = -104;
      public static final int VK_JSON_FAILED = -104;
  
      /**
       * @deprecated Use VK_REQUEST_HTTP_FAILED instead
       */
      public static final int VK_API_REQUEST_HTTP_FAILED = -105;
      public static final int VK_REQUEST_HTTP_FAILED = -105;
  
      /**
       * Contains system HTTP error
       */
      public Exception httpError;
      /**
       * Describes API error
       */
      public VKError apiError;
      /**
       * Request which caused error
       */
      public VKRequest request;
      /**
       * May contains such errors:<br/>
       * <b>HTTP status code</b> if HTTP error occured;<br/>
       * <b>VK_API_ERROR</b> if API error occured;<br/>
       * <b>VK_API_CANCELED</b> if request was canceled;<br/>
       * <b>VK_API_REQUEST_NOT_PREPARED</b> if error occured while preparing request;
       */
      public int errorCode;
      /**
       * API error message
       */
      public String errorMessage;
      /**
       * Reason for authorization fail
       */
      public String errorReason;
      /**
       * API parameters passed to request
       */
      public ArrayList<Map<String, String>> requestParams;
      /**
       * Captcha identifier for captcha-check
       */
      public String captchaSid;
      /**
       * Image for captcha-check
       */
      public String captchaImg;
      /**
       * Redirection address if validation check required
       */
      public String redirectUri;
  
      /**
       * Generate new error with code
       *
       * @param errorCode positive if it's an HTTP error. Negative if it's API or SDK error
       */
      public VKError(int errorCode) {
          this.errorCode = errorCode;
      }
  
      /**
       * Generate API error from JSON
       *
       * @param json Json description of VK API error
       */
      @SuppressWarnings("unchecked")
  	public VKError(JSONObject json) throws JSONException {
          VKError internalError = new VKError(json.getInt(VKApiConst.ERROR_CODE));
          internalError.errorMessage = json.getString(VKApiConst.ERROR_MSG);
          internalError.requestParams = (ArrayList<Map<String, String>>) VKJsonHelper.toList(
                  json.getJSONArray(VKApiConst.REQUEST_PARAMS));
          if (internalError.errorCode == 14) {
              internalError.captchaImg = json.getString(VKApiConst.CAPTCHA_IMG);
              internalError.captchaSid = json.getString(VKApiConst.CAPTCHA_SID);
          }
          if (internalError.errorCode == 17) {
              internalError.redirectUri = json.getString(VKApiConst.REDIRECT_URI);
          }
  
          this.errorCode = VK_API_ERROR;
          this.apiError = internalError;
      }
  
      private static final String FAIL = "fail";
      private static final String ERROR_REASON = "error_reason";
      private static final String ERROR_DESCRIPTION = "error_description";
  
      /**
       * Generate API error from HTTP-query
       *
       * @param queryParams key-value parameters
       */
      public VKError(Map<String, String> queryParams) {
          this.errorCode = VK_API_ERROR;
          this.errorReason = queryParams.get(ERROR_REASON);
          this.errorMessage = Uri.decode(queryParams.get(ERROR_DESCRIPTION));
          if (queryParams.containsKey(FAIL)) {
              this.errorReason = "Action failed";
          }
          if (queryParams.containsKey("cancel")) {
              this.errorCode   = VK_CANCELED;
              this.errorReason = "User canceled request";
          }
      }
  
      /**
       * Repeats failed captcha request with user entered answer to captcha
       *
       * @param userEnteredCode answer for captcha
       */
      public void answerCaptcha(String userEnteredCode) {
          VKParameters params = new VKParameters();
          params.put(VKApiConst.CAPTCHA_SID, captchaSid);
          params.put(VKApiConst.CAPTCHA_KEY, userEnteredCode);
          request.addExtraParameters(params);
          request.repeat();
      }
      public static VKError getRegisteredError(long requestId) {
          return (VKError) getRegisteredObject(requestId);
      }
  
      private void appendFields(StringBuilder builder) {
          if (errorReason != null)
              builder.append(String.format("; %s", errorReason));
          if (errorMessage != null)
              builder.append(String.format("; %s", errorMessage));
      }
  
  	@Override public String toString()
  	{
  		StringBuilder errorString = new StringBuilder("VKError (");
  		switch (this.errorCode) {
  			case VK_API_ERROR:
  				errorString.append("API error");
                  if (apiError != null) {
                      errorString.append(apiError.toString());
                  }
  				break;
  			case VK_CANCELED:
  				errorString.append("Canceled");
  				break;
  			case VK_REQUEST_NOT_PREPARED:
  				errorString.append("Request wasn't prepared");
  				break;
  			case VK_JSON_FAILED:
  				errorString.append("JSON failed");
  
  				break;
  			case VK_REQUEST_HTTP_FAILED:
  				errorString.append("HTTP failed");
  				break;
  
  			default:
  				errorString.append(String.format("code: %d; ", errorCode));
  				break;
  		}
          appendFields(errorString);
  		errorString.append(")");
  		return errorString.toString();
  	}
  }
  