/*
 * Copyright (c) 2017 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;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Scanner;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.annotation.NonNull;
import android.content.pm.PackageManager;
import android.Manifest;
import android.widget.CheckBox;

public class SelectProvisioningActivity  extends Activity {
    private final String ERROR_TAG = "IOT_ERROR";
    Activity activity;
    private final int PERMISSION_CODE = 123;
    /**
     * Set useDevicePolicy to true/false to enable/disable using policies in this sample.
     * Default value: false.
     */
    private static boolean useDevicePolicy = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        if (getIntent().getBooleanExtra("EXIT", false)) {
            finish();
            System.exit(0);
        }
        if (getIntent().getBooleanExtra("RESET", false)) {
            clearProperties();
            getIntent().removeExtra("RESET");
        }
        super.onCreate(savedInstanceState);
        activity = this;

        setContentView(R.layout.activity_choose_provision);
        Button selectButton = (Button) findViewById(R.id.file_selection_button);
        //Button createButton = (Button) findViewById(R.id.create_file_button);
        Button networkButton = (Button) findViewById(R.id.network_provision_button);

        final CheckBox checkBoxUseDevicePolicy = (CheckBox) findViewById(R.id.checkBox);
        checkBoxUseDevicePolicy.setChecked(useDevicePolicy);
        checkBoxUseDevicePolicy.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SharedPreferences pref = getApplicationContext().getSharedPreferences(
                        getString(R.string.preference_file_key), Context.MODE_PRIVATE);
                SharedPreferences.Editor prefsEditor = pref.edit();
                prefsEditor.putBoolean("useDevicePolicy",checkBoxUseDevicePolicy.isChecked());
                prefsEditor.apply();
            }
        });

        selectButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent anIntent = new Intent(SelectProvisioningActivity.this,
                        ProvisioningInformationActivity.class);
                anIntent.putExtra("NEXT_INTENT", "MainActivity");
                startActivity(anIntent);
                finish();
            }
        });

        networkButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent anIntent;
                // Prepare file for NetworkProvision
                String destinationFileName = getApplicationContext()
                        .getFilesDir().getPath() + "/bootstraper.conf";
                try {
                    File file = new File(destinationFileName);
                    // Recreate file to accept new one
                    if (file.exists()) {
                        file.delete();
                        file.createNewFile();
                    }
                } catch (IOException ex) {
                    AlertDialog builder = new AlertDialog.Builder(activity).create();
                    builder.setTitle("Error");
                    builder.setMessage("Can not create file " +
                                       "for Network Provision " +
                                       ex.getMessage());
                    builder.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                                new DialogInterface.OnClickListener() {
                                    public void onClick(DialogInterface dialog, int which) {
                                        dialog.dismiss();
                                    }
                                });
                    builder.show();
                    Log.e(ERROR_TAG, "Can not create file for Network Provision "
                            + ex.getMessage());
                    return;
                }
                SharedPreferences pref = getApplicationContext().getSharedPreferences(
                    getString(R.string.preference_file_key), Context.MODE_PRIVATE);

                // if password was not preconfigured
                String pass = pref.getString(getString(R.string.ta_password),"");
                if (pass == null || pass.length() == 0) {
                    SharedPreferences.Editor prefsEditor = pref.edit();
                    prefsEditor.putString(getString(R.string.ta_file_path), destinationFileName);
                    prefsEditor.putString(getString(R.string.ta_file_path_orig), destinationFileName);
                    prefsEditor.putBoolean(getString(R.string.use_provided_bks), false);
                    prefsEditor.apply();

                    anIntent = new Intent(SelectProvisioningActivity.this,
                            ProvisioningInformationActivity.class);
                    anIntent.putExtra("NEXT_INTENT", "NetworkProvisionActivity");
                } else {
                    anIntent = new Intent(SelectProvisioningActivity.this,
                            NetworkProvisionActivity.class);
                }
                anIntent.putExtra("useDevicePolicy",checkBoxUseDevicePolicy.isChecked());
                startActivity(anIntent);
                finish();
            }
        });

        if(ContextCompat.checkSelfPermission(activity.getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(activity,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    PERMISSION_CODE);

        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (!getIntent().getBooleanExtra("RESET", false)) {
            if (isProvisioned()) {
                if(!needUserInput()) {
                    // properties have already been set. go to main activity
                    Class<?> mainActivity = null;
                    Exception e = null;
                    try {
                        mainActivity = Class.forName("com.oracle.iot.sample.MainActivity");
                    } catch (ClassNotFoundException ex1) {
                        try {
                            mainActivity = Class.forName("com.oracle.iot.sample.ext.MainActivity");
                        } catch (ClassNotFoundException ex2) {
                            try {
                                mainActivity = Class.forName("com.oracle.iot.sample.enterpriseclientsample.MainActivity");
                            } catch (ClassNotFoundException ex3) {
                                e = ex3;
                            }
                        }
                    }
                    if (e == null) {
                        Intent anIntent = new Intent(SelectProvisioningActivity.this, mainActivity);
                        startActivity(anIntent);
                        finish();
                    } else {
                        Log.d(ERROR_TAG, "MainActivity was not found");
                    }
                    return;
                } else {
                    // properties have already been set except password
                    Intent anIntent = new Intent(SelectProvisioningActivity.this, ProvisioningInformationActivity.class);
                    startActivity(anIntent);
                    finish();
                    return;
                }
            }
        }
    }

    private boolean isProvisioned() {
        // Check properties
        SharedPreferences pref = getApplicationContext().getSharedPreferences(
            getString(R.string.preference_file_key), Context.MODE_PRIVATE);
        String bksPath = pref.getString(getString(R.string.ta_file_path), "");
        if (bksPath.equals("")) {
            // Read last known file
            try (FileInputStream fis = openFileInput(getString(R.string.last_known))) {
                if (fis.available() > 0) {
                    byte [] fileBytes = new byte[fis.available()];
                    fis.read(fileBytes);
                    SharedPreferences.Editor prefsEditor = pref.edit();
                    String filePath = new String(fileBytes);
                    if (new File(filePath).exists() && new File(filePath).canRead()
                        && new File(filePath).isFile() && new File(filePath).length() > 0) {
                        prefsEditor.putString(getString(R.string.ta_file_path), new String(fileBytes));
                        return true;
                    } else {
                        deleteFile(getString(R.string.last_known));
                    }
                }
            } catch (IOException ex) {
                Log.d(ERROR_TAG, "Can not safe to internal storage");
            }
            return isBKSProvided();
        } else {
            return true;
        }
    }

    private boolean needUserInput() {
        SharedPreferences pref = getApplicationContext().getSharedPreferences(
                getString(R.string.preference_file_key), Context.MODE_PRIVATE);
        SharedPreferences.Editor prefsEditor = pref.edit();
        String bksPath = pref.getString(getString(R.string.ta_file_path), "");
        boolean useProvidedBKS = bksPath.equals("");
        boolean bksProvided = isBKSProvided();
        int flags = this.getIntent().getFlags();
        if(!getIntent().getBooleanExtra("RESET", false)) {
            // starting for the first time
            if(useProvidedBKS){
                if(bksProvided){
                    prefsEditor.putBoolean(getString(R.string.use_provided_bks), true);
                    prefsEditor.apply();
                    return false;
                } else {
                    prefsEditor.putBoolean(getString(R.string.use_provided_bks), false);
                    prefsEditor.apply();
                    return true;
                }
            }else{
                prefsEditor.putBoolean(getString(R.string.use_provided_bks), false);
                prefsEditor.apply();

                File bksFile = new File(bksPath);
                if(bksFile.exists() && !bksFile.isDirectory()){
                    // already have a stored bks, use that one, no need to show user the input screen
                    return false;
                }
                return true;
            }
        } else {
            clearProperties();
        }
        return true;
    }

    private boolean isBKSProvided() {
        InputStream configInStream = null;
        boolean bksProvided = false;
        try {
            configInStream = (InputStream) getApplicationContext().getAssets().open("trustedAssets.properties");
            Properties config = new Properties();
            config.load(configInStream);
            String taStoreFileName = config.getProperty("oracle.iot.client.trustedAssetsStore","");
            if(!taStoreFileName.equals("")){
                InputStream is = (InputStream) getApplicationContext().getAssets().open(taStoreFileName);
                bksProvided = true;
                is.close();
            }
        } catch (Exception ex) {
            Log.d(ERROR_TAG, "BKS Not provided" + ex.toString());
        } finally {
            try {
                if (configInStream != null) {
                    configInStream.close();
                }
            } catch (IOException ex) {
            }
        }
        return bksProvided;
    }
    
    private void clearProperties() {
        // Clear
        SharedPreferences pref = getApplicationContext().getSharedPreferences(
            getString(R.string.preference_file_key), Context.MODE_PRIVATE);
        SharedPreferences.Editor prefsEditor = pref.edit();
        prefsEditor.remove(getString(R.string.ta_file_path));
        prefsEditor.remove(getString(R.string.ta_file_path_orig));
        prefsEditor.remove(getString(R.string.use_provided_bks));
        prefsEditor.remove(getString(R.string.ta_password));
        deleteFile(getString(R.string.last_known));
        prefsEditor.apply();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        if (requestCode == PERMISSION_CODE) {
            if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                Log.d(ERROR_TAG, "Storage permission was not granted");
            }
        }
    }
}
