<commit_before>package com.wonderpush.sdk;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

import org.OpenUDID.OpenUDID_manager;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.content.LocalBroadcastManager;
import android.telephony.TelephonyManager;
import android.text.method.ScrollingMovementMethod;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.wonderpush.sdk.WonderPushDialogBuilder.Button;
import com.wonderpush.sdk.WonderPushDialogBuilder.Button.Action;

/**
 * Main class of the WonderPush SDK.
 *
 * <p>You would normally only interact with this class, which has all static members.</p>
 *
 * <p>
 *   Make sure you properly installed the WonderPush SDK, as described in
 *   <a href="../../../packages.html">the guide</a>.
 * </p>
 *
 * <p>You must call {@link #initialize(Activity, String, String, String)} before using any other function.</p>
 *
 * <p>
 *   Troubleshooting tip:
 *   As the SDK should not interfere with your application other than when a notification is to be shown,
 *   make sure to monitor your logs for the <tt>WonderPush</tt> tag during development,
 *   if things did not went as smoothly as they should have.
 * </p>
 */
public class WonderPush {

    static final String TAG = WonderPush.class.getSimpleName();

    private static Context sApplicationContext;
    private static String sClientId;
    private static String sClientSecret;
    private static Location sLocation;
    private static String sBaseURL;
    private static String sLang;
    private static boolean sIsInitialized = false;
    private static boolean sIsReachable = false;

    /**
     * The timeout for WebView requests
     */
    protected static final int WEBVIEW_REQUEST_TOTAL_TIMEOUT = 10000;
    protected static final int API_INT = 1; // reset SDK_VERSION when bumping this
    protected static final String API_VERSION = "v" + API_INT;
    protected static final String SDK_VERSION = "Android-" + API_INT + ".0.9.0"; // reset to .1.0.0 when bumping API_INT
    private static final String PREF_FILE = "wonderpush";
    protected static final int ERROR_INVALID_SID = 12017;
    private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

    /**
     * Local intent broadcasted when the WonderPush SDK has been initialized and network is reachable.
     */
    public static final String INTENT_INTIALIZED = "wonderpushInitialized";

    /**
     * Local intent broadcasted when a resource has been successfully preloaded.
     */
    protected static final String INTENT_RESOURCE_PRELOADED = "wonderpushResourcePreloaded";

    /**
     * The extra key for the path of a preloaded resource in a {@link #INTENT_RESOURCE_PRELOADED} intent.
     */
    protected static final String INTENT_RESOURCE_PRELOADED_EXTRA_PATH = "wonderpushResourcePreloadedPath";

    /**
     * Intent extra key for GCM notification data when the user clicks the notification.
     */
    protected static final String NOTIFICATION_EXTRA_KEY = "_wpNotification";

    static enum NotificationType {
        ALERT("alert"),
        IN_APP("inApp"),
        PLAIN("plain"),
        HTML("html"),
        MAP("map"),
        URL("url"),
        ;

        private String type;

        private NotificationType(String type) {
            this.type = type;
        }

        @Override
        public String toString() {
            return type;
        }

        public static NotificationType fromString(String type) {
            if (type == null) {
                throw new NullPointerException();
            }
            for (NotificationType notificationType : NotificationType.values()) {
                if (type.equals(notificationType.toString())) {
                    return notificationType;
                }
            }
            throw new IllegalArgumentException("Constant \"" + type + "\" is not a known " + NotificationType.class.getSimpleName());
        }
    }

    private static final String PRODUCTION_API_URL = "https://api.wonderpush.com/" + API_VERSION;
    protected static boolean SHOW_DEBUG = true;
    protected static final int ERROR_INVALID_ACCESS_TOKEN = 11003;
    protected static final String DEFAULT_LANGUAGE_CODE = "en";
    protected static final String[] VALID_LANGUAGE_CODES = {
            "af", "ar", "be", "bg", "bn", "ca", "cs", "da", "de", "el", "en", "en_GB", "en_US", "es", "es_ES", "es_MX",
            "et", "fa", "fi", "fr", "fr_FR", "fr_CA", "he", "hi", "hr", "hu", "id", "is", "it", "ja", "ko", "lt", "lv",
            "mk", "ms", "nb", "nl", "pa", "pl", "pt", "pt_PT", "pt_BR", "ro", "ru", "sk", "sl", "sq", "sr", "sv", "sw",
            "ta", "th", "tl", "tr", "uk", "vi", "zh", "zh_CN", "zh_TW", "zh_HK",
    };

    protected WonderPush() {
    }

    /**
     * Gets the current player id from the local cache.
     *
     * @return The current player id from the local cache.
     */
    protected static String getUserId() {
        return WonderPushRestClient.getUserId();
    }

