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

import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.UserHandle;
import android.telecom.GatewayInfo;
import android.telecom.PhoneAccountHandle;
import android.telephony.TelephonyManager;

import com.android.internal.telecom.ICallRedirectionAdapter;
import com.android.internal.telecom.ICallRedirectionService;
import com.android.server.telecom.Call;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.PhoneAccountRegistrar;
import com.android.server.telecom.SystemStateHelper;
import com.android.server.telecom.TelecomSystem;
import com.android.server.telecom.Timeouts;

import com.android.server.telecom.callredirection.CallRedirectionProcessor;
import com.android.server.telecom.callredirection.CallRedirectionProcessorHelper;

import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;

import org.junit.Before;

import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(JUnit4.class)
public class CallRedirectionProcessorTest extends TelecomTestCase {
    @Mock private Context mContext;
    @Mock private CallsManager mCallsManager;
    @Mock private PhoneAccountRegistrar mPhoneAccountRegistrar;
    @Mock private PhoneAccountHandle mPhoneAccountHandle;
    private TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { };

    @Mock private Call mCall;

    @Mock private PackageManager mPackageManager;
    @Mock private TelephonyManager mTelephonyManager;
    @Mock private IBinder mBinder;
    @Mock private ICallRedirectionService mCallRedirectionService;

    @Mock private SystemStateHelper mSystemStateHelper;
    @Mock private CallRedirectionProcessorHelper mCallRedirectionProcessorHelper;

    @Mock private Uri mHandle;
    @Mock private GatewayInfo mGatewayInfo;
    @Mock private UserHandle mUserHandle;
    @Mock private ContentResolver mContentResolver;

    @Mock private Timeouts.Adapter mTimeoutsAdapter;

    private static final Uri ORIGINAL_NUMBER_WITH_POST_DIAL = Uri.parse("tel:6505551212,,,1234");
    private static final Uri ORIGINAL_NUMBER_NO_POST_DIAL = Uri.parse("tel:6505551212");
    private static final Uri REDIRECTED_GATEWAY_NUMBER = Uri.parse("tel:6505551213");
    private static final Uri REDIRECTED_GATEWAY_NUMBER_WITH_POST_DIAL =
            Uri.parse("tel:6505551213,,,1234");
    private static final String USER_DEFINED_PKG_NAME = "user_defined_pkg";
    private static final String USER_DEFINED_CLS_NAME = "user_defined_cls";
    private static final String CARRIER_PKG_NAME = "carrier_pkg";
    private static final String CARRIER_CLS_NAME = "carrier_cls";

    private static final long HANDLER_TIMEOUT_DELAY = 5000;
    private static final long USER_DEFINED_SHORT_TIMEOUT_MS = 1200;
    private static final long CARRIER_SHORT_TIMEOUT_MS = 400;
    private static final long CODE_EXECUTION_DELAY = 500;

    // TODO integerate with a test user-defined service
    private static final ComponentName USER_DEFINED_SERVICE_TEST_COMPONENT_NAME =
            new ComponentName(USER_DEFINED_PKG_NAME, USER_DEFINED_CLS_NAME);
    // TODO integerate with a test carrier service
    private static final ComponentName CARRIER_SERVICE_TEST_COMPONENT_NAME =
            new ComponentName(CARRIER_PKG_NAME, CARRIER_CLS_NAME);

    private static final boolean SPEAKER_PHONE_ON = true;
    private static final int VIDEO_STATE = 0;

    private CallRedirectionProcessor mProcessor;

