/*
 * 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 android.telecom.cts;

import static android.telecom.cts.TestUtils.*;

import android.os.Bundle;
import android.telecom.Call;
import android.telecom.Conference;
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
import android.telecom.DisconnectCause;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.StatusHints;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;

import java.util.ArrayList;

/**
 * Extended suite of tests that use {@link CtsConnectionService} and {@link MockInCallService} to
 * verify the functionality of Call Conferencing.
 */
public class ConferenceTest extends BaseTelecomTestWithMockServices {

    public static final int CONF_CAPABILITIES = Connection.CAPABILITY_SEPARATE_FROM_CONFERENCE |
            Connection.CAPABILITY_DISCONNECT_FROM_CONFERENCE | Connection.CAPABILITY_HOLD |
            Connection.CAPABILITY_MERGE_CONFERENCE | Connection.CAPABILITY_SWAP_CONFERENCE;

    private Call mCall1, mCall2;
    private MockConnection mConnection1, mConnection2;
    MockInCallService mInCallService;
    Conference mConferenceObject;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mContext = getInstrumentation().getContext();
        if (mShouldTestTelecom) {
            addOutgoingCalls();
            addConferenceCall(mCall1, mCall2);
            // Use vanilla conference object so that the CTS coverage tool detects the useage.
            mConferenceObject = verifyConferenceForOutgoingCall();
            verifyConferenceObject(mConferenceObject, mConnection1, mConnection2);
        }
    }

    public void testConferenceCreate() {
        if (!mShouldTestTelecom) {
            return;
        }
        final Call conf = mInCallService.getLastConferenceCall();
        assertCallState(conf, Call.STATE_ACTIVE);

        if (mCall1.getParent() != conf || mCall2.getParent() != conf) {
            fail("The 2 participating calls should contain the conference call as its parent");
        }
        if (!(conf.getChildren().contains(mCall1) && conf.getChildren().contains(mCall2))) {
            fail("The conference call should contain the 2 participating calls as its children");
        }
        assertTrue(mConferenceObject.getConnections().contains(mConnection1));

        assertConnectionState(mConferenceObject.getConnections().get(0), Connection.STATE_ACTIVE);
        assertConnectionState(mConferenceObject.getConnections().get(1), Connection.STATE_ACTIVE);
        assertConferenceState(mConferenceObject, Connection.STATE_ACTIVE);
    }

    public void testConferenceSplit() {
        if (!mShouldTestTelecom) {
            return;
        }
        final Call conf = mInCallService.getLastConferenceCall();
        assertCallState(conf, Call.STATE_ACTIVE);

        if (!(mCall1.getParent() == conf) && (conf.getChildren().contains(mCall1))) {
            fail("Call 1 not conferenced");
        }
        assertTrue(mConferenceObject.getConnections().contains(mConnection1));

        splitFromConferenceCall(mCall1);

        if ((mCall1.getParent() == conf) || (conf.getChildren().contains(mCall1))) {
            fail("Call 1 should not be still conferenced");
        }
        assertFalse(mConferenceObject.getConnections().contains(mConnection1));
    }

    public void testConferenceHoldAndUnhold() {
        if (!mShouldTestTelecom) {
            return;
        }
        final Call conf = mInCallService.getLastConferenceCall();
        assertCallState(conf, Call.STATE_ACTIVE);

        conf.hold();
        assertCallState(conf, Call.STATE_HOLDING);
        assertCallState(mCall1, Call.STATE_HOLDING);
        assertCallState(mCall2, Call.STATE_HOLDING);

        conf.unhold();
        assertCallState(conf, Call.STATE_ACTIVE);
        assertCallState(mCall1, Call.STATE_ACTIVE);
        assertCallState(mCall2, Call.STATE_ACTIVE);
    }

    public void testConferenceMergeAndSwap() {
        if (!mShouldTestTelecom) {
            return;
        }
        final Call conf = mInCallService.getLastConferenceCall();
        assertCallState(conf, Call.STATE_ACTIVE);

        conf.mergeConference();
        assertCallDisplayName(mCall1, TestUtils.MERGE_CALLER_NAME);
        assertCallDisplayName(mCall2, TestUtils.MERGE_CALLER_NAME);
        assertConnectionCallDisplayName(mConferenceObject.getConnections().get(0),
                TestUtils.MERGE_CALLER_NAME);
        assertConnectionCallDisplayName(mConferenceObject.getConnections().get(1),
                TestUtils.MERGE_CALLER_NAME);

        conf.swapConference();
        assertCallDisplayName(mCall1, TestUtils.SWAP_CALLER_NAME);
        assertCallDisplayName(mCall2, TestUtils.SWAP_CALLER_NAME);
        assertConnectionCallDisplayName(mConferenceObject.getConnections().get(0),
                TestUtils.SWAP_CALLER_NAME);
        assertConnectionCallDisplayName(mConferenceObject.getConnections().get(1),
                TestUtils.SWAP_CALLER_NAME);

    }

    public void testConferenceSetters() {
        if (!mShouldTestTelecom) {
            return;
        }
        final Call conf = mInCallService.getLastConferenceCall();
        assertCallState(conf, Call.STATE_ACTIVE);

        placeAndVerifyCall();
        MockConnection newConnection = verifyConnectionForOutgoingCall(2);
        final Call newCall = mInCallService.getLastCall();

        ArrayList<Connection> connectionList = new ArrayList<>();
        connectionList.add(newConnection);
        ArrayList<Call> callList = new ArrayList<>();
        callList.add(newCall);

        assertFalse(conf.getDetails().can(Call.Details.CAPABILITY_MUTE));
        int capabilities = mConferenceObject.getConnectionCapabilities() |
                Connection.CAPABILITY_MUTE;
        mConferenceObject.setConnectionCapabilities(capabilities);
        assertCallCapability(conf, Call.Details.CAPABILITY_MUTE);

        assertFalse(conf.getConferenceableCalls().contains(newCall));
        mConferenceObject.setConferenceableConnections(connectionList);
        assertCallConferenceableList(conf, callList);

        mConferenceObject.setConnectionTime(0);

        Bundle extras = new Bundle();
        extras.putString(TelecomManager.EXTRA_CALL_DISCONNECT_MESSAGE, "Test");
        assertNull(conf.getDetails().getExtras());
        mConferenceObject.setExtras(extras);
        assertCallExtras(conf, TelecomManager.EXTRA_CALL_DISCONNECT_MESSAGE, "Test");

        StatusHints hints = new StatusHints("Test", null, null);
        assertNull(conf.getDetails().getStatusHints());
        mConferenceObject.setStatusHints(hints);
        assertCallStatusHints(conf, hints);

        assertFalse(conf.getChildren().contains(newCall));
        mConferenceObject.addConnection(newConnection);
        assertCallChildrenContains(conf, newCall, true);

        assertTrue(conf.getChildren().contains(newCall));
        mConferenceObject.removeConnection(newConnection);
        assertCallChildrenContains(conf, newCall, false);

        assertVideoState(conf, VideoProfile.STATE_AUDIO_ONLY);
        final MockVideoProvider mockVideoProvider = mConnection1.getMockVideoProvider();
        mConferenceObject.setVideoProvider(mConnection1, mockVideoProvider);
        mConferenceObject.setVideoState(mConnection1, VideoProfile.STATE_BIDIRECTIONAL);
        assertVideoState(conf, VideoProfile.STATE_BIDIRECTIONAL);

        // Dialing state is unsupported for conference calls. so, the state remains active.
        mConferenceObject.setDialing();
        assertCallState(conf, Call.STATE_ACTIVE);

        mConferenceObject.setOnHold();
        assertCallState(conf, Call.STATE_HOLDING);

        mConferenceObject.setActive();
        assertCallState(conf, Call.STATE_ACTIVE);

        mConferenceObject.setDisconnected(new DisconnectCause(DisconnectCause.LOCAL));
        assertCallState(conf, Call.STATE_DISCONNECTED);

        // Destroy state is unsupported for conference calls. so, the state remains active.
        mConferenceObject.destroy();
        assertCallState(conf, Call.STATE_DISCONNECTED);
    }

    public void testConferenceAddAndRemoveConnection() {
        if (!mShouldTestTelecom) {
            return;
        }
        final Call conf = mInCallService.getLastConferenceCall();
        assertCallState(conf, Call.STATE_ACTIVE);

        placeAndVerifyCall();
        MockConnection newConnection = verifyConnectionForOutgoingCall(2);
        final Call newCall = mInCallService.getLastCall();

        ArrayList<Connection> connectionList = new ArrayList<>();
        connectionList.add(newConnection);
        ArrayList<Call> callList = new ArrayList<>();
        callList.add(newCall);

        assertFalse(conf.getChildren().contains(newCall));
        mConferenceObject.addConnection(newConnection);
        assertCallChildrenContains(conf, newCall, true);

        assertTrue(conf.getChildren().contains(newCall));
        mConferenceObject.removeConnection(newConnection);
        assertCallChildrenContains(conf, newCall, false);
    }

    public void testConferenceDTMFTone() {
        if (!mShouldTestTelecom) {
            return;
        }
        final Call conf = mInCallService.getLastConferenceCall();
        assertCallState(conf, Call.STATE_ACTIVE);

        assertTrue(((MockConference)mConferenceObject).getDtmfString().isEmpty());
        conf.playDtmfTone('1');
        assertDtmfString((MockConference)mConferenceObject, "1");
        conf.stopDtmfTone();
        assertDtmfString((MockConference)mConferenceObject, "1.");
        conf.playDtmfTone('3');
        assertDtmfString((MockConference)mConferenceObject, "1.3");
        conf.stopDtmfTone();
        assertDtmfString((MockConference)mConferenceObject, "1.3.");
    }

    private void verifyConferenceObject(Conference mConferenceObject, MockConnection connection1,
            MockConnection connection2) {
        assertNull(mConferenceObject.getCallAudioState());
        assertTrue(mConferenceObject.getConferenceableConnections().isEmpty());
        assertEquals(connection1.getConnectionCapabilities(),
                mConferenceObject.getConnectionCapabilities());
        assertEquals(connection1.getState(), mConferenceObject.getState());
        assertEquals(connection2.getState(), mConferenceObject.getState());
        assertTrue(mConferenceObject.getConnections().contains(connection1));
        assertTrue(mConferenceObject.getConnections().contains(connection2));
        assertEquals(connection1.getDisconnectCause(), mConferenceObject.getDisconnectCause());
        assertEquals(connection1.getExtras(), mConferenceObject.getExtras());
        assertEquals(connection1.getPhoneAccountHandle(), mConferenceObject.getPhoneAccountHandle());
        assertEquals(connection1.getStatusHints(), mConferenceObject.getStatusHints());
        assertEquals(VideoProfile.STATE_AUDIO_ONLY, mConferenceObject.getVideoState());
        assertNull(mConferenceObject.getVideoProvider());
    }

    private void addOutgoingCalls() {
        try {
            PhoneAccount account = setupConnectionService(
                    new MockConnectionService() {
                        @Override
                        public Connection onCreateOutgoingConnection(
                                PhoneAccountHandle connectionManagerPhoneAccount,
                                ConnectionRequest request) {
                            Connection connection = super.onCreateOutgoingConnection(
                                    connectionManagerPhoneAccount,
                                    request);
                            // Modify the connection object created with local values.
                            int capabilities = connection.getConnectionCapabilities();
                            connection.setConnectionCapabilities(capabilities | CONF_CAPABILITIES);
                            return connection;
                        }
                    }, FLAG_REGISTER | FLAG_ENABLE);
        } catch(Exception e) {
            fail("Error in setting up the connection services");
        }

        placeAndVerifyCall();
        mConnection1 = verifyConnectionForOutgoingCall(0);
        mInCallService = mInCallCallbacks.getService();
        mCall1 = mInCallService.getLastCall();
        assertCallState(mCall1, Call.STATE_DIALING);
        mConnection1.setActive();
        assertCallState(mCall1, Call.STATE_ACTIVE);

        placeAndVerifyCall();
        mConnection2 = verifyConnectionForOutgoingCall(1);
        mCall2 = mInCallService.getLastCall();
        assertCallState(mCall2, Call.STATE_DIALING);
        mConnection2.setActive();
        assertCallState(mCall2, Call.STATE_ACTIVE);

        setAndVerifyConferenceablesForOutgoingConnection(0);
        setAndVerifyConferenceablesForOutgoingConnection(1);
    }

    private void assertCallCapability(final Call call, final int capability) {
        waitUntilConditionIsTrueOrTimeout(
                new Condition() {
                    @Override
                    public Object expected() {
                        return true;
                    }

                    @Override
                    public Object actual() {
                        return call.getDetails().can(capability);
                    }
                },
                WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
                "Call should have capability " + capability
        );
    }

    private void assertCallConnectTime(final Call call, final int connectTime) {
        waitUntilConditionIsTrueOrTimeout(
                new Condition() {
                    @Override
                    public Object expected() {
                        return connectTime;
                    }

                    @Override
                    public Object actual() {
                        return call.getDetails().getConnectTimeMillis();
                    }
                },
                WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
                "Call should have connect time " + connectTime
        );
    }

    private void assertCallExtras(final Call call, final String key, final String value) {
        waitUntilConditionIsTrueOrTimeout(
                new Condition() {
                    @Override
                    public Object expected() {
                        return value;
                    }

                    @Override
                    public Object actual() {
                        return call.getDetails().getExtras() != null ?
                            call.getDetails().getExtras().getString(key) : null;
                    }
                },
                WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
                "Call should have extra " + key + "=" + value
        );
    }

    private void assertCallStatusHints(final Call call, final StatusHints hints) {
        waitUntilConditionIsTrueOrTimeout(
                new Condition() {
                    @Override
                    public Object expected() {
                        return hints;
                    }

                    @Override
                    public Object actual() {
                        return call.getDetails().getStatusHints();
                    }
                },
                WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
                "Call should have status hints " + hints
        );
    }

    private void assertCallChildrenContains(final Call call, final Call childrenCall,
                                            final boolean expected) {
        waitUntilConditionIsTrueOrTimeout(
                new Condition() {
                    @Override
                    public Object expected() {
                        return expected;
                    }

                    @Override
                    public Object actual() {
                        return call.getChildren().contains(childrenCall);
                    }
                },
                WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
                expected == true ? "Call should have child call " + childrenCall :
                        "Call should not have child call " + childrenCall
        );
    }

    private void assertVideoState(final Call call, final int videoState) {
        waitUntilConditionIsTrueOrTimeout(
                new Condition() {
                    @Override
                    public Object expected() {
                        return videoState;
                    }

                    @Override
                    public Object actual() {
                        return call.getDetails().getVideoState();
                    }
                },
                TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS,
                "Call should be in videoState " + videoState
        );
    }
}
