/*
 * Copyright (C) 2011 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.dialer;

import static com.android.dialer.CallDetailActivity.Tasks.UPDATE_PHONE_CALL_DETAILS;
import static com.android.dialer.voicemail.VoicemailPlaybackPresenter.Tasks.CHECK_FOR_CONTENT;
import static com.android.dialer.voicemail.VoicemailPlaybackPresenter.Tasks.PREPARE_MEDIA_PLAYER;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import android.provider.CallLog;
import android.provider.VoicemailContract;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.Suppress;
import android.view.Menu;
import android.widget.TextView;

import com.android.dialer.util.AsyncTaskExecutors;
import com.android.dialer.util.FakeAsyncTaskExecutor;
import com.android.contacts.common.test.IntegrationTestUtils;
import com.android.dialer.util.LocaleTestUtils;
import com.android.internal.view.menu.ContextMenuBuilder;
import com.google.common.io.Closeables;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Locale;

/**
 * Unit tests for the {@link CallDetailActivity}.
 */
@LargeTest
public class CallDetailActivityTest extends ActivityInstrumentationTestCase2<CallDetailActivity> {
    private static final String TEST_ASSET_NAME = "quick_test_recording.mp3";
    private static final String MIME_TYPE = "audio/mp3";
    private static final String CONTACT_NUMBER = "+1412555555";
    private static final String VOICEMAIL_FILE_LOCATION = "/sdcard/sadlfj893w4j23o9sfu.mp3";

    private Uri mCallLogUri;
    private Uri mVoicemailUri;
    private IntegrationTestUtils mTestUtils;
    private LocaleTestUtils mLocaleTestUtils;
    private FakeAsyncTaskExecutor mFakeAsyncTaskExecutor;
    private CallDetailActivity mActivityUnderTest;

