/*
 * Copyright (c) 2016 Oracle and/or its affiliates.  All rights reserved.
 *
 * This software is dual-licensed to you under the MIT License (MIT) and
 * the Universal Permissive License (UPL).  See the LICENSE file in the root
 * directory for license terms.  You may choose either license, or both.
 */

package com.oracle.iot.sample.enterpriseclientsample;

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

import com.oracle.iot.client.trust.TrustedAssetsManager;

import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;

import oracle.iot.client.enterprise.EnterpriseClient;
import oracle.iot.client.enterprise.UserAuthenticationException;
import com.oracle.iot.sample.R;

public class EnterpriseClientUtil {
    private static EnterpriseClientUtil instance;
    private EnterpriseClient mECL;
    private DeviceModelLineItem dm;
    private String appName;
    private static TrustedAssetsManager tam;
    private AuthType authType;
    private DeviceListItem selectedDeviceToMonitor;
    private Context currentContext;


    private static final String ERROR_TAG = "IOT_ERROR";
    private static final String MESSAGE_TAG = "IOT_MESSAGE";

    private EnterpriseClientUtil(Context context) {
        if(context != null)
            currentContext = context;
        registerUncaughtHandler();
    }

    private EnterpriseClientUtil(String name,Context context) throws UserAuthenticationException{
        if(context != null)
            currentContext = context;
        registerUncaughtHandler();
        this.initializeECL(name, context);
    }

    private void registerUncaughtHandler(){
        Thread.UncaughtExceptionHandler uch = new Thread.UncaughtExceptionHandler() {
            public void uncaughtException(Thread th, Throwable ex) {
                if (ex.getCause()instanceof UserAuthenticationException) {
                    Log.d(MESSAGE_TAG, "Session Expired");
                    Context threadContext = EnterpriseClientUtil.getInstance(null).getCurrentContext();
                    if (threadContext != null) {
                        Intent intent = new Intent(threadContext, MainActivity.class);
                        threadContext.startActivity(intent);
                    }else {
                        Log.d(ERROR_TAG, "Session Expired, Unable to switch to Login Screen");
                    }
                }
            }
        };
        Thread.setDefaultUncaughtExceptionHandler(uch);
    }

    public static EnterpriseClientUtil getInstance(Context context)    {

        if(instance == null){
            instance = new EnterpriseClientUtil(context);
        }
        return instance;
    }

    public static EnterpriseClientUtil getInstance(String name, Context context) throws UserAuthenticationException{
        if(instance == null)        {
            instance = new EnterpriseClientUtil(name,context);
        }
        return instance;
    }

    public void initializeECL(String name,Context context)throws UserAuthenticationException{
        try {
            SharedPreferences mSharedPref = context.getSharedPreferences(
                    context.getString(R.string.preference_file_key), Context.MODE_PRIVATE);

            String path = mSharedPref.getString(context.getString(R.string.ta_file_path), "");
            String password = mSharedPref.getString(context.getString(R.string.ta_password),"");
            if(mSharedPref.getBoolean(context.getString(R.string.use_provided_bks), true)){
                mECL = EnterpriseClient.newClient(name, context);
            }else{
                mECL = EnterpriseClient.newClient(path,password, name, context);
            }
            appName =mECL.getApplication().getName();
        } catch (IOException e) {
            Log.e(ERROR_TAG, e.getMessage());
            e.printStackTrace();
        } catch (GeneralSecurityException e) {
            Log.e(ERROR_TAG, e.getMessage());
            e.printStackTrace();
        }
    }


    public EnterpriseClient getECL(){
        return this.mECL;
    }

    public DeviceListItem getSelectedDeviceToMonitor() {
        return selectedDeviceToMonitor;
    }

    public void setSelectedDeviceToMonitor(DeviceListItem selectedDeviceToMonitor) {
        this.selectedDeviceToMonitor = selectedDeviceToMonitor;
    }

    public Context getCurrentContext() {
        return currentContext;
    }

    public void setCurrentContext(Context currentContext) {
        this.currentContext = currentContext;
    }

    public AuthType getAuthType() {
        return authType;
    }

    public void setAuthType(AuthType authType) {
        this.authType = authType;
    }

    public DeviceModelLineItem getDM(){
        return this.dm;
    }

    public void setDM(DeviceModelLineItem a){
        dm = a;
    }

    public void setAppName(String app){
        this.appName = app;
    }

    public String getAppName(){
        return this.appName;
    }

    public static TrustedAssetsManager getTam(String path, String password, Context context) throws GeneralSecurityException{
        if(tam == null){
            if(path == null){
                tam = TrustedAssetsManager.Factory.getTrustedAssetsManager(context);
            }else{
                tam = TrustedAssetsManager.Factory.getTrustedAssetsManager(path, password, context);
            }
        }
        return tam;
    }

    public TrustedAssetsManager getTam(){
        return tam;
    }

    public static void reset(Context context)
    {
        Context appContext = context.getApplicationContext();
        // delete the previous provisioning file
        File[] files = appContext.getFilesDir().listFiles();
        for(File f : files){
            f.delete();
        }
        SharedPreferences pref = appContext.getSharedPreferences(
                context.getString(R.string.preference_file_key), Context.MODE_PRIVATE);
        SharedPreferences.Editor prefsEditor = pref.edit();
        prefsEditor.putString(context.getString(R.string.ta_password), "");
        prefsEditor.putString(context.getString(R.string.ta_file_path), "");
        prefsEditor.putBoolean(context.getString(R.string.use_provided_bks), false);
        prefsEditor.apply();
        instance = null;
    }

}