    @Override
    @Before
    public void setUp() throws Exception {
        super.setUp();
        when(mCall.getTargetPhoneAccount()).thenReturn(mPhoneAccountHandle);
        when(mCallsManager.getCurrentUserHandle()).thenReturn(UserHandle.CURRENT);
        when(mContext.getPackageManager()).thenReturn(mPackageManager);
        when(mContext.getContentResolver()).thenReturn(mContentResolver);
        doReturn(mCallRedirectionService).when(mBinder).queryLocalInterface(anyString());
        when(mCallsManager.getSystemStateHelper()).thenReturn(mSystemStateHelper);
        when(mCallsManager.getTimeoutsAdapter()).thenReturn(mTimeoutsAdapter);
        when(mTimeoutsAdapter.getUserDefinedCallRedirectionTimeoutMillis(mContentResolver))
                .thenReturn(USER_DEFINED_SHORT_TIMEOUT_MS);
        when(mTimeoutsAdapter.getCarrierCallRedirectionTimeoutMillis(mContentResolver))
                .thenReturn(CARRIER_SHORT_TIMEOUT_MS);
        when(mCallsManager.getLock()).thenReturn(mLock);
        when(mCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
        when(mTelephonyManager.getNetworkCountryIso()).thenReturn("");
        when(mContext.bindServiceAsUser(nullable(Intent.class), nullable(ServiceConnection.class),
                anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
    }

    @Override
    @After
    public void tearDown() throws Exception {
        mProcessor.getHandler().removeCallbacksAndMessages(null);
        waitForHandlerAction(new Handler(Looper.getMainLooper()), TelecomSystemTest.TEST_TIMEOUT);
        super.tearDown();
    }

    private void setIsInCarMode(boolean isInCarMode) {
        when(mSystemStateHelper.isCarModeOrProjectionActive()).thenReturn(isInCarMode);
    }

    private void enableUserDefinedCallRedirectionService() {
        when(mCallRedirectionProcessorHelper.getUserDefinedCallRedirectionService()).thenReturn(
                USER_DEFINED_SERVICE_TEST_COMPONENT_NAME);
    }

    private void enableCarrierCallRedirectionService() {
        when(mCallRedirectionProcessorHelper.getCarrierCallRedirectionService(
                any(PhoneAccountHandle.class))).thenReturn(CARRIER_SERVICE_TEST_COMPONENT_NAME);
    }

    private void disableUserDefinedCallRedirectionService() {
        when(mCallRedirectionProcessorHelper.getUserDefinedCallRedirectionService()).thenReturn(
                null);
    }

    private void disableCarrierCallRedirectionService() {
        when(mCallRedirectionProcessorHelper.getCarrierCallRedirectionService(any())).thenReturn(
                null);
    }

    private void startProcessWithNoGateWayInfo() {
        startProcessWithNoGateWayInfo(mHandle);
    }

    private void startProcessWithNoGateWayInfo(Uri handle) {
        mProcessor = new CallRedirectionProcessor(mContext, mCallsManager, mCall, handle,
                mPhoneAccountRegistrar, null, SPEAKER_PHONE_ON, VIDEO_STATE);
        mProcessor.setCallRedirectionServiceHelper(mCallRedirectionProcessorHelper);
    }

    private void startProcessWithGateWayInfo() {
        mProcessor = new CallRedirectionProcessor(mContext, mCallsManager, mCall, mHandle,
                mPhoneAccountRegistrar, mGatewayInfo, SPEAKER_PHONE_ON, VIDEO_STATE);
        mProcessor.setCallRedirectionServiceHelper(mCallRedirectionProcessorHelper);
    }

    @Test
    public void testNoUserDefinedServiceNoCarrierSerivce() {
        startProcessWithNoGateWayInfo();
        disableUserDefinedCallRedirectionService();
        disableCarrierCallRedirectionService();
        mProcessor.performCallRedirection();
        verify(mContext, times(0)).bindServiceAsUser(any(Intent.class),
                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), eq(mHandle),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
    }

    @Test
    public void testCarrierServiceTimeoutNoUserDefinedService() throws Exception {
        startProcessWithNoGateWayInfo();
        // To make sure tests are not flaky, clean all the previous handler messages
        waitForHandlerAction(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY);
        disableUserDefinedCallRedirectionService();
        enableCarrierCallRedirectionService();
        mProcessor.performCallRedirection();
        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
        verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
        waitForHandlerActionDelayed(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY,
                CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
    }

    @Test
    public void testUserDefinedServiceTimeoutNoCarrierService() throws Exception {
        startProcessWithNoGateWayInfo();
        // To make sure tests are not flaky, clean all the previous handler messages
        waitForHandlerAction(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY);
        enableUserDefinedCallRedirectionService();
        disableCarrierCallRedirectionService();
        mProcessor.performCallRedirection();
        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
        verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(false), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));

        // Test it is waiting for a User-defined timeout, not a Carrier timeout
        Thread.sleep(CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
        verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(false), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));

        // Wait for the rest of user-defined timeout time.
        waitForHandlerActionDelayed(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY,
                USER_DEFINED_SHORT_TIMEOUT_MS - CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(true), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
    }

    @Test
    public void testUserDefinedServiceTimeoutAndCarrierServiceTimeout() throws Exception {
        startProcessWithNoGateWayInfo();
        // To make sure tests are not flaky, clean all the previous handler messages
        waitForHandlerAction(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY);
        enableUserDefinedCallRedirectionService();
        enableCarrierCallRedirectionService();
        mProcessor.performCallRedirection();

        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
        verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(false), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));

        // Test it is waiting for a User-defined timeout, not a Carrier timeout
        Thread.sleep(CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
        verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(false), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));