    public CallDetailActivityTest() {
        super(CallDetailActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mFakeAsyncTaskExecutor = new FakeAsyncTaskExecutor(getInstrumentation());
        AsyncTaskExecutors.setFactoryForTest(mFakeAsyncTaskExecutor.getFactory());
        // I don't like the default of focus-mode for tests, the green focus border makes the
        // screenshots look weak.
        setActivityInitialTouchMode(true);
        mTestUtils = new IntegrationTestUtils(getInstrumentation());
        // Some of the tests rely on the text that appears on screen - safest to force a
        // specific locale.
        mLocaleTestUtils = new LocaleTestUtils(getInstrumentation().getTargetContext());
        mLocaleTestUtils.setLocale(Locale.US);
    }

    @Override
    protected void tearDown() throws Exception {
        mLocaleTestUtils.restoreLocale();
        mLocaleTestUtils = null;
        cleanUpUri();
        mTestUtils = null;
        AsyncTaskExecutors.setFactoryForTest(null);
        super.tearDown();
    }

    public void testInitialActivityStartsWithFetchingVoicemail() throws Throwable {
        setActivityIntentForTestVoicemailEntry();
        startActivityUnderTest();
        // When the activity first starts, we will show "Fetching voicemail" on the screen.
        // The duration should not be visible.
        assertHasOneTextViewContaining("Fetching voicemail");
        assertZeroTextViewsContaining("00:00");
    }

    public void testWhenCheckForContentCompletes_UiShowsBuffering() throws Throwable {
        setActivityIntentForTestVoicemailEntry();
        startActivityUnderTest();
        // There is a background check that is testing to see if we have the content available.
        // Once that task completes, we shouldn't be showing the fetching message, we should
        // be showing "Buffering".
        mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
        assertHasOneTextViewContaining("Buffering");
        assertZeroTextViewsContaining("Fetching voicemail");
    }

    public void testInvalidVoicemailShowsErrorMessage() throws Throwable {
        setActivityIntentForTestVoicemailEntry();
        startActivityUnderTest();
        mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
        // There should be exactly one background task ready to prepare the media player.
        // Preparing the media player will have thrown an IOException since the file doesn't exist.
        // This should have put a failed to play message on screen, buffering is gone.
        mFakeAsyncTaskExecutor.runTask(PREPARE_MEDIA_PLAYER);
        assertHasOneTextViewContaining("Couldn't play voicemail");
        assertZeroTextViewsContaining("Buffering");
    }

    public void testOnResumeDoesNotCreateManyFragments() throws Throwable {
        // There was a bug where every time the activity was resumed, a new fragment was created.
        // Before the fix, this was failing reproducibly with at least 3 "Buffering" views.
        setActivityIntentForTestVoicemailEntry();
        startActivityUnderTest();
        mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
        getInstrumentation().runOnMainSync(new Runnable() {
            @Override
            public void run() {
                getInstrumentation().callActivityOnPause(mActivityUnderTest);
                getInstrumentation().callActivityOnResume(mActivityUnderTest);
                getInstrumentation().callActivityOnPause(mActivityUnderTest);
                getInstrumentation().callActivityOnResume(mActivityUnderTest);
            }
        });
        assertHasOneTextViewContaining("Buffering");
    }

    /**
     * Test for bug where increase rate button with invalid voicemail causes a crash.
     * <p>
     * The repro steps for this crash were to open a voicemail that does not have an attachment,
     * then click the play button (which just reported an error), then after that try to adjust the
     * rate.  See http://b/5047879.
     */
    public void testClickIncreaseRateButtonWithInvalidVoicemailDoesNotCrash() throws Throwable {
        setActivityIntentForTestVoicemailEntry();
        startActivityUnderTest();
        mTestUtils.clickButton(mActivityUnderTest, R.id.playback_start_stop);
        mTestUtils.clickButton(mActivityUnderTest, R.id.rate_increase_button);
    }

    /** Test for bug where missing Extras on intent used to start Activity causes NPE. */
    public void testCallLogUriWithMissingExtrasShouldNotCauseNPE() throws Throwable {
        setActivityIntentForTestCallEntry();
        startActivityUnderTest();
    }

    /**
     * Test for bug where voicemails should not have remove-from-call-log entry.
     * <p>
     * See http://b/5054103.
     */
    public void testVoicemailDoesNotHaveRemoveFromCallLog() throws Throwable {
        setActivityIntentForTestVoicemailEntry();
        startActivityUnderTest();
        Menu menu = new ContextMenuBuilder(mActivityUnderTest);
        mActivityUnderTest.onCreateOptionsMenu(menu);
        mActivityUnderTest.onPrepareOptionsMenu(menu);
        assertFalse(menu.findItem(R.id.menu_remove_from_call_log).isVisible());
    }

    /** Test to check that I haven't broken the remove-from-call-log entry from regular calls. */
    public void testRegularCallDoesHaveRemoveFromCallLog() throws Throwable {
        setActivityIntentForTestCallEntry();
        startActivityUnderTest();
        Menu menu = new ContextMenuBuilder(mActivityUnderTest);
        mActivityUnderTest.onCreateOptionsMenu(menu);
        mActivityUnderTest.onPrepareOptionsMenu(menu);
        assertTrue(menu.findItem(R.id.menu_remove_from_call_log).isVisible());
    }

    /**
     * Test to show that we are correctly displaying playback rate on the ui.
     * <p>
     * See bug http://b/5044075.
     */
    @Suppress
    public void testVoicemailPlaybackRateDisplayedOnUi() throws Throwable {
        setActivityIntentForTestVoicemailEntry();
        startActivityUnderTest();
        // Find the TextView containing the duration.  It should be initially displaying "00:00".
        List<TextView> views = mTestUtils.getTextViewsWithString(mActivityUnderTest, "00:00");
        assertEquals(1, views.size());
        TextView timeDisplay = views.get(0);
        // Hit the plus button.  At this point we should be displaying "fast speed".
        mTestUtils.clickButton(mActivityUnderTest, R.id.rate_increase_button);
        assertEquals("fast speed", mTestUtils.getText(timeDisplay));
        // Hit the minus button.  We should be back to "normal" speed.
        mTestUtils.clickButton(mActivityUnderTest, R.id.rate_decrease_button);
        assertEquals("normal speed", mTestUtils.getText(timeDisplay));
        // Wait for one and a half seconds.  The timer will be back.
        Thread.sleep(1500);
        assertEquals("00:00", mTestUtils.getText(timeDisplay));
    }

    @Suppress
    public void testClickingCallStopsPlayback() throws Throwable {
        setActivityIntentForRealFileVoicemailEntry();
        startActivityUnderTest();
        mFakeAsyncTaskExecutor.runTask(CHECK_FOR_CONTENT);
        mFakeAsyncTaskExecutor.runTask(PREPARE_MEDIA_PLAYER);
        mTestUtils.clickButton(mActivityUnderTest, R.id.playback_speakerphone);
        mTestUtils.clickButton(mActivityUnderTest, R.id.playback_start_stop);
        mTestUtils.clickButton(mActivityUnderTest, R.id.call_and_sms_main_action);
        Thread.sleep(2000);
        // TODO: Suppressed the test for now, because I'm looking for an easy way to say "the audio
        // is not playing at this point", and I can't find it without doing dirty things.
    }

    private void setActivityIntentForTestCallEntry() {
        assertNull(mCallLogUri);
        ContentResolver contentResolver = getContentResolver();
        ContentValues values = new ContentValues();
        values.put(CallLog.Calls.NUMBER, CONTACT_NUMBER);
        values.put(CallLog.Calls.TYPE, CallLog.Calls.INCOMING_TYPE);
        mCallLogUri = contentResolver.insert(CallLog.Calls.CONTENT_URI, values);
        setActivityIntent(new Intent(Intent.ACTION_VIEW, mCallLogUri));
    }

    private void setActivityIntentForTestVoicemailEntry() {
        assertNull(mVoicemailUri);
        ContentResolver contentResolver = getContentResolver();
        ContentValues values = new ContentValues();
        values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER);
        values.put(VoicemailContract.Voicemails.HAS_CONTENT, 1);
        values.put(VoicemailContract.Voicemails._DATA, VOICEMAIL_FILE_LOCATION);
        mVoicemailUri = contentResolver.insert(VoicemailContract.Voicemails.CONTENT_URI, values);
        Uri callLogUri = ContentUris.withAppendedId(CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL,
                ContentUris.parseId(mVoicemailUri));
        Intent intent = new Intent(Intent.ACTION_VIEW, callLogUri);
        intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_URI, mVoicemailUri);
        setActivityIntent(intent);
    }

    private void setActivityIntentForRealFileVoicemailEntry() throws IOException {
        assertNull(mVoicemailUri);
        ContentValues values = new ContentValues();
        values.put(VoicemailContract.Voicemails.DATE, String.valueOf(System.currentTimeMillis()));
        values.put(VoicemailContract.Voicemails.NUMBER, CONTACT_NUMBER);
        values.put(VoicemailContract.Voicemails.MIME_TYPE, MIME_TYPE);
        values.put(VoicemailContract.Voicemails.HAS_CONTENT, 1);
        String packageName = getInstrumentation().getTargetContext().getPackageName();
        mVoicemailUri = getContentResolver().insert(
                VoicemailContract.Voicemails.buildSourceUri(packageName), values);
        AssetManager assets = getAssets();
        OutputStream outputStream = null;
        InputStream inputStream = null;
        try {
            inputStream = assets.open(TEST_ASSET_NAME);
            outputStream = getContentResolver().openOutputStream(mVoicemailUri);
            copyBetweenStreams(inputStream, outputStream);
        } finally {
            Closeables.closeQuietly(outputStream);
            Closeables.closeQuietly(inputStream);
        }
        Uri callLogUri = ContentUris.withAppendedId(CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL,
                ContentUris.parseId(mVoicemailUri));
        Intent intent = new Intent(Intent.ACTION_VIEW, callLogUri);
        intent.putExtra(CallDetailActivity.EXTRA_VOICEMAIL_URI, mVoicemailUri);
        setActivityIntent(intent);
    }

    public void copyBetweenStreams(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[1024];
        int bytesRead;
        int total = 0;
        while ((bytesRead = in.read(buffer)) != -1) {
            total += bytesRead;
            out.write(buffer, 0, bytesRead);
        }
    }

    private void cleanUpUri() {
        if (mVoicemailUri != null) {
            getContentResolver().delete(VoicemailContract.Voicemails.CONTENT_URI,
                    "_ID = ?", new String[] { String.valueOf(ContentUris.parseId(mVoicemailUri)) });
            mVoicemailUri = null;
        }
        if (mCallLogUri != null) {
            getContentResolver().delete(CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL,
                    "_ID = ?", new String[] { String.valueOf(ContentUris.parseId(mCallLogUri)) });
            mCallLogUri = null;
        }
    }

    private ContentResolver getContentResolver() {
        return getInstrumentation().getTargetContext().getContentResolver();
    }

    private TextView assertHasOneTextViewContaining(String text) throws Throwable {
        assertNotNull(mActivityUnderTest);
        List<TextView> views = mTestUtils.getTextViewsWithString(mActivityUnderTest, text);
        assertEquals("There should have been one TextView with text '" + text + "' but found "
                + views, 1, views.size());
        return views.get(0);
    }

    private void assertZeroTextViewsContaining(String text) throws Throwable {
        assertNotNull(mActivityUnderTest);
        List<TextView> views = mTestUtils.getTextViewsWithString(mActivityUnderTest, text);
        assertEquals("There should have been no TextViews with text '" + text + "' but found "
                + views, 0,  views.size());
    }

    private void startActivityUnderTest() throws Throwable {
        assertNull(mActivityUnderTest);
        mActivityUnderTest = getActivity();
        assertNotNull("activity should not be null", mActivityUnderTest);
        // We have to run all tasks, not just one.
        // This is because it seems that we can have onResume, onPause, onResume during the course
        // of a single unit test.
        mFakeAsyncTaskExecutor.runAllTasks(UPDATE_PHONE_CALL_DETAILS);
    }

    private AssetManager getAssets() {
        return getInstrumentation().getContext().getAssets();
    }
}
