/*
 * 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.server.telecom.tests;

import static com.android.server.telecom.tests.TelecomSystemTest.TEST_TIMEOUT;

import android.content.ComponentName;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Binder;
import android.telecom.DisconnectCause;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.server.telecom.Call;
import com.android.server.telecom.CallIdMapper;
import com.android.server.telecom.ConnectionServiceFocusManager;
import com.android.server.telecom.ConnectionServiceRepository;
import com.android.server.telecom.ConnectionServiceWrapper;
import com.android.server.telecom.CreateConnectionProcessor;
import com.android.server.telecom.CreateConnectionResponse;
import com.android.server.telecom.PhoneAccountRegistrar;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.util.ArrayList;
import java.util.Arrays;

import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
 * Unit testing for CreateConnectionProcessor as well as CreateConnectionTimeout classes.
 */
@RunWith(JUnit4.class)
public class CreateConnectionProcessorTest extends TelecomTestCase {

    private static final String TEST_PACKAGE = "com.android.server.telecom.tests";
    private static final String TEST_CLASS =
            "com.android.server.telecom.tests.MockConnectionService";

    @Mock
    ConnectionServiceRepository mMockConnectionServiceRepository;
    @Mock
    PhoneAccountRegistrar mMockAccountRegistrar;
    @Mock
    CreateConnectionResponse mMockCreateConnectionResponse;
    @Mock
    Call mMockCall;
    @Mock
    ConnectionServiceFocusManager mConnectionServiceFocusManager;

    CreateConnectionProcessor mTestCreateConnectionProcessor;

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        MockitoAnnotations.initMocks(this);
        mContext = mComponentContextFixture.getTestDouble().getApplicationContext();

        when(mMockCall.getConnectionServiceFocusManager()).thenReturn(
                mConnectionServiceFocusManager);
        doAnswer(new Answer<Void>() {
                     @Override
                     public Void answer(InvocationOnMock invocation) {
                         Object[] args = invocation.getArguments();
                         ConnectionServiceFocusManager.CallFocus focus =
                                 (ConnectionServiceFocusManager.CallFocus) args[0];
                         ConnectionServiceFocusManager.RequestFocusCallback callback =
                                 (ConnectionServiceFocusManager.RequestFocusCallback) args[1];
                         callback.onRequestFocusDone(focus);
                         return null;
                     }
                 }
                ).when(mConnectionServiceFocusManager).requestFocus(any(), any());

