package com.algobase.share.app;

import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.io.IOException;

import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.Iterator;

import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.StackTraceElement;

import android.os.Build;
import android.os.Process;
import android.os.Environment;
import android.os.Bundle;

import android.app.ActivityManager;
import android.app.Application;
import android.app.PendingIntent;
import android.app.AlarmManager;
import android.util.Log;

import android.content.Intent;
import android.content.Context;
import android.content.SharedPreferences;

import android.widget.Toast;

import com.algobase.share.activity.*;
import com.algobase.share.compat.*;


public class  GlobalExceptionHandler implements 
                                         Thread.UncaughtExceptionHandler
{

  public static final String EXTRA_CRASH_APP_NAME = "CrashAppName";
  public static final String EXTRA_CRASH_EXCEPTION = "CrashException";
  public static final String EXTRA_CRASH_TEXT = "CrashText";
  public static final String EXTRA_CRASH_PATH = "CrashPath";
  public static final String EXTRA_LOG1_PATH = "Log1Path";
  public static final String EXTRA_LOG2_PATH = "Log2Path";

  UncaughtExceptionHandler defaultHandler =
                 Thread.getDefaultUncaughtExceptionHandler();

  String appName = "Unknown App";

  File appFolder = null;

  File crashFile = null;
  File log1File = null;
  File log2File = null;

  Context context;


  public GlobalExceptionHandler(Context ctxt, String app_name) 
  { context = ctxt;
    appName = app_name;
/*
    File sd_root = Environment.getExternalStorageDirectory();
    appFolder = new File(sd_root,app_name();
    if (!appFolder.exists()) appFolder.mkdir();
*/
    appFolder = ctxt.getFilesDir();
    crashFile = new File(appFolder,"crash_report.txt");
    log1File = new File(appFolder,"log/logfile.txt");
    log2File = new File(appFolder,"log/service_log.txt");

  }


  public void setCrashFile(String path) { 
      crashFile = new File(appFolder,path);
  }

  public void setLog1File(String path) {
      log1File = new File(appFolder,path);
  }

  public void setLog2File(String path) {
      log2File = new File(appFolder,path);
  }


  private void write_report(Thread t, Throwable e) throws IOException
  {
    BufferedWriter writer = new BufferedWriter(new FileWriter(crashFile));

    StringWriter str = new StringWriter();
    PrintWriter printWriter = new PrintWriter(str);
    e.printStackTrace(printWriter);
    printWriter.close();

    String stack_trace = str.toString();

    //writer.write("Error: uncaught exception.");

    writer.write("ANDROID: " + "SDK-" + Build.VERSION.SDK_INT);
    writer.newLine();
    writer.write("MODEL:   " + Build.MODEL);
    writer.newLine();
    writer.newLine();

    writer.write("[THREAD]");
    writer.newLine();
    writer.write(t.getName());
    writer.newLine();

    writer.write("[EXCEPTION]");
    writer.newLine();
    writer.write(e.toString());
    writer.newLine();

    String msg = e.getMessage();

    if (msg != null)
    { writer.write(e.getMessage());
      writer.newLine();
     }
    writer.newLine();

    writer.write("[STACK TRACE]");
    writer.newLine();
    writer.write(stack_trace);
    writer.newLine();


    StackTraceElement trace[] = e.getStackTrace();
    for(int i=0; i<trace.length; i++) 
    { writer.write(trace[i].toString());
      writer.newLine();
     }

    writer.close();
  }



  @Override
  public void uncaughtException(Thread thread, final Throwable ex) 
  { 

    Thread.setDefaultUncaughtExceptionHandler(null);

    long cur_time = System.currentTimeMillis();

    SharedPreferences
       prefs = context.getSharedPreferences("GlobalExceptionHandler",0);
    long last_time = prefs.getLong("TIMESTAMP",0);

    long time_diff = cur_time - last_time;

    SharedPreferences.Editor edit = prefs.edit();
    edit.putLong("TIMESTAMP",cur_time);
    edit.commit();


    StringWriter str = new StringWriter();
    PrintWriter printWriter = new PrintWriter(str);
    ex.printStackTrace(printWriter);
    printWriter.close();

    String stack_trace = str.toString();

    try {
      write_report(thread,ex);
    } catch (Exception e) {
        Toast.makeText(context,e.toString(), Toast.LENGTH_LONG).show();
      }
      
    Intent intent = new Intent(context,CrashReportActivity.class);

    //intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                    Intent.FLAG_ACTIVITY_SINGLE_TOP);

    intent.putExtra(EXTRA_CRASH_APP_NAME,appName);
    intent.putExtra(EXTRA_CRASH_EXCEPTION,ex.toString());
    intent.putExtra(EXTRA_CRASH_TEXT,stack_trace);
    intent.putExtra(EXTRA_CRASH_PATH,crashFile.getPath());

    if (log1File != null)
      intent.putExtra(EXTRA_LOG1_PATH,log1File.getPath());

    if (log2File != null)
      intent.putExtra(EXTRA_LOG2_PATH,log2File.getPath());


    if (time_diff >  5000) 
    {
      //context.startActivity(intent);
      PendingIntent p_intent = PendingIntent.getActivity(context, 0, intent, 
                                                PendingIntent.FLAG_ONE_SHOT |
                                                PendingIntent.FLAG_IMMUTABLE);
      try { p_intent.send(); } catch (Exception e) {}
   }


    //defaultHandler.uncaughtException(thread, ex);
    //Process.killProcess(Process.myPid());

    System.exit(1);

  }
}
    

