/*
 * Copyright (C) 2020 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 android.app.ActivityManager;
import android.app.UiAutomation;
import android.app.role.RoleManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.IBinder;
import android.os.UserHandle;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.cts.carmodetestapp.CtsCarModeInCallServiceControl;
import android.telecom.cts.carmodetestapp.ICtsCarModeInCallServiceControl;
import android.telecom.cts.carmodetestappselfmanaged.CtsCarModeInCallServiceControlSelfManaged;
import android.telecom.cts.carmodetestapptwo.CtsCarModeInCallServiceControlTwo;
import android.telecom.cts.thirdptydialer.CtsThirdPtyDialerInCallServiceControl;
import android.telecom.cts.thirdptydialertwo.CtsThirdPtyDialerInCallServiceControlTwo;
import android.telecom.cts.thirdptyincallservice.CtsThirdPartyInCallServiceControl;
import android.telecom.cts.thirdptyincallservice.ICtsThirdPartyInCallServiceControl;
import android.util.Log;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;

public class SelfManagedConnectionTest extends BaseTelecomTestWithMockServices {
    private static final String TAG = "SelfManagedConnectionTest";
    private static final long TIMEOUT = 3000L;
    private static final String THIRD_PTY_CONTROL =
            CtsThirdPartyInCallServiceControl.CONTROL_INTERFACE_ACTION;
    private static final String CAR_MODE_CONTROL =
            "android.telecom.cts.carmodetestapp.ACTION_CAR_MODE_CONTROL";
    private static final ComponentName NON_UI_INCALLSERVICE = ComponentName.createRelative(
            CtsThirdPartyInCallServiceControl.class.getPackage().getName(),
            CtsThirdPartyInCallServiceControl.class.getName());
    // Default dialer that not support self-managed calls
    private static final String DEFAULT_DIALER_PKG_1 = CtsThirdPtyDialerInCallServiceControl.class
            .getPackage().getName();
    private static final ComponentName DEFAULT_DIALER_INCALLSERVICE_1 = ComponentName
            .createRelative(DEFAULT_DIALER_PKG_1,
                    CtsThirdPtyDialerInCallServiceControl.class.getName());
    // Default dialerhat support self-managed calls
    private static final String DEFAULT_DIALER_PKG_2 = CtsThirdPtyDialerInCallServiceControlTwo
            .class.getPackage().getName();
    private static final ComponentName DEFAULT_DIALER_INCALLSERVICE_2 = ComponentName
            .createRelative(DEFAULT_DIALER_PKG_2,
                    CtsThirdPtyDialerInCallServiceControlTwo.class.getName());
    private static final String CAR_DIALER_PKG_1 = CtsCarModeInCallServiceControl.class
            .getPackage().getName();
    private static final ComponentName CAR_DIALER_1 = ComponentName.createRelative(
            CAR_DIALER_PKG_1, CtsCarModeInCallServiceControl.class.getName());
    private static final String CAR_DIALER_PKG_2 = CtsCarModeInCallServiceControlTwo.class
            .getPackage().getName();
    private static final String CAR_SELF_MANAGED_PKG =
            CtsCarModeInCallServiceControlSelfManaged.class
                    .getPackage().getName();
    private static final ComponentName CAR_DIALER_2 = ComponentName.createRelative(
            CAR_DIALER_PKG_2, CtsCarModeInCallServiceControlTwo.class.getName());
    private static final ComponentName CAR_SELF_MANAGED_COMPONENT = ComponentName.createRelative(
            CAR_SELF_MANAGED_PKG, CtsCarModeInCallServiceControlSelfManaged.class.getName());

    private Uri TEST_ADDRESS = Uri.fromParts("tel", "6505551213", null);

    private static final PhoneAccountHandle TEST_CAR_SELF_MANAGED_HANDLE =
            new PhoneAccountHandle(
                    new ComponentName(CAR_SELF_MANAGED_PKG, TestUtils.SELF_MANAGED_COMPONENT),
                    TestUtils.SELF_MANAGED_ACCOUNT_ID_1);

    private static final PhoneAccount TEST_SELF_MANAGED_PHONE_ACCOUNT = PhoneAccount.builder(
                    TEST_CAR_SELF_MANAGED_HANDLE, TestUtils.SELF_MANAGED_ACCOUNT_LABEL)
            .setAddress(Uri.parse("sip:test@test.com"))
            .setSubscriptionAddress(Uri.parse("sip:test@test.com"))
            .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED
                    | PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING
                    | PhoneAccount.CAPABILITY_VIDEO_CALLING)
            .setHighlightColor(Color.BLUE)
            .setShortDescription(TestUtils.SELF_MANAGED_ACCOUNT_LABEL)
            .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
            .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
            .setExtras(TestUtils.SELF_MANAGED_ACCOUNT_1_EXTRAS)
            .build();

    private RoleManager mRoleManager;
    private String mDefaultDialer;
    private UiAutomation mUiAutomation;
    private ICtsCarModeInCallServiceControl mCarModeIncallServiceControlOne;
    private ICtsCarModeInCallServiceControl mCarModeIncallServiceControlTwo;
    private ICtsCarModeInCallServiceControl mCarModeIncallServiceControlSelfManaged;

    private class TestServiceConnection implements ServiceConnection {
        private IBinder mService;
        private CountDownLatch mLatch = new CountDownLatch(1);
        private boolean mIsConnected;

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder service) {
            Log.i(TAG, "Service Connected: " + componentName);
            mService = service;
            mIsConnected = true;
            mLatch.countDown();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mService = null;
        }

        public IBinder getService() {
            return mService;
        }

        public boolean waitBind() {
            try {
                mLatch.await(TIMEOUT, TimeUnit.MILLISECONDS);
                return mIsConnected;
            } catch (InterruptedException e) {
                return false;
            }
        }
    }

    @Override
    protected void setUp() throws Exception {
        if (!mShouldTestTelecom) {
            return;
        }
        super.setUp();
        NewOutgoingCallBroadcastReceiver.reset();
        mContext = getInstrumentation().getContext();
        mUiAutomation = getInstrumentation().getUiAutomation();
        if (mShouldTestTelecom) {
            mRoleManager = mContext.getSystemService(RoleManager.class);
            setupConnectionService(null, FLAG_ENABLE | FLAG_REGISTER);
            mTelecomManager.registerPhoneAccount(TestUtils.TEST_SELF_MANAGED_PHONE_ACCOUNT_4);
            mDefaultDialer = getDefaultDialer();
        }
    }

    @Override
    protected void tearDown() throws Exception {
        if (!mShouldTestTelecom) {
            return;
        }
        super.tearDown();

        disableAndVerifyCarMode(mCarModeIncallServiceControlOne, Configuration.UI_MODE_TYPE_NORMAL);
        disableAndVerifyCarMode(mCarModeIncallServiceControlTwo, Configuration.UI_MODE_TYPE_NORMAL);

        disconnectAllCallsAndVerify(mCarModeIncallServiceControlOne);
        disconnectAllCallsAndVerify(mCarModeIncallServiceControlTwo);

        CtsSelfManagedConnectionService connectionService =
                CtsSelfManagedConnectionService.getConnectionService();
        if (connectionService != null) {
            connectionService.tearDown();
            mTelecomManager.unregisterPhoneAccount(TestUtils.TEST_SELF_MANAGED_HANDLE_4);
            assertTrue(setDefaultDialer(mDefaultDialer));
        }
    }

    /**
     * Test bind to non-UI in call services that support self-managed connections
     */
    public void testBindToSupportNonUiInCallService() throws Exception {
        if (!mShouldTestTelecom) {
            return;
        }
        TestServiceConnection controlConn = setUpControl(THIRD_PTY_CONTROL,
                NON_UI_INCALLSERVICE);
        ICtsThirdPartyInCallServiceControl control = ICtsThirdPartyInCallServiceControl.Stub
                .asInterface(controlConn.getService());
        control.resetLatchForServiceBound(true /* bind */);

        mUiAutomation.adoptShellPermissionIdentity("android.permission.CONTROL_INCALL_EXPERIENCE");
        SelfManagedConnection connection = placeAndVerifySelfManagedCall();
        control.checkBindStatus(true /* bindStatus */);
        assertTrue(control.checkBindStatus(true /* bindStatus */));
        connection.waitOnInCallServiceTrackingChanged();
        assertTrue(connection.isTracked());
        mUiAutomation.dropShellPermissionIdentity();

        connection.disconnectAndDestroy();
        assertIsInCall(false);
        mContext.unbindService(controlConn);
    }

    /**
     * Test bind to default dialer that support self-managed connections when device is not in car
     * mode
     */
    public void testBindToSupportDefaultDialerNoCarMode() throws Exception {
        if (!mShouldTestTelecom) {
            return;
        }
        TestServiceConnection controlConn = setUpControl(THIRD_PTY_CONTROL,
                DEFAULT_DIALER_INCALLSERVICE_2);
        ICtsThirdPartyInCallServiceControl control = ICtsThirdPartyInCallServiceControl.Stub
                .asInterface(controlConn.getService());
        TestUtils.setDefaultDialer(getInstrumentation(), DEFAULT_DIALER_PKG_2);
        control.resetLatchForServiceBound(true /* bind */);

        SelfManagedConnection connection = placeAndVerifySelfManagedCall();
        assertTrue(control.checkBindStatus(true /* bindStatus */));

        connection.waitOnInCallServiceTrackingChanged();
        assertTrue(connection.isAlternativeUiShowing());
        mUiAutomation.dropShellPermissionIdentity();

        connection.disconnectAndDestroy();
        assertIsInCall(false);
        mContext.unbindService(controlConn);
    }

    /**
     * Test not bind to default dialer that not support self-managed connections when device is not
     * in car mode
     */
    public void testNoBindToUnsupportDefaultDialerNoCarMode() throws Exception {
        if (!mShouldTestTelecom) {
            return;
        }
        TestServiceConnection controlConn = setUpControl(THIRD_PTY_CONTROL,
                DEFAULT_DIALER_INCALLSERVICE_1);
        ICtsThirdPartyInCallServiceControl control = ICtsThirdPartyInCallServiceControl.Stub
                .asInterface(controlConn.getService());
        assertTrue(setDefaultDialer(DEFAULT_DIALER_PKG_1));
        control.resetLatchForServiceBound(true /* bind */);

        SelfManagedConnection connection = placeAndVerifySelfManagedCall();
        assertFalse(control.checkBindStatus(true /* bindStatus */));

        connection.disconnectAndDestroy();
        assertIsInCall(false);
        mContext.unbindService(controlConn);
    }

    public void testEnterCarMode() throws Exception {
        if (!mShouldTestTelecom) {
            return;
        }
        TestServiceConnection controlConn = setUpControl(CAR_MODE_CONTROL,
                CAR_DIALER_1);
        mCarModeIncallServiceControlOne = ICtsCarModeInCallServiceControl.Stub
                .asInterface(controlConn.getService());
        mCarModeIncallServiceControlOne.reset();

        SelfManagedConnection connection = placeAndVerifySelfManagedCall();
        mUiAutomation.adoptShellPermissionIdentity(
                "android.permission.ENTER_CAR_MODE_PRIORITIZED",
                "android.permission.CONTROL_INCALL_EXPERIENCE");
        mCarModeIncallServiceControlOne.enableCarMode(1000);
        assertTrue(mCarModeIncallServiceControlOne.checkBindStatus(true /* bindStatus */));
        mCarModeIncallServiceControlOne.disableCarMode();
        mUiAutomation.dropShellPermissionIdentity();

        connection.disconnectAndDestroy();
        assertIsInCall(false);
        mContext.unbindService(controlConn);
    }

    /**
     * Test {@link TelecomManager#getOwnSelfManagedPhoneAccounts} works on packages with only the
     * {@link android.Manifest.permission#MANAGE_OWN_CALLS} permission.
     */
    public void testTelecomManagerGetSelfManagedPhoneAccountsForPackage() throws Exception {
        if (!mShouldTestTelecom) {
            return;
        }
        // bind to CarModeTestAppSelfManaged which only has the
        // {@link android.Manifest.permission#MANAGE_OWN_CALLS} permission
        TestServiceConnection control = setUpControl(CAR_MODE_CONTROL, CAR_SELF_MANAGED_COMPONENT);

        mCarModeIncallServiceControlSelfManaged =
                ICtsCarModeInCallServiceControl.Stub
                        .asInterface(control.getService());

        mCarModeIncallServiceControlSelfManaged.reset();

        // register a self-managed phone account
        mCarModeIncallServiceControlSelfManaged.registerPhoneAccount(
                TEST_SELF_MANAGED_PHONE_ACCOUNT);

        List<PhoneAccountHandle> pah =
                mCarModeIncallServiceControlSelfManaged.getOwnSelfManagedPhoneAccounts();

        // assert that we can get all the self-managed phone accounts registered to
        // CarModeTestAppSelfManaged
        assertEquals(1, pah.size());
        assertTrue(pah.contains(TEST_CAR_SELF_MANAGED_HANDLE));

        mCarModeIncallServiceControlSelfManaged.unregisterPhoneAccount(
                TEST_CAR_SELF_MANAGED_HANDLE);

        // unbind to CarModeTestAppSelfManaged
        mContext.unbindService(control);
    }

    public void testChangeCarModeApp() throws Exception {
        if (!mShouldTestTelecom) {
            return;
        }
        TestServiceConnection controlConn1 = setUpControl(CAR_MODE_CONTROL, CAR_DIALER_1);
        TestServiceConnection controlConn2 = setUpControl(CAR_MODE_CONTROL, CAR_DIALER_2);
        mCarModeIncallServiceControlOne = ICtsCarModeInCallServiceControl.Stub
                .asInterface(controlConn1.getService());
        mCarModeIncallServiceControlTwo = ICtsCarModeInCallServiceControl.Stub
                .asInterface(controlConn2.getService());
        mCarModeIncallServiceControlOne.reset();
        mCarModeIncallServiceControlTwo.reset();

        mUiAutomation.adoptShellPermissionIdentity(
                "android.permission.ENTER_CAR_MODE_PRIORITIZED",
                "android.permission.CONTROL_INCALL_EXPERIENCE");
        mCarModeIncallServiceControlOne.enableCarMode(999);

        SelfManagedConnection connection = placeAndVerifySelfManagedCall();
        assertTrue(mCarModeIncallServiceControlOne.checkBindStatus(true /* bindStatus */));
        mCarModeIncallServiceControlTwo.enableCarMode(1000);
        assertTrue(mCarModeIncallServiceControlOne.checkBindStatus(false /* bindStatus */));
        assertTrue(mCarModeIncallServiceControlTwo.checkBindStatus(true /* bindStatus */));

        mCarModeIncallServiceControlOne.disableCarMode();
        mCarModeIncallServiceControlTwo.disableCarMode();

        connection.disconnectAndDestroy();
        assertIsInCall(false);
        mUiAutomation.dropShellPermissionIdentity();
        mContext.unbindService(controlConn1);
        mContext.unbindService(controlConn2);
    }

    public void testExitCarMode() throws Exception {
        if (!mShouldTestTelecom) {
            return;
        }
        TestServiceConnection controlConn = setUpControl(CAR_MODE_CONTROL, CAR_DIALER_1);
        mCarModeIncallServiceControlOne = ICtsCarModeInCallServiceControl.Stub
                .asInterface(controlConn.getService());
        mCarModeIncallServiceControlOne.reset();

        mUiAutomation.adoptShellPermissionIdentity(
                "android.permission.ENTER_CAR_MODE_PRIORITIZED",
                "android.permission.CONTROL_INCALL_EXPERIENCE");
        mCarModeIncallServiceControlOne.enableCarMode(1000);

        SelfManagedConnection connection = placeAndVerifySelfManagedCall();
        assertTrue(mCarModeIncallServiceControlOne.checkBindStatus(true /* bindStatus */));
        mCarModeIncallServiceControlOne.disableCarMode();
        assertTrue(mCarModeIncallServiceControlOne.checkBindStatus(false /* bindStatus */));
        mUiAutomation.dropShellPermissionIdentity();

        connection.disconnectAndDestroy();
        assertIsInCall(false);
        mContext.unbindService(controlConn);
    }

    private TestServiceConnection setUpControl(String action, ComponentName componentName) {
        Intent bindIntent = new Intent(action);
        bindIntent.setComponent(componentName);

        TestServiceConnection serviceConnection = new TestServiceConnection();
        mContext.bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
        if (!serviceConnection.waitBind()) {
            fail("fail bind to service");
        }
        return serviceConnection;
    }

    private boolean setDefaultDialer(String packageName) {
        mUiAutomation.adoptShellPermissionIdentity();
        try {
            CompletableFuture<Boolean> future = new CompletableFuture<>();
            Consumer<Boolean> callback = successful -> {
                future.complete(successful);
            };

            mRoleManager.addRoleHolderAsUser(RoleManager.ROLE_DIALER, packageName, 0,
                    UserHandle.of(ActivityManager.getCurrentUser()), AsyncTask.THREAD_POOL_EXECUTOR,
                    callback);
            return future.get(TIMEOUT, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            e.printStackTrace();
            return false;
        } finally {
            mUiAutomation.dropShellPermissionIdentity();
        }
    }

    private String getDefaultDialer() {
        mUiAutomation.adoptShellPermissionIdentity();
        String result = mRoleManager.getRoleHolders(RoleManager.ROLE_DIALER).get(0);
        mUiAutomation.dropShellPermissionIdentity();
        return result;
    }

    private SelfManagedConnection placeAndVerifySelfManagedCall() {
        TestUtils.addIncomingCall(getInstrumentation(), mTelecomManager,
                TestUtils.TEST_SELF_MANAGED_HANDLE_4, TEST_ADDRESS);
        if (!CtsSelfManagedConnectionService.waitForBinding()) {
            fail("Could not bind to Self-Managed ConnectionService");
        }
        return TestUtils.waitForAndGetConnection(TEST_ADDRESS);
    }
}
