/*
 *    Copyright 2013 APPNEXUS INC
 *
 *    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
 *    distributed 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 the specific language governing permissions and
 *    limitations under the License.
 */

package com.appnexus.opensdk.utils;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Build;
import android.util.Pair;
import com.appnexus.opensdk.SDKSettings;

import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Utility class for retrieving and setting
 * the Google Play Services Advertising ID asynchronously.
 */
public class AdvertistingIDUtil {

    /**
     * Starts an AsyncTask to retrieve and set the AAID.
     * Does nothing if Settings.aaid is already set for the SDK.
     *
     * @param context context to retrieve the AAID on.
     */
    public static void retrieveAndSetAAID(Context context) {
        // skip if AAID is already available
        if (!StringUtil.isEmpty(SDKSettings.getAAID())) {
            return;
        }

        AAIDTask getAAIDTask = new AAIDTask(context);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            getAAIDTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        } else {
            getAAIDTask.execute();
        }
    }

    /**
     * Retrieves AAID from GooglePlayServices via reflection
     * Sets the SDK's aaid value to the result if successful,
     * or null if failed.
     */
    private static class AAIDTask extends AsyncTask<Void, Void, Pair<String, Boolean>> {
        private static final String cAdvertisingIdClientName
                = "com.google.android.gms.ads.identifier.AdvertisingIdClient";
        private static final String cAdvertisingIdClientInfoName
                = "com.google.android.gms.ads.identifier.AdvertisingIdClient$Info";

        private WeakReference<Context> context;

        private AAIDTask(Context context) {
            this.context = new WeakReference<Context>(context);
        }

        @Override
        protected Pair<String, Boolean> doInBackground(Void... params) {
            String aaid = null;
            Boolean limited = false;

            // attempt to retrieve AAID from GooglePlayServices via reflection
            do {
                try {
                    Context callcontext = context.get();
                    if (callcontext != null) {
                        // NPE catches null objects
                        Class<?> cInfo = Class.forName(cAdvertisingIdClientInfoName);
                        Class<?> cClient = Class.forName(cAdvertisingIdClientName);

                        Method mGetAdvertisingIdInfo = cClient.getMethod("getAdvertisingIdInfo", Context.class);
                        Method mGetId = cInfo.getMethod("getId");
                        Method mIsLimitAdTrackingEnabled = cInfo.getMethod("isLimitAdTrackingEnabled");

                        Object adInfoObject = cInfo.cast(mGetAdvertisingIdInfo.invoke(null, callcontext));

                        aaid = (String) mGetId.invoke(adInfoObject);
                        limited = (Boolean) mIsLimitAdTrackingEnabled.invoke(adInfoObject);
                    }
                } catch (ClassNotFoundException ignored) {
                } catch (InvocationTargetException ignored) {
                } catch (NoSuchMethodException ignored) {
                } catch (IllegalAccessException ignored) {
                } catch (ClassCastException ignored) {
                } catch (NullPointerException ignored) {
                }

            } while (false);

            // set or clear the AAID depending on success/failure
            return new Pair<String, Boolean>(aaid, limited);
        }

        @Override
        protected void onPostExecute(Pair<String, Boolean> pair) {
            super.onPostExecute(pair);
            SDKSettings.setAAID(pair.first, pair.second);
        }
    }
}

@@ -769,16 +769,17 @@
 l.Pair;%0A
+%0A
 import c
@@ -2699,29 +2699,9 @@
 ion%0A
-            do %7B%0A    
+%0A
     
@@ -2714,20 +2714,16 @@
   try %7B%0A
-    
         
@@ -2763,28 +2763,24 @@
 text.get();%0A
-    
             
@@ -2830,20 +2830,16 @@
         
-    
 // NPE c
@@ -2870,36 +2870,32 @@
                 
-   
- 
 Class%3C?%3E cInfo =
@@ -2952,36 +2952,32 @@
                 
-    
 Class%3C?%3E cClient
@@ -3033,36 +3033,32 @@
                 
-  
-  
 Method mGetAdver
@@ -3142,36 +3142,32 @@
                 
-    
 Method mGetId = 
@@ -3204,36 +3204,32 @@
                 
- 
-   
 Method mIsLimitA
@@ -3289,28 +3289,24 @@
 Enabled%22);%0A%0A
-    
             
@@ -3417,20 +3417,16 @@
         
-    
 aaid = (
@@ -3454,36 +3454,32 @@
 (adInfoObject);%0A
-    
                 
@@ -3566,24 +3566,18 @@
         
-    %7D%0A  
+%7D%0A
         
@@ -3572,34 +3572,32 @@
   %7D%0A            
-  
 %7D catch (ClassNo
@@ -3615,36 +3615,32 @@
 tion ignored) %7B%0A
-    
             %7D ca
@@ -3685,36 +3685,32 @@
 ) %7B%0A            
- 
-   
 %7D catch (NoSuchM
@@ -3727,36 +3727,32 @@
 tion ignored) %7B%0A
-    
             %7D ca
@@ -3794,36 +3794,32 @@
 ) %7B%0A            
-    
 %7D catch (ClassCa
@@ -3833,36 +3833,32 @@
 tion ignored) %7B%0A
-    
             %7D ca
@@ -3910,43 +3910,157 @@
     
-    %7D%0A%0A            %7D while (false);
+%7D catch (Exception ignored) %7B%0A                // catches GooglePlayServicesRepairableException, GooglePlayServicesNotAvailableException%0A            %7D
 %0A%0A  

add exceptions for AdvertisingIdClient.Info