        // Wait for the rest of user-defined timeout time.
        waitForHandlerActionDelayed(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY,
                USER_DEFINED_SHORT_TIMEOUT_MS - CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(true), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));

        // Wait for another carrier timeout time, but should not expect any carrier service request
        // is triggered.
        Thread.sleep(CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(true), eq(CallRedirectionProcessor.UI_TYPE_USER_DEFINED_TIMEOUT));
    }

    @Test
    public void testProcessGatewayCall() {
        startProcessWithGateWayInfo();
        enableUserDefinedCallRedirectionService();
        enableCarrierCallRedirectionService();
        mProcessor.performCallRedirection();
        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
                any(ServiceConnection.class), anyInt(), any(UserHandle.class));
        verify(mCallsManager, times(0)).onCallRedirectionComplete(eq(mCall), any(),
                eq(mPhoneAccountHandle), eq(null), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
        waitForHandlerActionDelayed(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY,
                CARRIER_SHORT_TIMEOUT_MS + CODE_EXECUTION_DELAY);
        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall), eq(mHandle),
                eq(mPhoneAccountHandle), eq(mGatewayInfo), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
    }

    @Test
    public void testStripPostDialDigits() throws Exception {
        startProcessWithNoGateWayInfo(ORIGINAL_NUMBER_WITH_POST_DIAL);
        enableUserDefinedCallRedirectionService();
        disableCarrierCallRedirectionService();

        mProcessor.performCallRedirection();

        // Capture binding and mock it out.
        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor = ArgumentCaptor.forClass(
                ServiceConnection.class);
        verify(mContext, times(1)).bindServiceAsUser(any(Intent.class),
                serviceConnectionCaptor.capture(), anyInt(), any(UserHandle.class));

        // Mock out a service which performed a redirection
        IBinder mockBinder = mock(IBinder.class);
        ICallRedirectionService mockCallRedirectionService = mock(ICallRedirectionService.class);
        when(mockBinder.queryLocalInterface(anyString())).thenReturn(mockCallRedirectionService);
        serviceConnectionCaptor.getValue().onServiceConnected(
                USER_DEFINED_SERVICE_TEST_COMPONENT_NAME, mockBinder);

        ArgumentCaptor<ICallRedirectionAdapter> redirectionAdapterCaptor = ArgumentCaptor.forClass(
                ICallRedirectionAdapter.class);
        ArgumentCaptor<Uri> uriArgumentCaptor = ArgumentCaptor.forClass(Uri.class);
        verify(mockCallRedirectionService, times(1)).placeCall(redirectionAdapterCaptor.capture(),
                uriArgumentCaptor.capture(), any(), anyBoolean());

        // Verify the service did not get passed post-dial digits.
        assertEquals(ORIGINAL_NUMBER_NO_POST_DIAL, uriArgumentCaptor.getValue());

        // Pretend it was verified.
        redirectionAdapterCaptor.getValue().redirectCall(REDIRECTED_GATEWAY_NUMBER,
                mPhoneAccountHandle, false);

        waitForHandlerAction(mProcessor.getHandler(), HANDLER_TIMEOUT_DELAY);

        ArgumentCaptor<GatewayInfo> gatewayInfoArgumentCaptor = ArgumentCaptor.forClass(
                GatewayInfo.class);
        verify(mCallsManager, times(1)).onCallRedirectionComplete(eq(mCall),
                eq(ORIGINAL_NUMBER_WITH_POST_DIAL), eq(mPhoneAccountHandle),
                gatewayInfoArgumentCaptor.capture(), eq(SPEAKER_PHONE_ON), eq(VIDEO_STATE),
                eq(false), eq(CallRedirectionProcessor.UI_TYPE_NO_ACTION));
        assertEquals(REDIRECTED_GATEWAY_NUMBER_WITH_POST_DIAL,
                gatewayInfoArgumentCaptor.getValue().getGatewayAddress());
    }
}
