/*
 * 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 com.android.shell;

import static com.android.shell.BugreportPrefs.STATE_SHOW;
import static com.android.shell.BugreportPrefs.getWarningState;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import libcore.io.Streams;

import com.google.android.collect.Lists;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Parcelable;
import android.os.Process;
import android.os.SystemProperties;
import android.support.v4.content.FileProvider;
import android.text.format.DateUtils;
import android.util.Log;
import android.util.Patterns;
import android.util.SparseArray;
import android.widget.Toast;

/**
 * Service used to keep progress of bug reports processes ({@code dumpstate}).
 * <p>
 * The workflow is:
 * <ol>
 * <li>When {@code dumpstate} starts, it sends a {@code BUGREPORT_STARTED} with its pid and the
 * estimated total effort.
 * <li>{@link BugreportReceiver} receives the intent and delegates it to this service.
 * <li>Upon start, this service:
 * <ol>
 * <li>Issues a system notification so user can watch the progresss (which is 0% initially).
 * <li>Polls the {@link SystemProperties} for updates on the {@code dumpstate} progress.
 * <li>If the progress changed, it updates the system notification.
 * </ol>
 * <li>As {@code dumpstate} progresses, it updates the system property.
 * <li>When {@code dumpstate} finishes, it sends a {@code BUGREPORT_FINISHED} intent.
 * <li>{@link BugreportReceiver} receives the intent and delegates it to this service, which in
 * turn:
 * <ol>
 * <li>Updates the system notification so user can share the bug report.
 * <li>Stops monitoring that {@code dumpstate} process.
 * <li>Stops itself if it doesn't have any process left to monitor.
 * </ol>
 * </ol>
 */
public class BugreportProgressService extends Service {
    private static final String TAG = "Shell";
    private static final boolean DEBUG = false;

    private static final String AUTHORITY = "com.android.shell";

    static final String INTENT_BUGREPORT_STARTED = "android.intent.action.BUGREPORT_STARTED";
    static final String INTENT_BUGREPORT_FINISHED = "android.intent.action.BUGREPORT_FINISHED";

    static final String EXTRA_BUGREPORT = "android.intent.extra.BUGREPORT";
    static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT";
    static final String EXTRA_PID = "android.intent.extra.PID";
    static final String EXTRA_MAX = "android.intent.extra.MAX";
    static final String EXTRA_NAME = "android.intent.extra.NAME";
    static final String EXTRA_ORIGINAL_INTENT = "android.intent.extra.ORIGINAL_INTENT";

    private static final int MSG_SERVICE_COMMAND = 1;
    private static final int MSG_POLL = 2;

    /** Polling frequency, in milliseconds. */
    private static final long POLLING_FREQUENCY = 500;

    /** How long (in ms) a dumpstate process will be monitored if it didn't show progress. */
    private static final long INACTIVITY_TIMEOUT = 3 * DateUtils.MINUTE_IN_MILLIS;

    /** System property used for monitoring progress. */
    private static final String PROGRESS_PROPERTY_TEMPLATE = "dumpstate.%d.progress";

    /** Managed dumpstate processes (keyed by pid) */
    private final SparseArray<BugreportInfo> mProcesses = new SparseArray<>();

    private Looper mServiceLooper;
    private ServiceHandler mServiceHandler;

