/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.chromium.latency.walt;

import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.StrictMode;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.Loader;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import org.chromium.latency.walt.programmer.Programmer;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.Locale;

import static org.chromium.latency.walt.Utils.getBooleanPreference;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "WALT";
    private static final int PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE_SHARE_LOG = 2;
    private static final int PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE_SYSTRACE = 3;
    private static final int PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE_WRITE_LOG = 4;
    private static final int PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE_CLEAR_LOG = 5;

    private static final String LOG_FILENAME = "qstep_log.txt";

    private Toolbar toolbar;
    LocalBroadcastManager broadcastManager;
    private SimpleLogger logger;
    private WaltDevice waltDevice;
    public Menu menu;

    public Handler handler = new Handler();

    private Fragment mRobotAutomationFragment;


    /**
     * A method to display exceptions on screen. This is very useful because our USB port is taken
     * and we often need to debug without adb.
     * Based on this article:
     * https://trivedihardik.wordpress.com/2011/08/20/how-to-avoid-force-close-error-in-android/
     */
    public class LoggingExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler {

        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
            StringWriter stackTrace = new StringWriter();
            ex.printStackTrace(new PrintWriter(stackTrace));
            String msg = "WALT crashed with the following exception:\n" + stackTrace;

            // Fire a new activity showing the stack trace
            Intent intent = new Intent(MainActivity.this, CrashLogActivity.class);
            intent.putExtra("crash_log", msg);
            MainActivity.this.startActivity(intent);

            // Terminate this process
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(10);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        final UsbDevice usbDevice;
        Intent intent = getIntent();
        if (intent != null && intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
            setIntent(null); // done with the intent
            usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
        } else {
            usbDevice = null;
        }

        // Connect and sync clocks, but a bit later as it takes time
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (usbDevice == null) {
                    waltDevice.connect();
                } else {
                    waltDevice.connect(usbDevice);
                }
            }
        }, 1000);

        if (intent != null && AutoRunFragment.TEST_ACTION.equals(intent.getAction())) {
            getSupportFragmentManager().popBackStack("Automated Test",
                    FragmentManager.POP_BACK_STACK_INCLUSIVE);
            Fragment autoRunFragment = new AutoRunFragment();
            autoRunFragment.setArguments(intent.getExtras());
            switchScreen(autoRunFragment, "Automated Test");
        }

        // Handle robot automation originating from adb shell am
        if (intent != null && Intent.ACTION_SEND.equals(intent.getAction())) {
            Log.e(TAG, "Received Intent: " + intent.toString());
            String test = intent.getStringExtra("StartTest");
            if (test != null) {
                Log.e(TAG, "Extras \"StartTest\" = " + test);
                if ("TapLatencyTest".equals(test)) {
                    mRobotAutomationFragment = new TapLatencyFragment();
                    switchScreen(mRobotAutomationFragment, "Tap Latency");
                } else if ("ScreenResponseTest".equals(test)) {
                    mRobotAutomationFragment = new ScreenResponseFragment();
                    switchScreen(mRobotAutomationFragment, "Screen Response");
                } else if ("DragLatencyTest".equals(test)) {
                    mRobotAutomationFragment = new DragLatencyFragment();
                    switchScreen(mRobotAutomationFragment, "Drag Latency");
                }
            }

            String robotEvent = intent.getStringExtra("RobotAutomationEvent");
            if (robotEvent != null && mRobotAutomationFragment != null) {
                Log.e(TAG, "Received robot automation event=\"" + robotEvent + "\", Fragment = " +
                        mRobotAutomationFragment);
                // Writing and clearing the log is not fragment-specific, so handle them here.
                if (robotEvent.equals(RobotAutomationListener.WRITE_LOG_EVENT)) {
                    attemptSaveLog();
                } else if (robotEvent.equals(RobotAutomationListener.CLEAR_LOG_EVENT)) {
                    attemptClearLog();
                } else {
                    // All other robot automation events are forwarded to the current fragment.
                    ((RobotAutomationListener) mRobotAutomationFragment)
                            .onRobotAutomationEvent(robotEvent);
                }
            }
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Thread.setDefaultUncaughtExceptionHandler(new LoggingExceptionHandler());
        setContentView(R.layout.activity_main);

        // App bar
        toolbar = (Toolbar) findViewById(R.id.toolbar_main);
        setSupportActionBar(toolbar);
        getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
            @Override
            public void onBackStackChanged() {
                int stackTopIndex = getSupportFragmentManager().getBackStackEntryCount() - 1;
                if (stackTopIndex >= 0) {
                    toolbar.setTitle(getSupportFragmentManager().getBackStackEntryAt(stackTopIndex).getName());
                } else {
                    toolbar.setTitle(R.string.app_name);
                    getSupportActionBar().setDisplayHomeAsUpEnabled(false);
                    // Disable fullscreen mode
                    getSupportActionBar().show();
                    getWindow().getDecorView().setSystemUiVisibility(0);
                }
            }
        });

        waltDevice = WaltDevice.getInstance(this);

        // Create front page fragment
        FrontPageFragment frontPageFragment = new FrontPageFragment();
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.add(R.id.fragment_container, frontPageFragment);
        transaction.commit();

        logger = SimpleLogger.getInstance(this);
        broadcastManager = LocalBroadcastManager.getInstance(this);

        // Add basic version and device info to the log
        logger.log(String.format("WALT v%s  (versionCode=%d)",
                BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE));
        logger.log("WALT protocol version " + WaltDevice.PROTOCOL_VERSION);
        logger.log("DEVICE INFO:");
        logger.log("  " + Build.FINGERPRINT);
        logger.log("  Build.SDK_INT=" + Build.VERSION.SDK_INT);
        logger.log("  os.version=" + System.getProperty("os.version"));

        // Set volume buttons to control media volume
        setVolumeControlStream(AudioManager.STREAM_MUSIC);
        requestSystraceWritePermission();
        // Allow network operations on the main thread
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        this.menu = menu;
        return true;
    }

    public void toast(String msg) {
        logger.log(msg);
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public boolean onSupportNavigateUp() {
        // Go back when the back or up button on toolbar is clicked
        getSupportFragmentManager().popBackStack();
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.

        Log.i(TAG, "Toolbar button: " + item.getTitle());

        switch (item.getItemId()) {
            case R.id.action_help:
                return true;
            case R.id.action_share:
                attemptSaveAndShareLog();
                return true;
            case R.id.action_upload:
                showUploadLogDialog();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // Handlers for main menu clicks
    ////////////////////////////////////////////////////////////////////////////////////////////////

    private void switchScreen(Fragment newFragment, String title) {
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        toolbar.setTitle(title);
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.fragment_container, newFragment);
        transaction.addToBackStack(title);
        transaction.commit();
    }

    public void onClickClockSync(View view) {
        DiagnosticsFragment diagnosticsFragment = new DiagnosticsFragment();
        switchScreen(diagnosticsFragment, "Diagnostics");
    }

    public void onClickTapLatency(View view) {
        TapLatencyFragment newFragment = new TapLatencyFragment();
        requestSystraceWritePermission();
        switchScreen(newFragment, "Tap Latency");
    }

    public void onClickScreenResponse(View view) {
        ScreenResponseFragment newFragment = new ScreenResponseFragment();
        requestSystraceWritePermission();
        switchScreen(newFragment, "Screen Response");
    }

    public void onClickAudio(View view) {
        AudioFragment newFragment = new AudioFragment();
        switchScreen(newFragment, "Audio Latency");
    }

    public void onClickMIDI(View view) {
        if (MidiFragment.hasMidi(this)) {
            MidiFragment newFragment = new MidiFragment();
            switchScreen(newFragment, "MIDI Latency");
        } else {
            toast("This device does not support MIDI");
        }
    }

    public void onClickDragLatency(View view) {
        DragLatencyFragment newFragment = new DragLatencyFragment();
        switchScreen(newFragment, "Drag Latency");
    }

    public void onClickOpenLog(View view) {
        LogFragment logFragment = new LogFragment();
        // menu.findItem(R.id.action_help).setVisible(false);
        switchScreen(logFragment, "Log");
    }

    public void onClickOpenAbout(View view) {
        AboutFragment aboutFragment = new AboutFragment();
        switchScreen(aboutFragment, "About");
    }

    public void onClickOpenSettings(View view) {
        SettingsFragment settingsFragment = new SettingsFragment();
        switchScreen(settingsFragment, "Settings");
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // Handlers for diagnostics menu clicks
    ////////////////////////////////////////////////////////////////////////////////////////////////
    public void onClickReconnect(View view) {
        waltDevice.connect();
    }

    public void onClickPing(View view) {
        long t1 = waltDevice.clock.micros();
        try {
            waltDevice.command(WaltDevice.CMD_PING);
            long dt = waltDevice.clock.micros() - t1;
            logger.log(String.format(Locale.US,
                    "Ping reply in %.1fms", dt / 1000.
            ));
        } catch (IOException e) {
            logger.log("Error sending ping: " + e.getMessage());
        }
    }

    public void onClickStartListener(View view) {
        if (waltDevice.isListenerStopped()) {
            try {
                waltDevice.startListener();
            } catch (IOException e) {
                logger.log("Error starting USB listener: " + e.getMessage());
            }
        } else {
            waltDevice.stopListener();
        }
    }

    public void onClickSync(View view) {
        try {
            waltDevice.syncClock();
        } catch (IOException e) {
            logger.log("Error syncing clocks: " + e.getMessage());
        }
    }

    public void onClickCheckDrift(View view) {
        waltDevice.checkDrift();
    }

    public void onClickProgram(View view) {
        if (waltDevice.isConnected()) {
            // show dialog telling user to first press white button
            final AlertDialog dialog = new AlertDialog.Builder(this)
                .setTitle("Press white button")
                .setMessage("Please press the white button on the WALT device.")
                .setCancelable(false)
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {}
                }).show();

            waltDevice.setConnectionStateListener(new WaltConnection.ConnectionStateListener() {
                @Override
                public void onConnect() {}

                @Override
                public void onDisconnect() {
                    dialog.cancel();
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            new Programmer(MainActivity.this).program();
                        }
                    }, 1000);
                }
            });
        } else {
            new Programmer(this).program();
        }
    }

    private void attemptSaveAndShareLog() {
        int currentPermission = ContextCompat.checkSelfPermission(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (currentPermission == PackageManager.PERMISSION_GRANTED) {
            String filePath = saveLogToFile();
            shareLogFile(filePath);
        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE_SHARE_LOG);
        }
    }

    private void attemptSaveLog() {
        int currentPermission = ContextCompat.checkSelfPermission(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (currentPermission == PackageManager.PERMISSION_GRANTED) {
            saveLogToFile();
        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE_WRITE_LOG);
        }
    }

    private void attemptClearLog() {
        int currentPermission = ContextCompat.checkSelfPermission(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE);
        if (currentPermission == PackageManager.PERMISSION_GRANTED) {
            clearLogFile();
        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE_CLEAR_LOG);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        final boolean isPermissionGranted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
        if (!isPermissionGranted) {
            logger.log("Could not get permission to write file to storage");
            return;
        }
        switch (requestCode) {
            case PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE_SHARE_LOG:
                attemptSaveAndShareLog();
                break;
            case PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE_WRITE_LOG:
                attemptSaveLog();
                break;
            case PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE_CLEAR_LOG:
                attemptClearLog();
                break;
        }
    }

    public String saveLogToFile() {

        // Save to file to later fire an Intent.ACTION_SEND
        // This allows to either send the file as email attachment
        // or upload it to Drive.

        // The permissions for attachments are a mess, writing world readable files
        // is frowned upon, but deliberately giving permissions as part of the intent is
        // way too cumbersome.

        // A reasonable world readable location,on many phones it's /storage/emulated/Documents
        // TODO: make this location configurable?
        File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
        File file = null;
        FileOutputStream outStream = null;

        try {
            if (!path.exists()) {
                path.mkdirs();
            }
            file = new File(path, LOG_FILENAME);
            logger.log("Saving log to: " + file + " at " + new Date());

            outStream = new FileOutputStream(file);
            outStream.write(logger.getLogText().getBytes());

            outStream.close();
            logger.log("Log saved");
        } catch (Exception e) {
            e.printStackTrace();
            logger.log("Failed to write log: " + e.getMessage());
        }
        return file.getPath();
    }

    public void clearLogFile() {
        File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
        try {
            File file = new File(path, LOG_FILENAME);
            file.delete();
        } catch (Exception e) {
            e.printStackTrace();
            logger.log("Failed to clear log: " + e.getMessage());
        }
    }

    public void shareLogFile(String filepath) {
        File file = new File(filepath);
        logger.log("Firing Intent.ACTION_SEND for file:");
        logger.log(file.getPath());

        Intent i = new Intent(Intent.ACTION_SEND);
        i.setType("text/plain");

        i.putExtra(Intent.EXTRA_SUBJECT, "WALT log");
        i.putExtra(Intent.EXTRA_TEXT, "Attaching log file " + file.getPath());
        i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));

        try {
            startActivity(Intent.createChooser(i, "Send mail..."));
        } catch (android.content.ActivityNotFoundException ex) {
            toast("There are no email clients installed.");
        }
    }

    private static boolean startsWithHttp(String url) {
        return url.toLowerCase().startsWith("http://") || url.toLowerCase().startsWith("https://");
    }

    private void showUploadLogDialog() {
        final AlertDialog dialog = new AlertDialog.Builder(this)
                .setTitle("Upload log to URL")
                .setView(R.layout.dialog_upload)
                .setPositiveButton("Upload", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {}
                })
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {}
                })
                .show();
        final EditText editText = (EditText) dialog.findViewById(R.id.edit_text);
        editText.setText(Utils.getStringPreference(
                MainActivity.this, R.string.preference_log_url, ""));
        dialog.getButton(AlertDialog.BUTTON_POSITIVE).
                setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                View progress = dialog.findViewById(R.id.progress_bar);
                String urlString = editText.getText().toString();
                if (!startsWithHttp(urlString)) {
                    urlString = "http://" + urlString;
                }
                editText.setVisibility(View.GONE);
                progress.setVisibility(View.VISIBLE);
                LogUploader uploader = new LogUploader(MainActivity.this, urlString);
                final String finalUrlString = urlString;
                uploader.registerListener(1, new Loader.OnLoadCompleteListener<Integer>() {
                    @Override
                    public void onLoadComplete(Loader<Integer> loader, Integer data) {
                        dialog.cancel();
                        if (data == -1) {
                            Toast.makeText(MainActivity.this,
                                    "Failed to upload log", Toast.LENGTH_SHORT).show();
                            return;
                        } else if (data / 100 == 2) {
                            Toast.makeText(MainActivity.this,
                                    "Log successfully uploaded", Toast.LENGTH_SHORT).show();
                        } else {
                            Toast.makeText(MainActivity.this,
                                    "Failed to upload log. Server returned status code " + data,
                                    Toast.LENGTH_SHORT).show();
                        }
                        SharedPreferences preferences = PreferenceManager
                                .getDefaultSharedPreferences(MainActivity.this);
                        preferences.edit().putString(
                                getString(R.string.preference_log_url), finalUrlString).apply();
                    }
                });
                uploader.startUpload();
            }
        });
    }

    private void requestSystraceWritePermission() {
        if (getBooleanPreference(this, R.string.preference_systrace, true)) {
            int currentPermission = ContextCompat.checkSelfPermission(this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE);
            if (currentPermission != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE_SYSTRACE);
            }
        }
    }

}
