package spacehunn.exploitr.deautherwebgui;


import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.location.LocationManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;

import com.crashlytics.android.Crashlytics;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView;
import com.thanosfisherman.wifiutils.WifiUtils;

import java.io.File;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import io.fabric.sdk.android.Fabric;


@SuppressLint({"SetTextI18n", "InflateParams", "SetJavaScriptEnabled"})
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

    public static final String TAG = "ESP8266LOG";
    public static final boolean isFinalBuild = true;
    WebView mainRender;
    DrawerLayout drawer;
    ListView listView;
    NavigationView navigationView;
    ProgressBar progressBar;

    static String[] perms = new String[]{
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.INTERNET,
            Manifest.permission.ACCESS_NETWORK_STATE,
            Manifest.permission.CHANGE_NETWORK_STATE,
            Manifest.permission.ACCESS_WIFI_STATE,
            Manifest.permission.CHANGE_WIFI_STATE
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        toolbar.setSubtitle("Deauth 'em all!");

        if (isFinalBuild) {
            Fabric.with(this, new Crashlytics());
            Crashlytics.setUserIdentifier(Build.FINGERPRINT);
            Crashlytics.setUserName(Build.DEVICE);
        }

        drawer = findViewById(R.id.drawer_layout);
        navigationView = findViewById(R.id.nav_view);
        progressBar = findViewById(R.id.progress);
        mainRender = findViewById(R.id.mainRender);

        for (String perm : perms) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
                    (checkSelfPermission(perm) != PackageManager.PERMISSION_GRANTED)) {
                requestPermissions(new String[]{perm}, 123);
                break;
            }
        }

        mainRender.post(() -> {
            if (Prefs.getInstance(getBaseContext()).isNew()) {
                new AlertDialog.Builder(MainActivity.this)
                        .setTitle("Info")
                        .setMessage("DeAuther Software target version *2.0.5*")
                        .setPositiveButton("Well", null)
                        .show();
                Prefs.getInstance(getBaseContext()).setOld();
            }
        });

        final WifiManager manager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
        if (manager != null && !manager.isWifiEnabled()) manager.setWifiEnabled(true);

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(view -> {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                final LocationManager manager1 = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
                if (manager1 != null && !manager1.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                    Toast.makeText(getApplicationContext(), "Ensure that GPS is enabled", Toast.LENGTH_LONG).show();
                    startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                }
                showScanResults();
            } else {
                showScanResults();
            }
        });

        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);

        drawer.addDrawerListener(toggle);
        toggle.syncState();

        navigationView.setNavigationItemSelectedListener(this);

        mainRender.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

        WebSettings settings = mainRender.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setCacheMode(WebSettings.LOAD_NO_CACHE);
        settings.setAppCacheEnabled(true);
        settings.setDomStorageEnabled(true);
        settings.setUseWideViewPort(true);
        settings.setSaveFormData(true);
        settings.setDatabaseEnabled(true);
        settings.setSupportZoom(true);
        settings.setDisplayZoomControls(true);

        mainRender.setWebViewClient(new WebViewClient() {

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {

                progressBar.setVisibility(View.VISIBLE);
                mainRender.setVisibility(View.INVISIBLE);
                findViewById(R.id.warn).setVisibility(View.INVISIBLE);

                if (url.contains("scan")) {
                    navigationView.setCheckedItem(R.id.action_apscan);
                }
                if (url.contains("ssid")) {
                    navigationView.setCheckedItem(R.id.action_ssid);
                }
                if (url.contains("attack")) {
                    navigationView.setCheckedItem(R.id.action_attacks);
                }
                if (url.contains("settings")) {
                    navigationView.setCheckedItem(R.id.action_settings);
                }

                new Handler().postDelayed(() -> mainRender.stopLoading(), 5000);

            }

            @Override
            public void onPageFinished(WebView view, String url) {
                String everyTitle = view.getTitle();
                if (everyTitle.contains("ESP8266") | everyTitle.contains("Deauther") | everyTitle.equals("ESP8266 Deauther")) { //too much?
                    findViewById(R.id.warn).setVisibility(View.INVISIBLE);
                    progressBar.setVisibility(View.INVISIBLE);
                    mainRender.setVisibility(View.VISIBLE);
                } else {
                    findViewById(R.id.warn).setVisibility(View.VISIBLE);
                    progressBar.setVisibility(View.INVISIBLE);
                    mainRender.setVisibility(View.INVISIBLE);
                }
            }
        });

        mainRender.setWebChromeClient(new WebChromeClient());

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            Drawable drawableProgress = DrawableCompat.wrap(progressBar.getIndeterminateDrawable());
            DrawableCompat.setTint(drawableProgress, Color.parseColor("#FFFFFFFF"));
            progressBar.setIndeterminateDrawable(DrawableCompat.unwrap(drawableProgress));
        } else {
            progressBar.getIndeterminateDrawable().setColorFilter(Color.parseColor("#FFFFFFFF"), PorterDuff.Mode.SRC_IN);
        }

        mainRender.loadUrl("http://192.168.4.1/"); // TODO CALL HIGHLIGHT
    }


    private void showScanResults() {

        View scanView = getLayoutInflater().inflate(R.layout.view_list, null);

        listView = scanView.findViewById(R.id.list);

        WifiManager manager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);

        if (manager != null) {
            manager.startScan();
        }

        Handler handlerX = new Handler();
        handlerX.post(new Runnable() {
            @Override
            public void run() {
                WifiUtils.withContext(getApplicationContext()).scanWifi(results -> {
                    List<String> arrayWIFIList = new ArrayList<>();
                    ScanResult result;
                    for (int i = 0; i < results.size(); i++) {
                        result = results.get(i);

                        Log.v(TAG, result.toString());
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            arrayWIFIList.add(i, result.SSID + "[" + (double) result.frequency / 1000 + "GHz" + "/" + result.level + "dBm" + "]"
                                    + result.capabilities + getChannelWidth(result.channelWidth));
                        } else {
                            arrayWIFIList.add(i, result.SSID + "[" + (double) result.frequency / 1000 + "GHz" + "/" + result.level + "dBm" + "]"
                                    + result.capabilities);
                        }
                    }

                    String[] stringArray = arrayWIFIList.toArray(new String[0]);

                    ArrayAdapter<?> adapter = new ArrayAdapter<Object>(MainActivity.this, R.layout.list_text, R.id.textList, stringArray);

                    adapter.notifyDataSetChanged();
                    listView.setAdapter(adapter);

                }).start();
                handlerX.postDelayed(this, TimeUnit.SECONDS.toMillis(10));
            }
        });

        if (Prefs.getInstance(getBaseContext()).isWIFIRand()) {
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (listView.getChildCount() > 0) {
                        for (int i = 0; i < listView.getChildCount(); i++) {
                            SecureRandom random = new SecureRandom(); /*  Just some beautifying */
                            int color = Color.argb(255, random.nextInt(200), random.nextInt(200), random.nextInt(255));
                            ((TextView) listView.getChildAt(i)).setTextColor(color);
                        }
                    }
                    handler.postDelayed(this, 250);
                }
            }, 100);
        }


        if (!MainActivity.this.isFinishing()) {
            new AlertDialog.Builder(MainActivity.this)
                    .setView(scanView)
                    .setTitle("WiFi Scan-results (Local)")
                    .setCancelable(false)
                    .setOnDismissListener(dialog -> {

                    })
                    .setNeutralButton("Help", (dialog, which) -> new AlertDialog.Builder(MainActivity.this)
                            .setMessage(R.string.help_scan)
                            .setCancelable(false)
                            .setPositiveButton("Okay", null)
                            .show())
                    .setPositiveButton("Close / Stop Scan", null).show();
        }
    }

    private String getChannelWidth(int mo) {
        switch (mo) {
            case 0:
                return "[20 MHz]";
            case 1:
                return "[40 MHz]";
            case 2:
                return "[80 MHz]";
            case 3:
                return "[160 MHz]";
            case 4:
                return "[80+80 MHz]";
            default:
                return "";
        }
    }

    @Override
    public void onBackPressed() {
        if (!mainRender.canGoBack()) {
            DrawerLayout drawer = findViewById(R.id.drawer_layout);
            if (drawer.isDrawerOpen(GravityCompat.START)) {
                drawer.closeDrawer(GravityCompat.START);
            } else {
                super.onBackPressed();
            }
        } else {
            mainRender.goBack();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

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


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        final boolean previous = Prefs.getInstance(getBaseContext()).isLogcatState();

        View mainOats = getLayoutInflater().inflate(R.layout.settings, null);

        Switch logcat = mainOats.findViewById(R.id.logcat);
        Switch wiRand = mainOats.findViewById(R.id.wiRand);
        final TextView location = mainOats.findViewById(R.id.location);

        File appDirectory = new File(Environment.getExternalStorageDirectory() + "/DeAuther");
        File logDirectory = new File(appDirectory + "/log");
        File logFile = new File(logDirectory, "logcat" + Prefs.getInstance(getBaseContext()).getTime() + ".txt");

        location.setText("Logcat will be saved to : " + logFile.getPath());

        logcat.setChecked(previous);
        wiRand.setChecked(Prefs.getInstance(getBaseContext()).isWIFIRand());

        if (Prefs.getInstance(getBaseContext()).isLogcatState()) {
            location.setVisibility(View.VISIBLE);
        }

        logcat.setOnCheckedChangeListener((buttonView, isChecked) -> {
            Prefs.getInstance(getBaseContext()).setIsLogcatEnabled(isChecked);
            if (isChecked) {
                location.setVisibility(View.VISIBLE);
            } else {
                location.setVisibility(View.GONE);
            }
        });

        wiRand.setOnCheckedChangeListener((buttonView, isChecked) -> Prefs.getInstance(getBaseContext()).setWIFIRand(isChecked));

        new AlertDialog.Builder(MainActivity.this)
                .setView(mainOats)
                .setTitle("Additional Config")
                .setPositiveButton("Okay", (dialog, which) -> {
                    if (!previous == Prefs.getInstance(getBaseContext()).isLogcatState()) {
                        Toast.makeText(getBaseContext(), "Start Application Manually", Toast.LENGTH_SHORT).show();
                        System.exit(0);
                    } else {
                        recreate();
                    }
                }).show();
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {

        int id = item.getItemId();

        if (id == R.id.action_apscan) {
            findViewById(R.id.warn).setVisibility(View.INVISIBLE);
            mainRender.loadUrl("http://192.168.4.1/scan.html");
        } else if (id == R.id.action_ssid) {
            findViewById(R.id.warn).setVisibility(View.INVISIBLE);
            mainRender.loadUrl("http://192.168.4.1/ssids.html");
        } else if (id == R.id.action_attacks) {
            findViewById(R.id.warn).setVisibility(View.INVISIBLE);
            mainRender.loadUrl("http://192.168.4.1/attack.html");
        } else if (id == R.id.action_settings) {
            findViewById(R.id.warn).setVisibility(View.INVISIBLE); // very foolish
            mainRender.loadUrl("http://192.168.4.1/settings.html");
        } else if (id == R.id.about) {
            if (!isFinishing()) {
                new AlertDialog.Builder(MainActivity.this)
                        .setTitle("About")
                        .setMessage("ESP8266 DeAuther is made and copyrighted by Stefan Kremser <aka SpaceHuhn>." +
                                "\n\n" +
                                "This additional application is made by Pratim Majumder and licensed under the terms of Apache 2.0." +
                                "\n\n" +
                                "You may obtain a copy of the License at:" +
                                "\n" +
                                "http://www.apache.org/licenses/LICENSE-2.0" +
                                "\n\n" +
                                "This application doesn't perform any attack!! And, it's totally unharmful to any WiFi comm. systems" +
                                "\n\n" +
                                "NavBar image from Pinterest" +
                                "\n\n" +
                                "Application icon and icon style © Pratim Majumder" +
                                "\n\n" +
                                "Some icons are © Google and distributed under the terms of Apache 2.0" +
                                "\n\n" +
                                "DeAuther Software target version 2.0.5")
                        .show();
            }
        }
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(MainActivity.this, "Permission Granted", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(MainActivity.this, "Permission denied", Toast.LENGTH_SHORT).show();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                finishAndRemoveTask();
            } else {
                finish();
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

}