package hf.lskj.com.carstockcount;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Application;
import android.content.pm.PackageManager;
import android.database.sqlite.SQLiteDatabase;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.text.format.DateFormat;
import android.util.Log;

import com.tencent.bugly.crashreport.CrashReport;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import hf.lskj.com.carstockcount.activity.MainActivity;
import hf.lskj.com.carstockcount.db.DaoMaster;
import hf.lskj.com.carstockcount.db.DaoSession;
import hf.lskj.com.carstockcount.db.User;


public class MyApplication extends Application {
    private static MyApplication instance;
    public static final boolean isDebugMode = BuildConfig.DEBUG;
    private DaoMaster.DevOpenHelper mHelper;
    private SQLiteDatabase db;
    private DaoMaster mDaoMaster;
    private DaoSession mDaoSession;
    public static User currentUser;

    public static class MyHandler extends Handler {

    }

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        CrashReport.initCrashReport(getApplicationContext(), "c7b34b5874", isDebugMode);
        setDatabase();
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread thread, Throwable ex) {
                createLogs(ex);
                MainActivity.closeUHF();
                android.os.Process.killProcess(android.os.Process.myPid());
            }
        });
    }

    public static MyApplication getInstances() {
        return instance;
    }

    /**
     * 设置greenDao
     */
    private void setDatabase() {
        // 通过 DaoMaster 的内部类 DevOpenHelper，你可以得到一个便利的 SQLiteOpenHelper 对象。
        // 可能你已经注意到了，你并不需要去编写「CREATE TABLE」这样的 SQL 语句，因为 greenDAO 已经帮你做了。
        // 注意：默认的 DaoMaster.DevOpenHelper 会在数据库升级时，删除所有的表，意味着这将导致数据的丢失。
        // 所以，在正式的项目中，你还应该做一层封装，来实现数据库的安全升级。
        mHelper = new DaoMaster.DevOpenHelper(this, "dbStockCount", null);
        db = mHelper.getWritableDatabase();
        // 注意：该数据库连接属于 DaoMaster，所以多个 Session 指的是相同的数据库连接。
        mDaoMaster = new DaoMaster(db);
        mDaoSession = mDaoMaster.newSession();
    }

    public DaoSession getDaoSession() {
        return mDaoSession;
    }

    public SQLiteDatabase getDb() {
        return db;
    }


    private final static String LOG_NAME_HEAD = "OCLog";
    private final static String LOG_SAVE_FOLDER = "/log/";
    private final static boolean SAVE_LOGS = true;

    /**
     * 创建日志文件
     *
     * @param throwable 要记录的异常
     * @return 执行结果
     */
    private boolean createLogs(Throwable throwable) {
        if (throwable == null || !SAVE_LOGS) {
            return false;
        }

        if (Build.VERSION.SDK_INT >= 23 && !checkPermission()) {
            Log.e("异常处理--保存日志", "保存失败 , Android 6.0+ 系统. 内存卡读写权限没有获取");
            return false;
        }

        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            //如果内存卡或内置储存已经挂载

            //创建储存目录
            String savePath = Environment.getExternalStorageDirectory().getPath() + LOG_SAVE_FOLDER;
            File file = new File(savePath);
            file.mkdirs();

            if (file.canWrite()) {
                //如果目录可以写入

                FileWriter fileWriter;
                PrintWriter printWriter;

                //得到当前的日期与时间 , 精确到秒
                String exceptionTime = DateFormat.format("yyyy-MM-dd hh:mm:ss", new Date()).toString();

                //创建日志文件对象
                file = new File(savePath + LOG_NAME_HEAD + "  " + exceptionTime + "  .log");
                try {
                    if (file.createNewFile()) {
                        //如果文件创建成功 , 则写入文件
                        fileWriter = new FileWriter(file, true);
                        printWriter = new PrintWriter(fileWriter);
                        printWriter.println("Date:" + exceptionTime + "\n");
                        printWriter.println("Exception Class Name: ");
                        printWriter.println(throwable.getStackTrace()[0].getClassName());
                        printWriter.println("");
                        printWriter.println("Exception Class Position: ");
                        printWriter.println("Line number: " + throwable.getStackTrace()[0].getLineNumber());
                        printWriter.println("");
                        printWriter.println("Exception Cause: ");
                        printWriter.println(throwable.getCause());
                        printWriter.println("");
                        printWriter.println("-----------------------------------\nException Message: \n");
                        for (int i = 0; i < throwable.getStackTrace().length; i++) {
                            printWriter.println(throwable.getStackTrace()[i]);
                        }
                        //清空与关闭用到的流
                        printWriter.flush();
                        fileWriter.flush();
                        printWriter.close();
                        fileWriter.close();
                        Log.w("异常处理--保存日志", "日志保存成功");
                        return true;
                    } else {
                        Log.e("异常处理--保存日志", "保存失败 , 存在相同名称的日志文件");
                        return false;
                    }
                } catch (IOException e) {
                    Log.e("异常处理--保存日志", "保存失败 , 无法创建日志文件或写入流失败");
                    return false;
                }

            } else {
                //目录不可写入 , 操作失败
                Log.e("异常处理--保存日志", "保存失败 , 无法写入目录");
                file = null;
                return false;
            }

        } else {
            Log.e("异常处理--保存日志", "保存失败 , 储存未挂载");
            return false;
        }

    }

    /**
     * 检查内存卡读写权限 针对Android 6.0+
     *
     * @return 是否有权限
     */
    @TargetApi(23)
    private boolean checkPermission() {
        return checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
    }

}