    private static boolean checkPlayService(Activity activity) {
        try {
            Class.forName("com.google.android.gms.common.GooglePlayServicesUtil");
            int resultCode = GooglePlayServicesUtil
                    .isGooglePlayServicesAvailable(activity);
            if (resultCode != ConnectionResult.SUCCESS) {
                if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                    GooglePlayServicesUtil.getErrorDialog(resultCode, activity, PLAY_SERVICES_RESOLUTION_REQUEST).show();
                } else {
                    Log.w(TAG, "This device does not support google play service no push notification will be received");
                }
                return false;
            }
            return true;
        } catch (ClassNotFoundException e) {
            Log.w(TAG, "The Google Play Services have not been added to the application");
            return false;
        }
    }

    /**
     * Helper method that will register a device for google cloud messages
     * notification and register the device token to WonderPush. This method is
     * called within {@link #initialize(Activity, String, String, String)}.
     *
     * @param activity
     *            The current activity.
     */
    protected static void registerForPushNotification(Activity activity) {
        if (checkPlayService(activity)) {
            WonderPushGcmClient.registerForPushNotification(activity);
        } else {
            Log.w(TAG, "Google Play Services not present. Check your setup.");
        }
    }

    protected static void logDebug(String debug) {
        if (WonderPush.SHOW_DEBUG) {
            Log.d(TAG, debug);
        }
    }

    private static void handleReceivedNotification(Activity activity, JSONObject data) {
        NotificationType type = null;
        try {
            type = NotificationType.fromString(data.optString("type"));
        } catch (NullPointerException e) {
        } catch (IllegalArgumentException e) {
        }
        if (type == null) {
            Log.w(TAG, "No built-in action for type " + data.optString("type"));
            return;
        }
        switch (type) {
            case ALERT:
            case IN_APP:
                // Nothing to do
                break;
            case URL:
                handleURLNotification(activity, data);
                break;
            case PLAIN:
                handleDialogNotification(activity, data);
                break;
            case MAP:
                handleMapNotification(activity, data);
                break;
            case HTML:
                handleHTMLNotification(activity, data);
                break;
            default:
                Log.w(TAG, "TODO: built-in action for type " + type);
                break;
        }
    }

    /**
     * Method to call on your {@code onCreate()} method to handle the WonderPush notification.
     * Must be added to the {@link Activity} implementation of the class you gave to
     * {@link #onBroadcastReceived(Context, Intent, int, Class)}
     * (will be called within {@link WonderPush#initialize(Activity, String, String)}).
     * Example:
     *<commit_msg>Fix notification type constants - now with a clearer name<commit_after>package com.wonderpush.sdk;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

import org.OpenUDID.OpenUDID_manager;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.content.LocalBroadcastManager;
import android.telephony.TelephonyManager;
import android.text.method.ScrollingMovementMethod;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.wonderpush.sdk.WonderPushDialogBuilder.Button;
import com.wonderpush.sdk.WonderPushDialogBuilder.Button.Action;

/**
 * Main class of the WonderPush SDK.
 *
 * <p>You would normally only interact with this class, which has all static members.</p>
 *
 * <p>
 *   Make sure you properly installed the WonderPush SDK, as described in
 *   <a href="../../../packages.html">the guide</a>.
 * </p>
 *
 * <p>You must call {@link #initialize(Activity, String, String, String)} before using any other function.</p>
 *
 * <p>
 *   Troubleshooting tip:
 *   As the SDK should not interfere with your application other than when a notification is to be shown,
 *   make sure to monitor your logs for the <tt>WonderPush</tt> tag during development,
 *   if things did not went as smoothly as they should have.
 * </p>
 */
public class WonderPush {

    static final String TAG = WonderPush.class.getSimpleName();

    private static Context sApplicationContext;
    private static String sClientId;
    private static String sClientSecret;
    private static Location sLocation;
    private static String sBaseURL;
    private static String sLang;
    private static boolean sIsInitialized = false;
    private static boolean sIsReachable = false;

    /**
     * The timeout for WebView requests
     */
    protected static final int WEBVIEW_REQUEST_TOTAL_TIMEOUT = 10000;
    protected static final int API_INT = 1; // reset SDK_VERSION when bumping this
    protected static final String API_VERSION = "v" + API_INT;
    protected static final String SDK_VERSION = "Android-" + API_INT + ".0.9.0"; // reset to .1.0.0 when bumping API_INT
    private static final String PREF_FILE = "wonderpush";
    protected static final int ERROR_INVALID_SID = 12017;
    private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

    /**
     * Local intent broadcasted when the WonderPush SDK has been initialized and network is reachable.
     */
    public static final String INTENT_INTIALIZED = "wonderpushInitialized";

    /**
     * Local intent broadcasted when a resource has been successfully preloaded.
     */
    protected static final String INTENT_RESOURCE_PRELOADED = "wonderpushResourcePreloaded";

    /**
     * The extra key for the path of a preloaded resource in a {@link #INTENT_RESOURCE_PRELOADED} intent.
     */
    protected static final String INTENT_RESOURCE_PRELOADED_EXTRA_PATH = "wonderpushResourcePreloadedPath";

