package com.suyashsrijan.forcedoze;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.InputType;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ListView;

import com.afollestad.materialdialogs.MaterialDialog;
import com.nanotasks.BackgroundWork;
import com.nanotasks.Completion;
import com.nanotasks.Tasks;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;

import eu.chainfire.libsuperuser.Shell;

public class WhitelistAppsActivity extends AppCompatActivity {
    ListView listView;
    SharedPreferences sharedPreferences;
    AppsAdapter whitelistAppsAdapter;
    ArrayList<String> whitelistedPackages;
    ArrayList<AppsItem> listData;
    public static String TAG = "ForceDoze";
    boolean showDozeWhitelistWarning = true;
    boolean isSuAvailable = false;
    MaterialDialog progressDialog = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_whitelist_apps);

        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        }

        listView = (ListView) findViewById(R.id.listView2);
        whitelistedPackages = new ArrayList<>();
        listData = new ArrayList<>();
        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        whitelistAppsAdapter = new AppsAdapter(this, listData);
        listView.setAdapter(whitelistAppsAdapter);
        loadPackagesFromWhitelist();
        isSuAvailable = sharedPreferences.getBoolean("isSuAvailable", false);
        showDozeWhitelistWarning = sharedPreferences.getBoolean("showDozeWhitelistWarning", true);

        if (showDozeWhitelistWarning) {
            displayDialog(getString(R.string.whitelisting_text), getString(R.string.whitelisted_apps_restrictions_text));
            SharedPreferences.Editor editor = sharedPreferences.edit();
            editor.putBoolean("showDozeWhitelistWarning", false);
            editor.apply();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.whitelist_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id) {
            case R.id.action_add_whitelist:
                startActivityForResult(new Intent(WhitelistAppsActivity.this, PackageChooserActivity.class), 999);
                break;
            case R.id.action_remove_whitelist:
                startActivityForResult(new Intent(WhitelistAppsActivity.this, PackageChooserActivity.class), 998);
                break;
            case R.id.action_add_whitelist_package:
                showManuallyAddPackageDialog();
                break;
            case R.id.action_remove_whitelist_package:
                showManuallyRemovePackageDialog();
                break;
            case R.id.action_whitelist_more_info:
                displayDialog(getString(R.string.whitelisting_text), getString(R.string.whitelisted_apps_restrictions_text));
                break;
            case R.id.action_launch_system_whitelist:
                startActivity(new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS));
            case android.R.id.home:
                onBackPressed();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (data != null) {
            if (requestCode == 999) {
                String pkg = data.getStringExtra("package_name");
                verifyAndAddPackage(pkg);
            } else if (requestCode == 998) {
                String pkg = data.getStringExtra("package_name");
                verifyAndRemovePackage(pkg);
            }
        }
    }

    public void loadPackagesFromWhitelist() {
        Log.i(TAG, "Loading whitelisted packages...");
        progressDialog = new MaterialDialog.Builder(this)
                .title(getString(R.string.please_wait_text))
                .autoDismiss(false)
                .cancelable(false)
                .content(R.string.loading_whitelisted_packages)
                .progress(true, 0)
                .show();

        Tasks.executeInBackground(WhitelistAppsActivity.this, new BackgroundWork<List<String>>() {
            @Override
            public List<String> doInBackground() throws Exception {
                List<String> output;
                List<String> packages = new ArrayList<>();
                output = Shell.SH.run("dumpsys deviceidle whitelist");
                for (String s : output) {
                    packages.add(s.split(",")[1]);
                }

                return new ArrayList<>(new LinkedHashSet<>(packages));
            }
        }, new Completion<List<String>>() {
            @Override
            public void onSuccess(Context context, List<String> result) {
                if (progressDialog != null) {
                    progressDialog.dismiss();
                }

                if (!result.isEmpty()) {
                    if (!listData.isEmpty() || !whitelistedPackages.isEmpty()) {
                        listData.clear();
                        whitelistedPackages.clear();
                    }
                    for (String r : result) {
                        AppsItem appItem = new AppsItem();
                        appItem.setAppPackageName(r);
                        whitelistedPackages.add(r);
                        try {
                            appItem.setAppName(getPackageManager().getApplicationLabel(getPackageManager().getApplicationInfo(r, PackageManager.GET_META_DATA)).toString());
                        } catch (PackageManager.NameNotFoundException e) {
                            appItem.setAppName("System package");
                        }
                        listData.add(appItem);
                    }
                    whitelistAppsAdapter.notifyDataSetChanged();
                }

                Log.i(TAG, "Whitelisted packages: " + listData.size() + " packages in total");
            }

            @Override
            public void onError(Context context, Exception e) {
                Log.e(TAG, "Error loading packages: " + e.getMessage());

            }
        });
    }

    public void showManuallyAddPackageDialog() {
        new MaterialDialog.Builder(this)
                .title(getString(R.string.whitelist_apps_setting_text))
                .content(R.string.manually_add_package_dialog_text)
                .inputType(InputType.TYPE_CLASS_TEXT)
                .input("com.spotify.music", "", false, new MaterialDialog.InputCallback() {
                    @Override
                    public void onInput(MaterialDialog dialog, CharSequence input) {
                        verifyAndAddPackage(input.toString());
                    }
                }).show();
    }

    public void showManuallyRemovePackageDialog() {
        new MaterialDialog.Builder(this)
                .title(getString(R.string.whitelist_apps_setting_text))
                .content(R.string.manually_remove_package_dialog_text)
                .inputType(InputType.TYPE_CLASS_TEXT)
                .input("com.spotify.music", "", false, new MaterialDialog.InputCallback() {
                    @Override
                    public void onInput(MaterialDialog dialog, CharSequence input) {
                        verifyAndRemovePackage(input.toString());
                    }
                }).show();
    }


    public void verifyAndAddPackage(String packageName) {
        if (whitelistedPackages.contains(packageName)) {
            displayDialog(getString(R.string.info_text), getString(R.string.app_already_whitelisted_text));
        } else {
            modifyWhitelist(packageName, false);
            loadPackagesFromWhitelist();
        }
    }

    public void verifyAndRemovePackage(String packageName) {
        if (!whitelistedPackages.contains(packageName)) {
            displayDialog(getString(R.string.info_text), getString(R.string.app_not_whitelisted_text));
        } else {
            modifyWhitelist(packageName, true);
            loadPackagesFromWhitelist();
        }
    }

    public void modifyWhitelist(String packageName, boolean remove) {
        if (remove) {
            Log.i(TAG, "Removing app " + packageName + " from Doze whitelist");
            executeCommand("dumpsys deviceidle whitelist -" + packageName);
        } else {
            Log.i(TAG, "Adding app " + packageName + " to Doze whitelist");
            executeCommand("dumpsys deviceidle whitelist +" + packageName);
        }
    }

    public void displayDialog(String title, String message) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.AppCompatAlertDialogStyle);
        builder.setTitle(title);
        builder.setMessage(message);
        builder.setPositiveButton(getString(R.string.close_button_text), null);
        builder.show();
    }

    public void executeCommand(final String command) {
        if (Utils.isDeviceRunningOnN() && isSuAvailable) {
            Shell.SU.run(command);
        } else {
            Shell.SH.run(command);
        }
    }
}