/*
 * Copyright (C) 2018 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 android.telecom.cts;

import static android.telecom.cts.TestUtils.TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE;
import static android.telecom.cts.TestUtils.TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE;
import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;

import android.net.Uri;
import android.os.Bundle;
import android.telecom.Call;
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;

/**
 * Tests the Telecom handover APIs.
 */
public class HandoverTest extends BaseTelecomTestWithMockServices {
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mContext = getInstrumentation().getContext();
        if (mShouldTestTelecom) {
            setupConnectionService(null, FLAG_REGISTER | FLAG_ENABLE);

            // Test handover source is a managed ConnectionService
            mTelecomManager.registerPhoneAccount(TestUtils.TEST_PHONE_ACCOUNT_HANDOVER_SRC);
            TestUtils.enablePhoneAccount(getInstrumentation(),
                    TestUtils.TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE);
            assertPhoneAccountEnabled(TestUtils.TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE);

            // Test handover destination is a self-managed ConnectionService.
            mTelecomManager.registerPhoneAccount(TestUtils.TEST_PHONE_ACCOUNT_HANDOVER_DEST);
        }

    }

    @Override
    protected void tearDown() throws Exception {
        CtsSelfManagedConnectionService connectionService =
                CtsSelfManagedConnectionService.getConnectionService();
        if (connectionService != null) {
            connectionService.tearDown();
            mTelecomManager.unregisterPhoneAccount(
                    TestUtils.TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE);
            mTelecomManager.unregisterPhoneAccount(
                    TestUtils.TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE);
        }

        super.tearDown();
    }

    /**
     * Ensures a call handover cannot be initiated for a {@link android.telecom.PhoneAccount} which
     * does not declare {@link android.telecom.PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
     */
    public void testHandoverSourceFailed() {
        if (!mShouldTestTelecom) {
            return;
        }

        placeAndVerifyCall();
        Call call = mInCallCallbacks.getService().getLastCall();

        call.handoverTo(TestUtils.TEST_SELF_MANAGED_HANDLE_1, VideoProfile.STATE_BIDIRECTIONAL,
                null);

        // Expect the handover failed callback to be called.
        mOnHandoverFailedCounter.waitForCount(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
        Call callbackCall = (Call) mOnHandoverFailedCounter.getArgs(0)[0];
        int failureReason = (int) mOnHandoverFailedCounter.getArgs(0)[1];
        assertEquals(call, callbackCall);
        assertEquals(Call.Callback.HANDOVER_FAILURE_NOT_SUPPORTED, failureReason);

        call.disconnect();
    }

    /**
     * Ensures a call handover cannot be initiated to a {@link android.telecom.PhoneAccount} which
     * does not declare {@link android.telecom.PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
     */
    public void testHandoverDestinationFailed() {
        if (!mShouldTestTelecom) {
            return;
        }
        startSourceCall();
        Call call = mInCallCallbacks.getService().getLastCall();

        // Now try to handover to an account which does not support handover.
        call.handoverTo(TestUtils.TEST_SELF_MANAGED_HANDLE_1, VideoProfile.STATE_BIDIRECTIONAL,
                null);

        // Expect the handover failed callback to be called.
        mOnHandoverFailedCounter.waitForCount(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
        Call callbackCall = (Call) mOnHandoverFailedCounter.getArgs(0)[0];
        int failureReason = (int) mOnHandoverFailedCounter.getArgs(0)[1];
        assertEquals(call, callbackCall);
        assertEquals(Call.Callback.HANDOVER_FAILURE_NOT_SUPPORTED, failureReason);

        call.disconnect();
    }

    /**
     * Ensures that when the source and destination both support handover that an outgoing handover
     * request will be successfully relayed.
     */
    public void testOutgoingHandoverRequestValid() {
        if (!mShouldTestTelecom) {
            return;
        }

        // Begin our source call on the CS which supports handover from it.
        startSourceCall();
        final Call call = mInCallCallbacks.getService().getLastCall();

        // Now try to handover to an account which does support handover to it.
        call.handoverTo(TestUtils.TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE,
                VideoProfile.STATE_BIDIRECTIONAL, null);

        // Ensure Telecom bound to the self managed CS
        if (!CtsSelfManagedConnectionService.waitForBinding()) {
            fail("Could not bind to Self-Managed ConnectionService");
        }

        // Wait for binding to self managed CS and invocation of outgoing handover method.
        TestUtils.InvokeCounter counter =
                CtsSelfManagedConnectionService.getConnectionService()
                        .getOnCreateOutgoingHandoverConnectionCounter();
        counter.waitForCount(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);

        SelfManagedConnection connection = TestUtils.waitForAndGetConnection(
                call.getDetails().getHandle());

        // Verify the from handle is as expected.
        PhoneAccountHandle fromHandle = (PhoneAccountHandle) counter.getArgs(0)[0];
        assertEquals(TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE, fromHandle);
        // Verify the to handle is as expected.
        ConnectionRequest request = (ConnectionRequest) counter.getArgs(0)[1];
        assertEquals(TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE, request.getAccountHandle());

        completeHandoverAndVerify(call, connection);
    }

    /**
     * Tests use of the
     * {@link android.telecom.TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} API on
     * the receiving side of the handover.
     */
    public void testIncomingHandoverRequestValid() {
        if (!mShouldTestTelecom) {
            return;
        }

        // Begin our source call on the CS which supports handover from it.
        startSourceCall();
        final Call call = mInCallCallbacks.getService().getLastCall();

        // Request to accept handover of that call to another app.
        mTelecomManager.acceptHandover(call.getDetails().getHandle(),
                VideoProfile.STATE_BIDIRECTIONAL, TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE);

        // Ensure Telecom bound to the self managed CS
        if (!CtsSelfManagedConnectionService.waitForBinding()) {
            fail("Could not bind to Self-Managed ConnectionService");
        }

        // Wait for binding to self managed CS and invocation of incoming handover method.
        TestUtils.InvokeCounter counter =
                CtsSelfManagedConnectionService.getConnectionService()
                        .getOnCreateIncomingHandoverConnectionCounter();
        counter.waitForCount(WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);

        SelfManagedConnection connection = TestUtils.waitForAndGetConnection(
                call.getDetails().getHandle());

        // Verify the from handle is as expected.
        PhoneAccountHandle fromHandle = (PhoneAccountHandle) counter.getArgs(0)[0];
        assertEquals(TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE, fromHandle);
        // Verify the to handle is as expected.
        ConnectionRequest request = (ConnectionRequest) counter.getArgs(0)[1];
        assertEquals(TEST_HANDOVER_DEST_PHONE_ACCOUNT_HANDLE, request.getAccountHandle());
        // The original call's address should match the address of the handover request.
        assertEquals(call.getDetails().getHandle(), request.getAddress());

        completeHandoverAndVerify(call, connection);
    }

    /**
     * Begins a call which will be the source of a handover.
     */
    private void startSourceCall() {
        // Ensure the ongoing account is on a PhoneAccount which supports handover from.
        Bundle extras = new Bundle();
        extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
                TEST_HANDOVER_SRC_PHONE_ACCOUNT_HANDLE);
        placeAndVerifyCall(extras);
        Connection connection = verifyConnectionForOutgoingCall();
        connection.setActive();
        Call call = mInCallCallbacks.getService().getLastCall();
        assertCallState(call, Call.STATE_ACTIVE);
    }

    /**
     * Complete the a call handover and verify that it was successfully reported.
     * @param call
     * @param connection
     */
    private void completeHandoverAndVerify(final Call call, SelfManagedConnection connection) {
        // Make the connection active, indicating that the user has accepted the handover.
        connection.setActive();

        // Expect the original call to have been informed of handover completion.
        mOnHandoverCompleteCounter.waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
        assertTrue("mOnHandoverCompleteCounter is zero",
                mOnHandoverCompleteCounter.getInvokeCount() >= 1);

        // Also expect the connection to be informed of handover completion.
        connection.getHandoverCompleteCounter().waitForCount(1, WAIT_FOR_STATE_CHANGE_TIMEOUT_MS);
        assertTrue("connection's handoverCompleteCounter is zero",
                connection.getHandoverCompleteCounter().getInvokeCount() >= 1);

        // Now, we expect that the original connection will get disconnected.
        waitUntilConditionIsTrueOrTimeout(new Condition() {
                                              @Override
                                              public Object expected() {
                                                  return Call.STATE_DISCONNECTED;
                                              }
                                              @Override
                                              public Object actual() {
                                                  return call.getState();
                                              }
                                          },
                WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
                "Expected original call to be disconnected."
        );
    }
}
