/* Copyright (c) 2009 Matthias Käppler
 *
 * 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.github.droidfu.support;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Locale;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.provider.Settings.SettingNotFoundException;

public class DiagnosticSupport {

    public static final int ANDROID_API_LEVEL;

    static {
        int apiLevel = -1;
        try {
            apiLevel = Build.VERSION.class.getField("SDK_INT").getInt(null);
        } catch (Exception e) {
            apiLevel = Integer.parseInt(Build.VERSION.SDK);
        }
        ANDROID_API_LEVEL = apiLevel;
    }

    /**
     * Returns the ANDROID_ID unique device ID for the current device. Unlike the platform
     * functions, this method is reliable: since reading that ID has changed between platform
     * versions, it takes care of attempting to read it in different ways, if one failed. Also, it
     * guarantees to never return null.
     * 
     * @param context
     *            the context
     * @return the device's ANDROID_ID, or "UNKNOWN_DEVICE"
     * @see Secure#ANDROID_ID
     */
    public static String getAndroidId(Context context) {
        String androidId = Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);
        if (androidId == null) {
            // this happens on 1.6 and older
            androidId = android.provider.Settings.System.getString(context.getContentResolver(),
                    android.provider.Settings.System.ANDROID_ID);
        }
        if (androidId == null) {
            androidId = "UNKNOWN_DEVICE";
        }
        return androidId;
    }

    public static String getApplicationVersionString(Context context) {
        try {
            PackageManager pm = context.getPackageManager();
            PackageInfo info = pm.getPackageInfo(context.getPackageName(), 0);
            return "v" + info.versionName;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String createDiagnosis(Activity context, Exception error) {
        StringBuilder sb = new StringBuilder();

        sb.append("Application version: " + getApplicationVersionString(context) + "\n");
        sb.append("Device locale: " + Locale.getDefault().toString() + "\n\n");

        // phone information
        sb.append("PHONE SPECS\n");
        sb.append("model: " + Build.MODEL + "\n");
        sb.append("brand: " + Build.BRAND + "\n");
        sb.append("product: " + Build.PRODUCT + "\n");
        sb.append("device: " + Build.DEVICE + "\n\n");

        // android information
        sb.append("PLATFORM INFO\n");
        sb.append("Android " + Build.VERSION.RELEASE + " " + Build.ID + " (build "
                + Build.VERSION.INCREMENTAL + ")\n");
        sb.append("build tags: " + Build.TAGS + "\n");
        sb.append("build type: " + Build.TYPE + "\n\n");

        // settings
        sb.append("SYSTEM SETTINGS\n");
        String networkMode = null;
        ContentResolver resolver = context.getContentResolver();
        try {
            if (Settings.Secure.getInt(resolver, Settings.Secure.WIFI_ON) == 0) {
                networkMode = "DATA";
            } else {
                networkMode = "WIFI";
            }
            sb.append("network mode: " + networkMode + "\n");
            sb.append("HTTP proxy: "
                    + Settings.Secure.getString(resolver, Settings.Secure.HTTP_PROXY) + "\n\n");
        } catch (SettingNotFoundException e) {
            e.printStackTrace();
        }

        sb.append("STACK TRACE FOLLOWS\n\n");

        StringWriter stackTrace = new StringWriter();
        error.printStackTrace(new PrintWriter(stackTrace));

        sb.append(stackTrace.toString());

        return sb.toString();
    }

}

@@ -1500,78 +1500,9 @@
 ce. 
-Unlike the platform%0A     * functions, this method is reliable: since r
+R
 eadi
@@ -1523,16 +1523,23 @@
  changed
+%0A     *
  between
@@ -1547,23 +1547,16 @@
 platform
-%0A     *
  version
@@ -1558,18 +1558,30 @@
 rsions, 
-it
+so this method
  takes c
@@ -1621,16 +1621,23 @@
 ifferent
+%0A     *
  ways, i
@@ -1653,57 +1653,8 @@
 led.
- Also, it%0A     * guarantees to never return null.
 %0A   
@@ -1753,32 +1753,50 @@
 _ID, or 
-%22UNKNOWN_DEVICE%22
+null if it could not be determined
 %0A     * 
@@ -2220,32 +2220,528 @@
 _ID);%0A        %7D%0A
+        return androidId;%0A    %7D%0A%0A    /**%0A     * Same as %7B@link #getAndroidId(Context)%7D, but never returns null.%0A     * %0A     * @param context%0A     *            the context%0A     * @param fallbackValue%0A     *            the fallback value%0A     * @return the device's ANDROID_ID, or the fallback value if it could not be determined%0A     * @see Secure#ANDROID_ID%0A     */%0A    public static String getAndroidId(Context context, String fallbackValue) %7B%0A        String androidId = getAndroidId(context);%0A
         if (andr
@@ -2785,24 +2785,21 @@
 d = 
-%22UNKNOWN_DEVICE%22
+fallbackValue
 ;%0A  
@@ -3503,32 +3503,98 @@
 ing() + %22%5Cn%5Cn%22);
+%0A        sb.append(%22Android ID: %22 + getAndroidId(context, %22n/a%22));
 %0A%0A        // pho

add fallback option to android ID getter; send Android ID in error reports