/*
 * 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 android.test.MoreAsserts.assertContainsRegex;
import static com.android.shell.ActionSendMultipleConsumerActivity.UI_NAME;
import static com.android.shell.BugreportProgressService.EXTRA_BUGREPORT;
import static com.android.shell.BugreportProgressService.EXTRA_MAX;
import static com.android.shell.BugreportProgressService.EXTRA_NAME;
import static com.android.shell.BugreportProgressService.EXTRA_PID;
import static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT;
import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_STARTED;

import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import libcore.io.Streams;
import android.app.Instrumentation;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemProperties;
import android.service.notification.StatusBarNotification;
import android.support.test.uiautomator.UiDevice;
import android.test.InstrumentationTestCase;
import android.util.Log;

import com.android.shell.ActionSendMultipleConsumerActivity.CustomActionSendMultipleListener;

/**
 * Integration tests for {@link BugreportReceiver}.
 * <p>
 * These tests don't mock any component and rely on external UI components (like the notification
 * bar and activity chooser), which can make them unreliable and slow.
 * <p>
 * The general workflow is:
 * <ul>
 * <li>creates the bug report files
 * <li>generates the BUGREPORT_FINISHED intent
 * <li>emulate user actions to share the intent with a custom activity
 * <li>asserts the extras received by the custom activity
 * </ul>
 * <p>
 * TODO: currently, these tests only work if the bug report sharing warning is disabled and the
 * device screen is unlocked.
 */
public class BugreportReceiverTest extends InstrumentationTestCase {

    private static final String TAG = "BugreportReceiverTest";

    // Timeout for UI operations, in milliseconds.
    private static final int TIMEOUT = 1000;

    private static final String ROOT_DIR = "/data/data/com.android.shell/files/bugreports";
    private static final String BUGREPORT_FILE = "test_bugreport.txt";
    private static final String ZIP_FILE = "test_bugreport.zip";
    private static final String PLAIN_TEXT_PATH = ROOT_DIR + "/" + BUGREPORT_FILE;
    private static final String ZIP_PATH = ROOT_DIR + "/" + ZIP_FILE;
    private static final String SCREENSHOT_PATH = ROOT_DIR + "/test_screenshot.png";

    private static final String BUGREPORT_CONTENT = "Dump, might as well dump!\n";
    private static final String SCREENSHOT_CONTENT = "A picture is worth a thousand words!\n";

    private Context mContext;
    private UiBot mUiBot;
    private CustomActionSendMultipleListener mListener;

    @Override
    protected void setUp() throws Exception {
        Instrumentation instrumentation = getInstrumentation();
        mContext = instrumentation.getTargetContext();
        mUiBot = new UiBot(UiDevice.getInstance(instrumentation), TIMEOUT);
        mListener = ActionSendMultipleConsumerActivity.getListener(mContext);
        cancelExistingNotifications();
    }

    public void testFullWorkflow() throws Exception {
        final String name = "BUG, Y U NO REPORT?";
        // TODO: call method to remove property instead
        SystemProperties.set("dumpstate.42.progress", "-1");

        Intent intent = new Intent(INTENT_BUGREPORT_STARTED);
        intent.putExtra(EXTRA_PID, 42);
        intent.putExtra(EXTRA_NAME, name);
        intent.putExtra(EXTRA_MAX, 1000);
        mContext.sendBroadcast(intent);

        assertProgressNotification(name, "0.00%");

        SystemProperties.set("dumpstate.42.progress", "108");
        assertProgressNotification(name, "10.80%");

        SystemProperties.set("dumpstate.42.progress", "500");
        assertProgressNotification(name, "50.00%");

        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
        createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
        Bundle extras = sendBugreportFinishedIntent(42, PLAIN_TEXT_PATH, SCREENSHOT_PATH);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);