        mTestCreateConnectionProcessor = new CreateConnectionProcessor(mMockCall,
                mMockConnectionServiceRepository, mMockCreateConnectionResponse,
                mMockAccountRegistrar, mContext);
    }

    @Override
    @After
    public void tearDown() throws Exception {
        mTestCreateConnectionProcessor = null;
        super.tearDown();
    }

    @SmallTest
    @Test
    public void testSimPhoneAccountSuccess() throws Exception {
        PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
        when(mMockCall.isEmergencyCall()).thenReturn(false);
        // No Connection Manager in this case
        when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(null);
        ConnectionServiceWrapper service = makeConnectionServiceWrapper();

        mTestCreateConnectionProcessor.process();

        verify(mMockCall).setConnectionManagerPhoneAccount(eq(pAHandle));
        verify(mMockCall).setTargetPhoneAccount(eq(pAHandle));
        verify(mMockCall).setConnectionService(eq(service));
        verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
        // Notify successful connection to call
        CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
        mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
        verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
    }

    @SmallTest
    @Test
    public void testbadPhoneAccount() throws Exception {
        PhoneAccountHandle pAHandle = null;
        when(mMockCall.isEmergencyCall()).thenReturn(false);
        when(mMockCall.getTargetPhoneAccount()).thenReturn(pAHandle);
        givePhoneAccountBindPermission(pAHandle);
        // No Connection Manager in this case
        when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(null);
        ConnectionServiceWrapper service = makeConnectionServiceWrapper();

        mTestCreateConnectionProcessor.process();

        verify(service, never()).createConnection(eq(mMockCall),
                any(CreateConnectionResponse.class));
        verify(mMockCreateConnectionResponse).handleCreateConnectionFailure(
                eq(new DisconnectCause(DisconnectCause.ERROR)));
    }

    @SmallTest
    @Test
    public void testConnectionManagerSuccess() throws Exception {
        PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
        when(mMockCall.isEmergencyCall()).thenReturn(false);
        // Include a Connection Manager
        PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandle("cm_acct");
        ConnectionServiceWrapper service = makeConnectionServiceWrapper();
        // Make sure the target phone account has the correct permissions
        PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct",
                PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
        when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn(
                mFakeTargetPhoneAccount);

        mTestCreateConnectionProcessor.process();

        verify(mMockCall).setConnectionManagerPhoneAccount(eq(callManagerPAHandle));
        verify(mMockCall).setTargetPhoneAccount(eq(pAHandle));
        verify(mMockCall).setConnectionService(eq(service));
        verify(service).createConnection(eq(mMockCall),
                any(CreateConnectionResponse.class));
        // Notify successful connection to call
        CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
        mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
        verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
    }

    @SmallTest
    @Test
    public void testConnectionManagerFailedFallToSim() throws Exception {
        PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
        when(mMockCall.isEmergencyCall()).thenReturn(false);
        // Include a Connection Manager
        PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandle("cm_acct");
        ConnectionServiceWrapper service = makeConnectionServiceWrapper();
        when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
        PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct",
                PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
        when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn(
                mFakeTargetPhoneAccount);
        when(mMockCall.getConnectionService()).thenReturn(service);
        // Put CreateConnectionProcessor in correct state to fail with ConnectionManager
        mTestCreateConnectionProcessor.process();
        reset(mMockCall);
        reset(service);

        when(mMockCall.getConnectionServiceFocusManager()).thenReturn(
                mConnectionServiceFocusManager);
        // Notify that the ConnectionManager has denied the call.
        when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
        when(mMockCall.getConnectionService()).thenReturn(service);
        mTestCreateConnectionProcessor.handleCreateConnectionFailure(
                new DisconnectCause(DisconnectCause.CONNECTION_MANAGER_NOT_SUPPORTED));

        // Verify that the Sim Phone Account is used correctly
        verify(mMockCall).setConnectionManagerPhoneAccount(eq(pAHandle));
        verify(mMockCall).setTargetPhoneAccount(eq(pAHandle));
        verify(mMockCall).setConnectionService(eq(service));
        verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
        // Notify successful connection to call
        CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
        mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
        verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
    }

    @SmallTest
    @Test
    public void testConnectionManagerFailedDoNotFallToSim() throws Exception {
        PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
        when(mMockCall.isEmergencyCall()).thenReturn(false);
        // Include a Connection Manager
        PhoneAccountHandle callManagerPAHandle = getNewConnectionMangerHandle("cm_acct");
        ConnectionServiceWrapper service = makeConnectionServiceWrapper();
        when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
        PhoneAccount mFakeTargetPhoneAccount = makeQuickAccount("cm_acct",
                PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
        when(mMockAccountRegistrar.getPhoneAccountUnchecked(pAHandle)).thenReturn(
                mFakeTargetPhoneAccount);
        when(mMockCall.getConnectionService()).thenReturn(service);
        // Put CreateConnectionProcessor in correct state to fail with ConnectionManager
        mTestCreateConnectionProcessor.process();
        reset(mMockCall);
        reset(service);

        when(mMockCall.getConnectionServiceFocusManager()).thenReturn(
                mConnectionServiceFocusManager);
        // Notify that the ConnectionManager has rejected the call.
        when(mMockCall.getConnectionManagerPhoneAccount()).thenReturn(callManagerPAHandle);
        when(mMockCall.getConnectionService()).thenReturn(service);
        when(service.isServiceValid("createConnection")).thenReturn(true);
        mTestCreateConnectionProcessor.handleCreateConnectionFailure(
                new DisconnectCause(DisconnectCause.OTHER));

        // Verify call connection rejected
        verify(mMockCreateConnectionResponse).handleCreateConnectionFailure(
                new DisconnectCause(DisconnectCause.OTHER));
    }

    @SmallTest
    @Test
    public void testEmergencyCallToSim() throws Exception {
        when(mMockCall.isEmergencyCall()).thenReturn(true);
        // Put in a regular phone account to be sure it doesn't call that
        PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
        // Include a Connection Manager to be sure it doesn't call that
        PhoneAccount callManagerPA = getNewConnectionManagerPhoneAccount("cm_acct", 0);
        ConnectionServiceWrapper service = makeConnectionServiceWrapper();
        PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer");
        PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle();

        mTestCreateConnectionProcessor.process();

        verify(mMockCall).setConnectionManagerPhoneAccount(eq(emergencyPhoneAccountHandle));
        verify(mMockCall).setTargetPhoneAccount(eq(emergencyPhoneAccountHandle));
        verify(mMockCall).setConnectionService(eq(service));
        verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
        // Notify successful connection to call
        CallIdMapper mockCallIdMapper = mock(CallIdMapper.class);
        mTestCreateConnectionProcessor.handleCreateConnectionSuccess(mockCallIdMapper, null);
        verify(mMockCreateConnectionResponse).handleCreateConnectionSuccess(mockCallIdMapper, null);
    }

    @SmallTest
    @Test
    public void testEmergencyCallSimFailToConnectionManager() throws Exception {
        when(mMockCall.isEmergencyCall()).thenReturn(true);
        when(mMockCall.getHandle()).thenReturn(Uri.parse(""));
        // Put in a regular phone account to be sure it doesn't call that
        PhoneAccountHandle pAHandle = getNewTargetPhoneAccountHandle("tel_acct");
        when(mMockAccountRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
                nullable(String.class))).thenReturn(pAHandle);
        // Include a normal Connection Manager to be sure it doesn't call that
        PhoneAccount callManagerPA = getNewConnectionManagerPhoneAccount("cm_acct", 0);
        // Include a connection Manager for the user with the capability to make calls
        PhoneAccount emerCallManagerPA = getNewEmergencyConnectionManagerPhoneAccount("cm_acct",
                PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS);
        ConnectionServiceWrapper service = makeConnectionServiceWrapper();
        PhoneAccount emergencyPhoneAccount = makeEmergencyPhoneAccount("tel_emer");
        mTestCreateConnectionProcessor.process();
        reset(mMockCall);
        reset(service);

        when(mMockCall.getConnectionServiceFocusManager()).thenReturn(
                mConnectionServiceFocusManager);
        when(mMockCall.isEmergencyCall()).thenReturn(true);

        // When Notify SIM connection fails, fall back to connection manager
        mTestCreateConnectionProcessor.handleCreateConnectionFailure(new DisconnectCause(
                DisconnectCause.REJECTED));

        verify(mMockCall).setConnectionManagerPhoneAccount(
                eq(emerCallManagerPA.getAccountHandle()));
        verify(mMockCall).setTargetPhoneAccount(eq(pAHandle));
        verify(mMockCall).setConnectionService(eq(service));
        verify(service).createConnection(eq(mMockCall), any(CreateConnectionResponse.class));
    }

    private PhoneAccount makeEmergencyPhoneAccount(String id) {
        final PhoneAccount emergencyPhoneAccount = makeQuickAccount(id,
                PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS |
                        PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION);
        PhoneAccountHandle emergencyPhoneAccountHandle = emergencyPhoneAccount.getAccountHandle();
        givePhoneAccountBindPermission(emergencyPhoneAccountHandle);
        ArrayList<PhoneAccount> phoneAccounts = new ArrayList<PhoneAccount>() {{
            add(emergencyPhoneAccount);
        }};
        when(mMockAccountRegistrar.getAllPhoneAccountsOfCurrentUser()).thenReturn(phoneAccounts);
        return emergencyPhoneAccount;
    }

    private void givePhoneAccountBindPermission(PhoneAccountHandle handle) {
        when(mMockAccountRegistrar.phoneAccountRequiresBindPermission(eq(handle))).thenReturn(true);
    }

    private PhoneAccountHandle getNewConnectionMangerHandle(String id) {
        PhoneAccountHandle callManagerPAHandle = makeQuickAccountHandle(id);
        when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(
                callManagerPAHandle);
        givePhoneAccountBindPermission(callManagerPAHandle);
        return callManagerPAHandle;
    }

    private PhoneAccountHandle getNewTargetPhoneAccountHandle(String id) {
        PhoneAccountHandle pAHandle = makeQuickAccountHandle(id);
        when(mMockCall.getTargetPhoneAccount()).thenReturn(pAHandle);
        givePhoneAccountBindPermission(pAHandle);
        return pAHandle;
    }

    private PhoneAccount getNewConnectionManagerPhoneAccount(String id, int capability) {
        PhoneAccount callManagerPA = makeQuickAccount(id, capability);
        when(mMockAccountRegistrar.getSimCallManagerFromCall(any(Call.class))).thenReturn(
                callManagerPA.getAccountHandle());
        givePhoneAccountBindPermission(callManagerPA.getAccountHandle());
        when(mMockAccountRegistrar.getPhoneAccountUnchecked(
                callManagerPA.getAccountHandle())).thenReturn(callManagerPA);
        return callManagerPA;
    }

    private PhoneAccount getNewEmergencyConnectionManagerPhoneAccount(String id, int capability) {
        PhoneAccount callManagerPA = makeQuickAccount(id, capability);
        when(mMockAccountRegistrar.getSimCallManagerOfCurrentUser()).thenReturn(
                callManagerPA.getAccountHandle());
        givePhoneAccountBindPermission(callManagerPA.getAccountHandle());
        when(mMockAccountRegistrar.getPhoneAccountUnchecked(
                callManagerPA.getAccountHandle())).thenReturn(callManagerPA);
        return callManagerPA;
    }

    private static ComponentName makeQuickConnectionServiceComponentName() {
        return new ComponentName(TEST_PACKAGE, TEST_CLASS);
    }

    private ConnectionServiceWrapper makeConnectionServiceWrapper() {
        ConnectionServiceWrapper wrapper = mock(ConnectionServiceWrapper.class);
        when(mMockConnectionServiceRepository.getService(
                eq(makeQuickConnectionServiceComponentName()),
                eq(Binder.getCallingUserHandle()))).thenReturn(wrapper);
        return wrapper;
    }

    private static PhoneAccountHandle makeQuickAccountHandle(String id) {
        return new PhoneAccountHandle(makeQuickConnectionServiceComponentName(), id,
                Binder.getCallingUserHandle());
    }

    private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) {
        return new PhoneAccount.Builder(makeQuickAccountHandle(id), "label" + idx);
    }

    private PhoneAccount makeQuickAccount(String id, int idx) {
        return makeQuickAccountBuilder(id, idx)
                .setAddress(Uri.parse("http://foo.com/" + idx))
                .setSubscriptionAddress(Uri.parse("tel:555-000" + idx))
                .setCapabilities(idx)
                .setIcon(Icon.createWithResource(
                        "com.android.server.telecom.tests", R.drawable.stat_sys_phone_call))
                .setShortDescription("desc" + idx)
                .setIsEnabled(true)
                .build();
    }
}