    /**
     * Intent extra key for GCM notification data when the user clicks the notification.
     */
    protected static final String NOTIFICATION_EXTRA_KEY = "_wpNotification";

    static enum NotificationType {
        SIMPLE("simple"),
        DATA("data"),
        TEXT("text"),
        HTML("html"),
        MAP("map"),
        URL("url"),
        ;

        private String type;

        private NotificationType(String type) {
            this.type = type;
        }

        @Override
        public String toString() {
            return type;
        }

        public static NotificationType fromString(String type) {
            if (type == null) {
                throw new NullPointerException();
            }
            for (NotificationType notificationType : NotificationType.values()) {
                if (type.equals(notificationType.toString())) {
                    return notificationType;
                }
            }
            throw new IllegalArgumentException("Constant \"" + type + "\" is not a known " + NotificationType.class.getSimpleName());
        }
    }

    private static final String PRODUCTION_API_URL = "https://api.wonderpush.com/" + API_VERSION;
    protected static boolean SHOW_DEBUG = true;
    protected static final int ERROR_INVALID_ACCESS_TOKEN = 11003;
    protected static final String DEFAULT_LANGUAGE_CODE = "en";
    protected static final String[] VALID_LANGUAGE_CODES = {
            "af", "ar", "be", "bg", "bn", "ca", "cs", "da", "de", "el", "en", "en_GB", "en_US", "es", "es_ES", "es_MX",
            "et", "fa", "fi", "fr", "fr_FR", "fr_CA", "he", "hi", "hr", "hu", "id", "is", "it", "ja", "ko", "lt", "lv",
            "mk", "ms", "nb", "nl", "pa", "pl", "pt", "pt_PT", "pt_BR", "ro", "ru", "sk", "sl", "sq", "sr", "sv", "sw",
            "ta", "th", "tl", "tr", "uk", "vi", "zh", "zh_CN", "zh_TW", "zh_HK",
    };

    protected WonderPush() {
    }

    /**
     * Gets the current player id from the local cache.
     *
     * @return The current player id from the local cache.
     */
    protected static String getUserId() {
        return WonderPushRestClient.getUserId();
    }

    private static boolean checkPlayService(Activity activity) {
        try {
            Class.forName("com.google.android.gms.common.GooglePlayServicesUtil");
            int resultCode = GooglePlayServicesUtil
                    .isGooglePlayServicesAvailable(activity);
            if (resultCode != ConnectionResult.SUCCESS) {
                if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                    GooglePlayServicesUtil.getErrorDialog(resultCode, activity, PLAY_SERVICES_RESOLUTION_REQUEST).show();
                } else {
                    Log.w(TAG, "This device does not support google play service no push notification will be received");
                }
                return false;
            }
            return true;
        } catch (ClassNotFoundException e) {
            Log.w(TAG, "The Google Play Services have not been added to the application");
            return false;
        }
    }

    /**
     * Helper method that will register a device for google cloud messages
     * notification and register the device token to WonderPush. This method is
     * called within {@link #initialize(Activity, String, String, String)}.
     *
     * @param activity
     *            The current activity.
     */
    protected static void registerForPushNotification(Activity activity) {
        if (checkPlayService(activity)) {
            WonderPushGcmClient.registerForPushNotification(activity);
        } else {
            Log.w(TAG, "Google Play Services not present. Check your setup.");
        }
    }

    protected static void logDebug(String debug) {
        if (WonderPush.SHOW_DEBUG) {
            Log.d(TAG, debug);
        }
    }

    private static void handleReceivedNotification(Activity activity, JSONObject data) {
        NotificationType type = null;
        try {
            type = NotificationType.fromString(data.optString("type"));
        } catch (NullPointerException e) {
        } catch (IllegalArgumentException e) {
        }
        if (type == null) {
            Log.w(TAG, "No built-in action for type " + data.optString("type"));
            return;
        }
        switch (type) {
            case SIMPLE:
            case DATA:
                // Nothing to do
                break;
            case URL:
                handleURLNotification(activity, data);
                break;
            case TEXT:
                handleDialogNotification(activity, data);
                break;
            case MAP:
                handleMapNotification(activity, data);
                break;
            case HTML:
                handleHTMLNotification(activity, data);
                break;
            default:
                Log.w(TAG, "TODO: built-in action for type " + type);
                break;
        }
    }

    /**
     * Method to call on your {@code onCreate()} method to handle the WonderPush notification.
     * Must be added to the {@link Activity} implementation of the class you gave to
     * {@link #onBroadcastReceived(Context, Intent, int, Class)}
     * (will be called within {@link WonderPush#initialize(Activity, String, String)}).
     * Example:
     *
{'fraction_non_alphanumeric': 0.10008885172215544, 'fraction_numerical': 0.0028223488214080385, 'mean_word_length': 2.726192794547225, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 27, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5310312', 'n_tokens_mistral': 5248, 'n_tokens_neox': 5068, 'n_words': 1546}