        // TODO: assert service is down
    }

    public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception {
        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
        createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
        Bundle extras = sendBugreportFinishedIntent(PLAIN_TEXT_PATH, SCREENSHOT_PATH);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
    }

    public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception {
        createZipFile(ZIP_PATH, BUGREPORT_FILE, BUGREPORT_CONTENT);
        createTextFile(SCREENSHOT_PATH, SCREENSHOT_CONTENT);
        Bundle extras = sendBugreportFinishedIntent(ZIP_PATH, SCREENSHOT_PATH);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT);
    }

    public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception {
        createTextFile(PLAIN_TEXT_PATH, BUGREPORT_CONTENT);
        Bundle extras = sendBugreportFinishedIntent(PLAIN_TEXT_PATH, null);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, null);
    }

    public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception {
        createZipFile(ZIP_PATH, BUGREPORT_FILE, BUGREPORT_CONTENT);
        Bundle extras = sendBugreportFinishedIntent(ZIP_PATH, null);
        assertActionSendMultiple(extras, BUGREPORT_CONTENT, null);
    }

    private void cancelExistingNotifications() {
        NotificationManager nm = NotificationManager.from(mContext);
        for (StatusBarNotification notification : nm.getActiveNotifications()) {
            int id = notification.getId();
            Log.i(TAG, "Canceling existing notification (id=" + id + ")");
            nm.cancel(id);
        }
    }

    private void assertProgressNotification(String name, String percent) {
        // TODO: it current looks for 3 distinct objects, without taking advantage of their
        // relationship.
        String title = mContext.getString(R.string.bugreport_in_progress_title);
        Log.v(TAG, "Looking for progress notification title: '" + title+ "'");
        mUiBot.getNotification(title);
        Log.v(TAG, "Looking for progress notification details: '" + name + "-" + percent + "'");
        mUiBot.getObject(name);
        mUiBot.getObject(percent);
    }

    /**
     * Sends a "bugreport finished" intent and waits for the result.
     *
     * @return extras sent to the bugreport finished consumer.
     */
    private Bundle sendBugreportFinishedIntent(String bugreportPath, String screenshotPath) {
        return sendBugreportFinishedIntent(null, bugreportPath, screenshotPath);
    }

    private Bundle sendBugreportFinishedIntent(Integer pid, String bugreportPath,
            String screenshotPath) {
        Intent intent = new Intent(INTENT_BUGREPORT_FINISHED);
        if (pid != null) {
            intent.putExtra(EXTRA_PID, pid);
        }
        if (bugreportPath != null) {
            intent.putExtra(EXTRA_BUGREPORT, bugreportPath);
        }
        if (screenshotPath != null) {
            intent.putExtra(EXTRA_SCREENSHOT, screenshotPath);
        }

        mContext.sendBroadcast(intent);

        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title));
        mUiBot.chooseActivity(UI_NAME);
        return mListener.getExtras();
    }

    /**
     * Asserts the proper ACTION_SEND_MULTIPLE intent was sent.
     */
    private void assertActionSendMultiple(Bundle extras, String bugreportContent,
            String screenshotContent) throws IOException {
        String body = extras.getString(Intent.EXTRA_TEXT);
        assertContainsRegex("missing build info",
                SystemProperties.get("ro.build.description"), body);
        assertContainsRegex("missing serial number",
                SystemProperties.get("ro.serialno"), body);

        assertEquals("wrong subject", ZIP_FILE, extras.getString(Intent.EXTRA_SUBJECT));

        List<Uri> attachments = extras.getParcelableArrayList(Intent.EXTRA_STREAM);
        int expectedSize = screenshotContent != null ? 2 : 1;
        assertEquals("wrong number of attachments", expectedSize, attachments.size());

        // Need to interact through all attachments, since order is not guaranteed.
        Uri zipUri = null, screenshotUri = null;
        for (Uri attachment : attachments) {
            if (attachment.getPath().endsWith(".zip")) {
                zipUri = attachment;
            }
            if (attachment.getPath().endsWith(".png")) {
                screenshotUri = attachment;
            }
        }
        assertNotNull("did not get .zip attachment", zipUri);
        assertZipContent(zipUri, BUGREPORT_FILE, BUGREPORT_CONTENT);

        if (screenshotContent != null) {
            assertNotNull("did not get .png attachment", screenshotUri);
            assertContent(screenshotUri, SCREENSHOT_CONTENT);
        } else {
            assertNull("should not have .png attachment", screenshotUri);
        }
    }

    private void assertContent(Uri uri, String expectedContent) throws IOException {
        Log.v(TAG, "assertContents(uri=" + uri);
        try (InputStream is = mContext.getContentResolver().openInputStream(uri)) {
            String actualContent = new String(Streams.readFully(is));
            assertEquals("wrong content for '" + uri + "'", expectedContent, actualContent);
        }
    }

    private void assertZipContent(Uri uri, String entryName, String expectedContent)
            throws IOException, IOException {
        Log.v(TAG, "assertZipEntry(uri=" + uri + ", entryName=" + entryName);
        try (ZipInputStream zis = new ZipInputStream(mContext.getContentResolver().openInputStream(
                uri))) {
            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                Log.v(TAG, "Zip entry: " + entry.getName());
                if (entry.getName().equals(entryName)) {
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    Streams.copy(zis, bos);
                    String actualContent = new String(bos.toByteArray(), "UTF-8");
                    bos.close();
                    assertEquals("wrong content for zip entry'" + entryName + "' on '" + uri + "'",
                            expectedContent, actualContent);
                    return;
                }
            }
        }
        fail("Did not find entry '" + entryName + "' on file '" + uri + "'");
    }

    private static void createTextFile(String path, String content) throws IOException {
        Log.v(TAG, "createFile(" + path + ")");
        try (Writer writer = new BufferedWriter(new OutputStreamWriter(
                new FileOutputStream(path)))) {
            writer.write(content);
        }
    }

    private void createZipFile(String path, String entryName, String content) throws IOException {
        Log.v(TAG, "createZipFile(" + path + ", " + entryName + ")");
        try (ZipOutputStream zos = new ZipOutputStream(
                new BufferedOutputStream(new FileOutputStream(path)))) {
            ZipEntry entry = new ZipEntry(entryName);
            zos.putNextEntry(entry);
            byte[] data = content.getBytes();
            zos.write(data, 0, data.length);
            zos.closeEntry();
        }
    }
}