    @Override
    public void onCreate() {
        HandlerThread thread = new HandlerThread("BugreportProgressServiceThread",
                Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            // Handle it in a separate thread.
            Message msg = mServiceHandler.obtainMessage();
            msg.what = MSG_SERVICE_COMMAND;
            msg.obj = intent;
            mServiceHandler.sendMessage(msg);
        }

        // If service is killed it cannot be recreated because it would not know which
        // dumpstate PIDs it would have to watch.
        return START_NOT_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
        super.onDestroy();
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        writer.printf("Monitored dumpstate processes: \n");
        synchronized (mProcesses) {
            for (int i = 0; i < mProcesses.size(); i++) {
              writer.printf("\t%s\n", mProcesses.valueAt(i));
            }
        }
    }

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
            pollProgress();
        }

        @Override
        public void handleMessage(Message msg) {
            if (msg.what == MSG_POLL) {
                pollProgress();
                return;
            }

            if (msg.what != MSG_SERVICE_COMMAND) {
                // Sanity check.
                Log.e(TAG, "Invalid message type: " + msg.what);
                return;
            }

            // At this point it's handling onStartCommand(), whose intent contains the extras
            // originally received by BugreportReceiver.
            if (!(msg.obj instanceof Intent)) {
                // Sanity check.
                Log.e(TAG, "Internal error: invalid msg.obj: " + msg.obj);
                return;
            }
            final Parcelable parcel = ((Intent) msg.obj).getParcelableExtra(EXTRA_ORIGINAL_INTENT);
            if (!(parcel instanceof Intent)) {
                // Sanity check.
                Log.e(TAG, "Internal error: msg.obj is missing extra " + EXTRA_ORIGINAL_INTENT);
                return;
            }

            final Intent intent = (Intent) parcel;
            final String action = intent.getAction();
            int pid = intent.getIntExtra(EXTRA_PID, 0);
            int max = intent.getIntExtra(EXTRA_MAX, -1);
            String name = intent.getStringExtra(EXTRA_NAME);

            if (DEBUG) Log.v(TAG, "action: " + action + ", name: " + name + ", pid: " + pid
                    + ", max: "+ max);
            switch (action) {
                case INTENT_BUGREPORT_STARTED:
                    if (!startProgress(name, pid, max)) {
                        stopSelfWhenDone();
                        return;
                    }
                    break;
                case INTENT_BUGREPORT_FINISHED:
                    if (pid == -1) {
                        // Shouldn't happen, unless BUGREPORT_FINISHED is received from a legacy,
                        // out-of-sync dumpstate process.
                        Log.w(TAG, "Missing " + EXTRA_PID + " on intent " + intent);
                    }
                    stopProgress(pid, intent);
                    break;
                default:
                    Log.w(TAG, "Unsupported intent: " + action);
            }
            return;

        }

        /**
         * Creates the {@link BugreportInfo} for a process and issue a system notification to
         * indicate its progress.
         *
         * @return whether it succeeded or not.
         */
        private boolean startProgress(String name, int pid, int max) {
            if (name == null) {
                Log.w(TAG, "Missing " + EXTRA_NAME + " on start intent");
                name = "N/A";
            }
            if (pid == -1) {
                Log.e(TAG, "Missing " + EXTRA_PID + " on start intent");
                return false;
            }
            if (max <= 0) {
                Log.e(TAG, "Invalid value for extra " + EXTRA_MAX + ": " + max);
                return false;
            }

            final BugreportInfo info = new BugreportInfo(pid, name, max);
            synchronized (mProcesses) {
                if (mProcesses.indexOfKey(pid) >= 0) {
                    Log.w(TAG, "PID " + pid + " already watched");
                } else {
                    mProcesses.put(info.pid, info);
                }
            }
            updateProgress(info);
            return true;
        }

        /**
         * Updates the system notification for a given bug report.
         */
        private void updateProgress(BugreportInfo info) {
            if (info.max <= 0 || info.progress < 0 || info.name == null) {
                Log.e(TAG, "Invalid progress values for " + info);
                return;
            }

            final Context context = getApplicationContext();
            final NumberFormat nf = NumberFormat.getPercentInstance();
            nf.setMinimumFractionDigits(2);
            nf.setMaximumFractionDigits(2);
            final String percentText = nf.format((double) info.progress / info.max);

            final String title = context.getString(R.string.bugreport_in_progress_title);
            final Notification notification = new Notification.Builder(context)
                    .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                    .setContentTitle(title)
                    .setTicker(title)
                    .setContentText(info.name)
                    .setContentInfo(percentText)
                    .setProgress(info.max, info.progress, false)
                    // TODO: .setOngoing(true) once it has a CANCEL action
                    .setLocalOnly(true)
                    .setColor(context.getColor(
                            com.android.internal.R.color.system_notification_accent_color))
                    .build();

            NotificationManager.from(context).notify(TAG, info.pid, notification);
        }

        /**
         * Finalizes the progress on a given process and sends the finished intent.
         */
        private void stopProgress(int pid, Intent intent) {
            synchronized (mProcesses) {
                if (mProcesses.indexOfKey(pid) < 0) {
                    Log.w(TAG, "PID not watched: " + pid);
                } else {
                    mProcesses.remove(pid);
                }
                stopSelfWhenDone();
            }
            if (DEBUG) Log.v(TAG, "stopProgress(" + pid + "): cancel notification");
            NotificationManager.from(getApplicationContext()).cancel(TAG, pid);
            if (intent != null) {
                // Bug report finished fine: send a new, different notification.
                if (DEBUG) Log.v(TAG, "stopProgress(" + pid + "): finish bug report");
                onBugreportFinished(pid, intent);
            }
        }

        /**
         * Poll {@link SystemProperties} to get the progress on each monitored process.
         */
        private void pollProgress() {
            synchronized (mProcesses) {
                if (mProcesses.size() == 0) {
                    Log.d(TAG, "No process to poll progress.");
                }
                for (int i = 0; i < mProcesses.size(); i++) {
                    int pid = mProcesses.keyAt(i);
                    String property = String.format(PROGRESS_PROPERTY_TEMPLATE, pid);
                    int progress;
                    try {
                        progress = SystemProperties.getInt(property, 0);
                    } catch (IllegalArgumentException e) {
                        Log.v(TAG, "Could not read system property " + property, e);
                        continue;
                    }
                    if (progress == 0) {
                        Log.v(TAG, "System property " + property + " is not set yet");
                        continue;
                    }

                    BugreportInfo info = mProcesses.valueAt(i);

                    if (progress != info.progress) {
                        if (DEBUG) Log.v(TAG, "Updating progress for PID " + pid + " from "
                                + info.progress + " to " + progress);
                        info.progress = progress;
                        info.lastUpdate = System.currentTimeMillis();
                        updateProgress(info);
                    } else {
                        long inactiveTime = System.currentTimeMillis() - info.lastUpdate;
                        if (inactiveTime >= INACTIVITY_TIMEOUT) {
                            Log.w(TAG, "No progress update for process " + pid + " since "
                                    + info.getFormattedLastUpdate());
                            stopProgress(info.pid, null);
                        }
                    }
                }
                // Keep polling...
                sendEmptyMessageDelayed(MSG_POLL, POLLING_FREQUENCY);
            }
        }

        /**
         * Finishes the service when it's not monitoring any more processes.
         */
        private void stopSelfWhenDone() {
            synchronized (mProcesses) {
                if (mProcesses.size() > 0) {
                    if (DEBUG) Log.v(TAG, "Staying alive, waiting for pids " + mProcesses);
                    return;
                }
                Log.v(TAG, "No more pids to handle, shutting down");
                stopSelf();
            }
        }

        private void onBugreportFinished(int pid, Intent intent) {
            final Context context = getApplicationContext();
            final Configuration conf = context.getResources().getConfiguration();
            final File bugreportFile = getFileExtra(intent, EXTRA_BUGREPORT);
            final File screenshotFile = getFileExtra(intent, EXTRA_SCREENSHOT);

            if ((conf.uiMode & Configuration.UI_MODE_TYPE_MASK) != Configuration.UI_MODE_TYPE_WATCH) {
                triggerLocalNotification(context, pid, bugreportFile, screenshotFile);
            }
        }
    }

    /**
     * Responsible for triggering a notification that allows the user to start a "share" intent with
     * the bug report. On watches we have other methods to allow the user to start this intent
     * (usually by triggering it on another connected device); we don't need to display the
     * notification in this case.
     */
    private static void triggerLocalNotification(final Context context, final int pid,
            final File bugreportFile, final File screenshotFile) {
        if (!bugreportFile.exists() || !bugreportFile.canRead()) {
            Log.e(TAG, "Could not read bugreport file " + bugreportFile);
            Toast.makeText(context, context.getString(R.string.bugreport_unreadable_text),
                    Toast.LENGTH_LONG).show();
            return;
        }

        boolean isPlainText = bugreportFile.getName().toLowerCase().endsWith(".txt");
        if (!isPlainText) {
            // Already zipped, send it right away.
            sendBugreportNotification(context, pid, bugreportFile, screenshotFile);
        } else {
            // Asynchronously zip the file first, then send it.
            sendZippedBugreportNotification(context, pid, bugreportFile, screenshotFile);
        }
    }

    private static Intent buildWarningIntent(Context context, Intent sendIntent) {
        final Intent intent = new Intent(context, BugreportWarningActivity.class);
        intent.putExtra(Intent.EXTRA_INTENT, sendIntent);
        return intent;
    }

    /**
     * Build {@link Intent} that can be used to share the given bugreport.
     */
    private static Intent buildSendIntent(Context context, Uri bugreportUri, Uri screenshotUri) {
        final Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
        final String mimeType = "application/vnd.android.bugreport";
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        intent.setType(mimeType);

        intent.putExtra(Intent.EXTRA_SUBJECT, bugreportUri.getLastPathSegment());

        // EXTRA_TEXT should be an ArrayList, but some clients are expecting a single String.
        // So, to avoid an exception on Intent.migrateExtraStreamToClipData(), we need to manually
        // create the ClipData object with the attachments URIs.
        String messageBody = String.format("Build info: %s\nSerial number:%s",
                SystemProperties.get("ro.build.description"), SystemProperties.get("ro.serialno"));
        intent.putExtra(Intent.EXTRA_TEXT, messageBody);
        final ClipData clipData = new ClipData(null, new String[] { mimeType },
                new ClipData.Item(null, null, null, bugreportUri));
        final ArrayList<Uri> attachments = Lists.newArrayList(bugreportUri);
        if (screenshotUri != null) {
            clipData.addItem(new ClipData.Item(null, null, null, screenshotUri));
            attachments.add(screenshotUri);
        }
        intent.setClipData(clipData);
        intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, attachments);

        final Account sendToAccount = findSendToAccount(context);
        if (sendToAccount != null) {
            intent.putExtra(Intent.EXTRA_EMAIL, new String[] { sendToAccount.name });
        }

        return intent;
    }

    /**
     * Sends a bugreport notitication.
     */
    private static void sendBugreportNotification(Context context, int pid, File bugreportFile,
            File screenshotFile) {
        // Files are kept on private storage, so turn into Uris that we can
        // grant temporary permissions for.
        final Uri bugreportUri = getUri(context, bugreportFile);
        final Uri screenshotUri = getUri(context, screenshotFile);

        Intent sendIntent = buildSendIntent(context, bugreportUri, screenshotUri);
        Intent notifIntent;

        // Send through warning dialog by default
        if (getWarningState(context, STATE_SHOW) == STATE_SHOW) {
            notifIntent = buildWarningIntent(context, sendIntent);
        } else {
            notifIntent = sendIntent;
        }
        notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        final String title = context.getString(R.string.bugreport_finished_title);
        final Notification.Builder builder = new Notification.Builder(context)
                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
                .setContentTitle(title)
                .setTicker(title)
                .setContentText(context.getString(R.string.bugreport_finished_text))
                .setContentIntent(PendingIntent.getActivity(
                        context, 0, notifIntent, PendingIntent.FLAG_CANCEL_CURRENT))
                .setAutoCancel(true)
                .setLocalOnly(true)
                .setColor(context.getColor(
                        com.android.internal.R.color.system_notification_accent_color));

        NotificationManager.from(context).notify(TAG, pid, builder.build());
    }

    /**
     * Sends a zipped bugreport notification.
     */
    private static void sendZippedBugreportNotification(final Context context,
            final int pid, final File bugreportFile, final File screenshotFile) {
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                File zippedFile = zipBugreport(bugreportFile);
                sendBugreportNotification(context, pid, zippedFile, screenshotFile);
                return null;
            }
        }.execute();
    }

    /**
     * Zips a bugreport file, returning the path to the new file (or to the
     * original in case of failure).
     */
    private static File zipBugreport(File bugreportFile) {
        String bugreportPath = bugreportFile.getAbsolutePath();
        String zippedPath = bugreportPath.replace(".txt", ".zip");
        Log.v(TAG, "zipping " + bugreportPath + " as " + zippedPath);
        File bugreportZippedFile = new File(zippedPath);
        try (InputStream is = new FileInputStream(bugreportFile);
                ZipOutputStream zos = new ZipOutputStream(
                        new BufferedOutputStream(new FileOutputStream(bugreportZippedFile)))) {
            ZipEntry entry = new ZipEntry(bugreportFile.getName());
            entry.setTime(bugreportFile.lastModified());
            zos.putNextEntry(entry);
            int totalBytes = Streams.copy(is, zos);
            Log.v(TAG, "size of original bugreport: " + totalBytes + " bytes");
            zos.closeEntry();
            // Delete old file;
            boolean deleted = bugreportFile.delete();
            if (deleted) {
                Log.v(TAG, "deleted original bugreport (" + bugreportPath + ")");
            } else {
                Log.e(TAG, "could not delete original bugreport (" + bugreportPath + ")");
            }
            return bugreportZippedFile;
        } catch (IOException e) {
            Log.e(TAG, "exception zipping file " + zippedPath, e);
            return bugreportFile; // Return original.
        }
    }

    /**
     * Find the best matching {@link Account} based on build properties.
     */
    private static Account findSendToAccount(Context context) {
        final AccountManager am = (AccountManager) context.getSystemService(
                Context.ACCOUNT_SERVICE);

        String preferredDomain = SystemProperties.get("sendbug.preferred.domain");
        if (!preferredDomain.startsWith("@")) {
            preferredDomain = "@" + preferredDomain;
        }

        final Account[] accounts = am.getAccounts();
        Account foundAccount = null;
        for (Account account : accounts) {
            if (Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) {
                if (!preferredDomain.isEmpty()) {
                    // if we have a preferred domain and it matches, return; otherwise keep
                    // looking
                    if (account.name.endsWith(preferredDomain)) {
                        return account;
                    } else {
                        foundAccount = account;
                    }
                    // if we don't have a preferred domain, just return since it looks like
                    // an email address
                } else {
                    return account;
                }
            }
        }
        return foundAccount;
    }

    private static Uri getUri(Context context, File file) {
        return file != null ? FileProvider.getUriForFile(context, AUTHORITY, file) : null;
    }

    static File getFileExtra(Intent intent, String key) {
        final String path = intent.getStringExtra(key);
        if (path != null) {
            return new File(path);
        } else {
            return null;
        }
    }

    /**
     * Information about a bug report process while its in progress.
     */
    private static final class BugreportInfo {
        /**
         * {@code pid} of the {@code dumpstate} process generating the bug report.
         */
        final int pid;

        /**
         * Name of the bug report, will be used to rename the final files.
         * <p>
         * Initial value is the bug report filename reported by {@code dumpstate}, but user can
         * change it later to a more meaningful name.
         */
        final String name;

        /**
         * Maximum progress of the bug report generation.
         */
        final int max;

        /**
         * Current progress of the bug report generation.
         */
        int progress;

        /**
         * Time of the last progress update.
         */
        long lastUpdate = System.currentTimeMillis();

        BugreportInfo(int pid, String name, int max) {
            this.pid = pid;
            this.name = name;
            this.max = max;
        }

        String getFormattedLastUpdate() {
            return SimpleDateFormat.getDateTimeInstance().format(new Date(lastUpdate));
        }

        @Override
        public String toString() {
            final float percent = ((float) progress * 100 / max);
            return String.format("Progress for %s (pid=%d): %d/%d (%2.2f%%) Last update: %s", name,
                    pid, progress, max, percent,
                    getFormattedLastUpdate());
        }
    }
}
