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.httpClient;
  
  import android.content.Context;
  import android.content.pm.PackageInfo;
  import android.content.pm.PackageManager;
  import android.os.Build;
  
  import com.vk.sdk.VKSdkVersion;
  import com.vk.sdk.VKUIHelper;
  import com.vk.sdk.api.VKParameters;
  import com.vk.sdk.api.VKRequest;
  import com.vk.sdk.api.model.VKAttachments;
  import com.vk.sdk.util.VKStringJoiner;
  import com.vk.sdk.util.VKUtil;
  
  import org.apache.http.NameValuePair;
  import org.apache.http.client.entity.UrlEncodedFormEntity;
  import org.apache.http.client.methods.HttpGet;
  import org.apache.http.client.methods.HttpPost;
  import org.apache.http.client.methods.HttpUriRequest;
  import org.apache.http.conn.ClientConnectionManager;
  import org.apache.http.conn.scheme.PlainSocketFactory;
  import org.apache.http.conn.scheme.Scheme;
  import org.apache.http.conn.scheme.SchemeRegistry;
  import org.apache.http.conn.ssl.SSLSocketFactory;
  import org.apache.http.impl.client.DefaultHttpClient;
  import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
  import org.apache.http.message.BasicNameValuePair;
  import org.apache.http.params.BasicHttpParams;
  import org.apache.http.params.CoreProtocolPNames;
  import org.apache.http.params.HttpParams;
  
  import java.io.File;
  import java.io.UnsupportedEncodingException;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.Locale;
  import java.util.Map;
  import java.util.concurrent.Executor;
  import java.util.concurrent.Executors;
  
  /**
   * Class provides configured http client for API request loading
   */
  public class VKHttpClient extends DefaultHttpClient {
      private static VKHttpClient sInstance;
  
      /**
       * Default constructor from basic class
       *
       * @param conman The connection manager
       * @param params The parameters
       */
      private VKHttpClient(ClientConnectionManager conman, HttpParams params) {
          super(conman, params);
      }
  
      /**
       * Creates the http client (if need). Returns reusing client
       *
       * @return Prepared client used for API requests loading
       */
      public static VKHttpClient getClient() {
          if (sInstance == null) {
              SchemeRegistry schemeRegistry = new SchemeRegistry();
              schemeRegistry.register(new Scheme("http",
                      PlainSocketFactory.getSocketFactory(), 80));
              schemeRegistry.register(new Scheme("https",
                      SSLSocketFactory.getSocketFactory(), 443));
              HttpParams params = new BasicHttpParams();
              Context ctx = VKUIHelper.getApplicationContext();
  
              try {
                  if (ctx != null)
                  {
                      PackageManager packageManager = ctx.getPackageManager();
                      if (packageManager != null) {
                          PackageInfo info = packageManager.getPackageInfo(ctx.getPackageName(), 0);
                          params.setParameter(CoreProtocolPNames.USER_AGENT,
                                  String.format(Locale.US,
                                          "%s/%s (%s; Android %d; Scale/%.2f; VK SDK %s; %s)",
                                          VKUtil.getApplicationName(ctx), info.versionName,
                                          Build.MODEL, Build.VERSION.SDK_INT,
                                          ctx.getResources().getDisplayMetrics().density,
                                          VKSdkVersion.SDK_VERSION,
                                          info.packageName));
                      }
                  }
              } catch (Exception ignored) {
              }
              sInstance = new VKHttpClient(new ThreadSafeClientConnManager(params, schemeRegistry),
                      params);
          }
          return sInstance;
      }
  
      /**
       * Prepares new "normal" request from VKRequest
       *
       * @param vkRequest Request, created for some method
       * @return Prepared request for creating VKHttpOperation
       */
      public static HttpUriRequest requestWithVkRequest(VKRequest vkRequest) {
          HttpUriRequest request = null;
          VKParameters preparedParameters = vkRequest.getPreparedParameters();
          StringBuilder urlStringBuilder = new StringBuilder(
                  String.format(Locale.US, "http%s://api.vk.com/method/%s",
                          vkRequest.secure ? "s" : "", vkRequest.methodName));
          switch (vkRequest.httpMethod) {
              case GET:
                  if (preparedParameters.size() > 0) {
                      urlStringBuilder.append("?").append(VKStringJoiner.joinUriParams(preparedParameters));
                  }
                  request = new HttpGet(urlStringBuilder.toString());
                  break;
  
              case POST:
                  HttpPost post = new HttpPost(urlStringBuilder.toString());
                  ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>(preparedParameters.size());
                  for (Map.Entry<String, Object> entry : preparedParameters.entrySet()) {
                      Object value = entry.getValue();
                      if (value instanceof VKAttachments) {
                          pairs.add(new BasicNameValuePair(entry.getKey(), ((VKAttachments)value).toAttachmentsString()));
                      }
                      else if (value instanceof Collection) {
                          Collection<?> values = (Collection<?>) value;
                          for (Object v : values) {
                              // This will add a parameter for each value in the Collection/List
                              pairs.add(new BasicNameValuePair(String.format("%s[]", entry.getKey()), v == null ? null : String.valueOf(v)));
                          }
                      } else {
                          pairs.add(new BasicNameValuePair(entry.getKey(), value == null ? null : String.valueOf(value)));
                      }
                  }
                  try {
                      UrlEncodedFormEntity entity = new UrlEncodedFormEntity(pairs, "UTF-8");
                      post.setEntity(entity);
                  } catch (UnsupportedEncodingException e) {
                      return null;
                  }
                  request = post;
                  break;
          }
          Map<String, String> defaultHeaders = getDefaultHeaders();
          for (String key : defaultHeaders.keySet()) {
              request.addHeader(key, defaultHeaders.get(key));
          }
  
          return request;
      }
  
      public static HttpPost fileUploadRequest(String uploadUrl, File... files) {
          HttpPost post = new HttpPost(uploadUrl);
          post.setEntity(new VKMultipartEntity(files));
          return post;
      }
  
      /**
       * Returns map of default headers for any request
       *
       * @return Map of default headers
       */
      private static Map<String, String> getDefaultHeaders() {
          return new HashMap<String, String>() {/**
  			 * 
  			 */
  			private static final long serialVersionUID = 200199014417610665L;
  
  		{
              put("Accept-Encoding", "gzip");
          }};
      }
  
      /**
       * Executor for performing requests in background
       */
      private static final Executor mBackgroundExecutor = Executors.newCachedThreadPool();
  
      /**
       * Starts operation in the one of network threads
       *
       * @param operation Operation to start
       */
      public static void enqueueOperation(final VKAbstractOperation operation) {
          mBackgroundExecutor.execute(new Runnable() {
              @Override
              public void run() {
  	            operation.start();
              }
          });
      }
  
  	/**
  	 * Cancel http operation request on background thread (to prevent exception)
  	 * @param operation executing http operation
  	 */
  	public static void cancelHttpOperation(final VKHttpOperation operation) {
  		mBackgroundExecutor.execute(new Runnable() {
  			@Override
  			public void run() {
  				operation.getUriRequest().abort();
  			}
  		});
  	}
  
  
  }
  