/*
 * Copyright 2017 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.internal.telephony.uicc;

import static com.android.internal.telephony.TelephonyTestUtils.waitForMs;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.isA;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.os.PersistableBundle;
import android.support.test.filters.SmallTest;
import android.telephony.CarrierConfigManager;

import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.cat.CatService;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;

import java.util.Map;

public class UiccProfileTest extends TelephonyTest {
    private UiccProfile mUiccProfile;

    public UiccProfileTest() {
        super();
    }

    private IccIoResult mIccIoResult;
    private static final int SCARY_SLEEP_MS = 200;

    private UiccProfileHandlerThread mTestHandlerThread;
    private Handler mHandler;
    private static final int UICCPROFILE_UPDATE_PROFILE_EVENT = 1;
    private static final int UICCPROFILE_UPDATE_APPLICATION_EVENT = 2;
    private static final int UICCPROFILE_CARRIER_PRIVILEDGE_LOADED_EVENT = 3;

    @Mock
    private CatService mCAT;
    @Mock
    private IccCardStatus mIccCardStatus;
    @Mock
    private Handler mMockedHandler;
    @Mock
    private UiccCard mUiccCard;

    private class UiccProfileHandlerThread extends HandlerThread {

        private UiccProfileHandlerThread(String name) {
            super(name);
        }

        @Override
        public void onLooperPrepared() {
            mUiccProfile = new UiccProfile(mContextFixture.getTestDouble(),
                                           mSimulatedCommands, mIccCardStatus, 0 /* phoneId */,
                                           mUiccCard);
            /* create a custom handler for the Handler Thread */
            mHandler = new Handler(mTestHandlerThread.getLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case UICCPROFILE_UPDATE_PROFILE_EVENT:
                            /* Upon handling this event, new CarrierPrivilegeRule
                            will be created with the looper of HandlerThread */
                            logd("Update UICC Profile");
                            mUiccProfile.update(mContextFixture.getTestDouble(),
                                    mSimulatedCommands, mIccCardStatus);
                            setReady(true);
                            break;
                        case UICCPROFILE_UPDATE_APPLICATION_EVENT:
                            logd("Update UICC Profile Applications");
                            mUiccProfile.update(mContextFixture.getTestDouble(),
                                    mSimulatedCommands, mIccCardStatus);
                            setReady(true);
                            break;
                        default:
                            logd("Unknown Event " + msg.what);
                    }
                }
            };
            /* wait for the carrier privilege rules to be loaded */
            waitForMs(50);
            setReady(true);
            logd("Create UiccProfile");
        }
    }

    private IccCardApplicationStatus composeUiccApplicationStatus(
            IccCardApplicationStatus.AppType appType,
            IccCardApplicationStatus.AppState appState, String aid) {
        IccCardApplicationStatus mIccCardAppStatus = new IccCardApplicationStatus();
        mIccCardAppStatus.aid = aid;
        mIccCardAppStatus.app_type = appType;
        mIccCardAppStatus.app_state = appState;
        mIccCardAppStatus.pin1 = mIccCardAppStatus.pin2 =
                IccCardStatus.PinState.PINSTATE_ENABLED_VERIFIED;
        return mIccCardAppStatus;
    }

    @Before
    public void setUp() throws Exception {
        super.setUp(getClass().getSimpleName());
         /* initially there are no application available, but the array should not be empty. */
        IccCardApplicationStatus umtsApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_USIM,
                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA2");
        mIccCardStatus.mApplications = new IccCardApplicationStatus[]{umtsApp};
        mIccCardStatus.mCdmaSubscriptionAppIndex =
                mIccCardStatus.mImsSubscriptionAppIndex =
                        mIccCardStatus.mGsmUmtsSubscriptionAppIndex = -1;
        mIccIoResult = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes("FF40"));
        mSimulatedCommands.setIccIoResultForApduLogicalChannel(mIccIoResult);
        /* starting the Handler Thread */
        mTestHandlerThread = new UiccProfileHandlerThread(TAG);
        mTestHandlerThread.start();

        waitUntilReady();

        /* wait for the carrier privilege rules to be loaded */
        waitForMs(50);

        replaceInstance(UiccProfile.class, "mCatService", mUiccProfile, mCAT);
    }

    @After
    public void tearDown() throws Exception {
        mTestHandlerThread.quit();
        super.tearDown();
    }

    @Test
    @SmallTest
    public void tesUiccProfileInfoSanity() {
        assertEquals(1, mUiccProfile.getNumApplications());
        assertNull(mUiccProfile.getUniversalPinState());
        assertNull(mUiccProfile.getOperatorBrandOverride());
        for (IccCardApplicationStatus.AppType mAppType :
                IccCardApplicationStatus.AppType.values()) {
            if (mAppType == IccCardApplicationStatus.AppType.APPTYPE_USIM) {
                assertTrue(mUiccProfile.isApplicationOnIcc(mAppType));
            } else {
                assertFalse(mUiccProfile.isApplicationOnIcc(mAppType));
            }

        }
    }

    @Test
    @SmallTest
    public void testParseWhitelistMapFromString() {
        String whitelist = "";
        Map<String, String> parsedMap = UiccProfile.parseToCertificateToPackageMap(whitelist);
        assertTrue(parsedMap.isEmpty());

        whitelist = "nokey;value;separation";
        parsedMap = UiccProfile.parseToCertificateToPackageMap(whitelist);
        assertTrue(parsedMap.isEmpty());

        whitelist = "KEY1:value1";
        parsedMap = UiccProfile.parseToCertificateToPackageMap(whitelist);
        assertEquals("value1", parsedMap.get("KEY1"));

        whitelist = "KEY1:value1;   KEY2:value2  ;KEY3:value3";
        parsedMap = UiccProfile.parseToCertificateToPackageMap(whitelist);
        assertEquals("value1", parsedMap.get("KEY1"));
        assertEquals("value2", parsedMap.get("KEY2"));
        assertEquals("value3", parsedMap.get("KEY3"));
    }

    @Test
    @SmallTest
    public void testUpdateUiccProfileApplication() {
        /* update app status and index */
        IccCardApplicationStatus cdmaApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_CSIM,
                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA0");
        IccCardApplicationStatus imsApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_ISIM,
                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA1");
        IccCardApplicationStatus umtsApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_USIM,
                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA2");
        mIccCardStatus.mApplications = new IccCardApplicationStatus[]{cdmaApp, imsApp, umtsApp};
        mIccCardStatus.mCdmaSubscriptionAppIndex = 0;
        mIccCardStatus.mImsSubscriptionAppIndex = 1;
        mIccCardStatus.mGsmUmtsSubscriptionAppIndex = 2;
        Message mProfileUpdate = mHandler.obtainMessage(UICCPROFILE_UPDATE_APPLICATION_EVENT);
        setReady(false);
        mProfileUpdate.sendToTarget();

        waitUntilReady();

        /* wait for the carrier privilege rules to be loaded */
        waitForMs(50);

        assertEquals(3, mUiccProfile.getNumApplications());
        assertTrue(mUiccProfile.isApplicationOnIcc(IccCardApplicationStatus.AppType.APPTYPE_CSIM));
        assertTrue(mUiccProfile.isApplicationOnIcc(IccCardApplicationStatus.AppType.APPTYPE_ISIM));
        assertTrue(mUiccProfile.isApplicationOnIcc(IccCardApplicationStatus.AppType.APPTYPE_USIM));
    }

    @Test
    @SmallTest
    public void testUpdateUiccProfile() {
        int mChannelId = 1;
        mIccCardStatus.mCardState = IccCardStatus.CardState.CARDSTATE_PRESENT;
        mSimulatedCommands.setOpenChannelId(mChannelId);
        Message mCardUpdate = mHandler.obtainMessage(UICCPROFILE_UPDATE_PROFILE_EVENT);
        setReady(false);
        mCardUpdate.sendToTarget();
        /* try to create a new CarrierPrivilege, loading state -> loaded state */
        /* wait till the async result and message delay */
        waitUntilReady();
        /* wait for the carrier privilege rules to be loaded */
        waitForMs(50);

        assertTrue(mUiccProfile.areCarrierPriviligeRulesLoaded());
        verify(mSimulatedCommandsVerifier, times(2)).iccOpenLogicalChannel(isA(String.class),
                anyInt(), isA(Message.class));
        verify(mSimulatedCommandsVerifier, times(2)).iccTransmitApduLogicalChannel(
                anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyString(),
                isA(Message.class)
        );
    }

    @Test
    @SmallTest
    public void testUpdateUiccProfilePinState() {
        mIccCardStatus.mUniversalPinState = IccCardStatus.PinState.PINSTATE_ENABLED_VERIFIED;
        mUiccProfile.update(mContextFixture.getTestDouble(), mSimulatedCommands, mIccCardStatus);
        assertEquals(IccCardStatus.PinState.PINSTATE_ENABLED_VERIFIED,
                mUiccProfile.getUniversalPinState());
    }

    @Test
    @SmallTest
    public void testCarrierPriviledgeLoadedListener() {
        mUiccProfile.registerForCarrierPrivilegeRulesLoaded(mMockedHandler,
                UICCPROFILE_CARRIER_PRIVILEDGE_LOADED_EVENT, null);
        ArgumentCaptor<Message> mCaptorMessage = ArgumentCaptor.forClass(Message.class);
        ArgumentCaptor<Long> mCaptorLong = ArgumentCaptor.forClass(Long.class);
        testUpdateUiccProfile();
        verify(mMockedHandler, atLeast(1)).sendMessageDelayed(mCaptorMessage.capture(),
                mCaptorLong.capture());
        assertEquals(UICCPROFILE_CARRIER_PRIVILEDGE_LOADED_EVENT, mCaptorMessage.getValue().what);
    }

    @Test
    @SmallTest
    public void testInitialCardState() {
        // after updateExternalState() is called, the state will not be UNKNOWN
        assertEquals(mUiccProfile.getState(), State.NOT_READY);
    }

    @Test
    @SmallTest
    public void testUpdateUiccProfileApplicationNotReady() {
        /* update app status and index */
        IccCardApplicationStatus cdmaApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_CSIM,
                IccCardApplicationStatus.AppState.APPSTATE_READY, "0xA0");
        IccCardApplicationStatus imsApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_ISIM,
                IccCardApplicationStatus.AppState.APPSTATE_READY, "0xA1");
        IccCardApplicationStatus umtsApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_USIM,
                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA2");
        mIccCardStatus.mApplications = new IccCardApplicationStatus[]{cdmaApp, imsApp, umtsApp};
        mIccCardStatus.mCdmaSubscriptionAppIndex = 0;
        mIccCardStatus.mImsSubscriptionAppIndex = 1;
        mIccCardStatus.mGsmUmtsSubscriptionAppIndex = 2;
        Message mProfileUpdate = mHandler.obtainMessage(UICCPROFILE_UPDATE_APPLICATION_EVENT);
        setReady(false);
        mProfileUpdate.sendToTarget();

        waitUntilReady();

        /* wait for the carrier privilege rules to be loaded */
        waitForMs(50);
        assertEquals(3, mUiccProfile.getNumApplications());

        mUiccProfile.mHandler.sendMessage(
                mUiccProfile.mHandler.obtainMessage(UiccProfile.EVENT_APP_READY));
        waitForMs(SCARY_SLEEP_MS);
        assertEquals(mUiccProfile.getState(), State.NOT_READY);
    }

    @Test
    @SmallTest
    public void testUpdateUiccProfileApplicationAllReady() {
        /* update app status and index */
        IccCardApplicationStatus cdmaApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_CSIM,
                IccCardApplicationStatus.AppState.APPSTATE_READY, "0xA0");
        IccCardApplicationStatus imsApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_ISIM,
                IccCardApplicationStatus.AppState.APPSTATE_READY, "0xA1");
        IccCardApplicationStatus umtsApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_USIM,
                IccCardApplicationStatus.AppState.APPSTATE_READY, "0xA2");
        mIccCardStatus.mApplications = new IccCardApplicationStatus[]{cdmaApp, imsApp, umtsApp};
        mIccCardStatus.mCdmaSubscriptionAppIndex = 0;
        mIccCardStatus.mImsSubscriptionAppIndex = 1;
        mIccCardStatus.mGsmUmtsSubscriptionAppIndex = 2;
        Message mProfileUpdate = mHandler.obtainMessage(UICCPROFILE_UPDATE_APPLICATION_EVENT);
        setReady(false);
        mProfileUpdate.sendToTarget();

        waitUntilReady();

        /* wait for the carrier privilege rules to be loaded */
        waitForMs(50);
        assertEquals(3, mUiccProfile.getNumApplications());

        mUiccProfile.mHandler.sendMessage(
                mUiccProfile.mHandler.obtainMessage(UiccProfile.EVENT_APP_READY));
        waitForMs(SCARY_SLEEP_MS);
        // state is loaded as all records are loaded right away as SimulatedCommands returns
        // response for them right away. Ideally applications and records should be mocked.
        assertEquals(State.LOADED, mUiccProfile.getState());
    }

    @Test
    @SmallTest
    public void testUpdateUiccProfileApplicationAllSupportedAppsReady() {
        /* update app status and index */
        IccCardApplicationStatus umtsApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_USIM,
                IccCardApplicationStatus.AppState.APPSTATE_READY, "0xA2");
        IccCardApplicationStatus imsApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_ISIM,
                IccCardApplicationStatus.AppState.APPSTATE_READY, "0xA1");
        IccCardApplicationStatus unknownApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_UNKNOWN,
                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "0xA2");
        mIccCardStatus.mApplications = new IccCardApplicationStatus[]{imsApp, umtsApp, unknownApp};
        mIccCardStatus.mCdmaSubscriptionAppIndex = -1;
        mIccCardStatus.mImsSubscriptionAppIndex = 0;
        mIccCardStatus.mGsmUmtsSubscriptionAppIndex = 1;
        Message mProfileUpdate = mHandler.obtainMessage(UICCPROFILE_UPDATE_APPLICATION_EVENT);
        setReady(false);
        mProfileUpdate.sendToTarget();

        waitUntilReady();

        /* wait for the carrier privilege rules to be loaded */
        waitForMs(50);
        assertEquals(3, mUiccProfile.getNumApplications());

        mUiccProfile.mHandler.sendMessage(
                mUiccProfile.mHandler.obtainMessage(UiccProfile.EVENT_APP_READY));
        waitForMs(SCARY_SLEEP_MS);
        // state is loaded as all records are loaded right away as SimulatedCommands returns
        // response for them right away. Ideally applications and records should be mocked.
        assertEquals(State.LOADED, mUiccProfile.getState());
    }

    @Test
    @SmallTest
    public void testUpdateUiccProfileApplicationNoApplication() {
        mIccCardStatus.mApplications = new IccCardApplicationStatus[]{};
        mIccCardStatus.mCdmaSubscriptionAppIndex = -1;
        mIccCardStatus.mImsSubscriptionAppIndex = -1;
        mIccCardStatus.mGsmUmtsSubscriptionAppIndex = -1;
        Message mProfileUpdate = mHandler.obtainMessage(UICCPROFILE_UPDATE_APPLICATION_EVENT);
        setReady(false);
        mProfileUpdate.sendToTarget();

        waitUntilReady();

        /* wait for the carrier privilege rules to be loaded */
        waitForMs(50);
        assertEquals(0, mUiccProfile.getNumApplications());

        mUiccProfile.mHandler.sendMessage(
                mUiccProfile.mHandler.obtainMessage(UiccProfile.EVENT_APP_READY));
        waitForMs(SCARY_SLEEP_MS);
        // state is loaded since there is no applications.
        assertEquals(State.NOT_READY, mUiccProfile.getState());
    }

    @Test
    @SmallTest
    public void testUpdateUiccProfileApplicationNoSupportApplication() {
        IccCardApplicationStatus unknownApp = composeUiccApplicationStatus(
                IccCardApplicationStatus.AppType.APPTYPE_UNKNOWN,
                IccCardApplicationStatus.AppState.APPSTATE_UNKNOWN, "");
        mIccCardStatus.mApplications = new IccCardApplicationStatus[]{unknownApp};
        mIccCardStatus.mCdmaSubscriptionAppIndex = -1;
        mIccCardStatus.mImsSubscriptionAppIndex = -1;
        mIccCardStatus.mGsmUmtsSubscriptionAppIndex = -1;
        Message mProfileUpdate = mHandler.obtainMessage(UICCPROFILE_UPDATE_APPLICATION_EVENT);
        setReady(false);
        mProfileUpdate.sendToTarget();

        waitUntilReady();

        /* wait for the carrier privilege rules to be loaded */
        waitForMs(50);
        assertEquals(1, mUiccProfile.getNumApplications());

        mUiccProfile.mHandler.sendMessage(
                mUiccProfile.mHandler.obtainMessage(UiccProfile.EVENT_APP_READY));
        waitForMs(SCARY_SLEEP_MS);
        // state is loaded since there is no applications.
        assertEquals(State.NOT_READY, mUiccProfile.getState());
    }

    @Test
    @SmallTest
    public void testUpdateExternalState() {
        // IO_ERROR
        doReturn(IccCardStatus.CardState.CARDSTATE_ERROR).when(mUiccCard).getCardState();
        mUiccProfile.updateExternalState();
        assertEquals(State.CARD_IO_ERROR, mUiccProfile.getState());

        // RESTRICTED
        doReturn(IccCardStatus.CardState.CARDSTATE_RESTRICTED).when(mUiccCard).getCardState();
        mUiccProfile.updateExternalState();
        assertEquals(State.CARD_RESTRICTED, mUiccProfile.getState());

        // CARD PRESENT; no mUiccApplication - state should be NOT_READY
        doReturn(IccCardStatus.CardState.CARDSTATE_PRESENT).when(mUiccCard).getCardState();
        mUiccProfile.updateExternalState();
        assertEquals(State.NOT_READY, mUiccProfile.getState());

        // set mUiccApplication
        testUpdateUiccProfileApplicationAllReady();
        mUiccProfile.updateExternalState();
        assertEquals(State.LOADED, mUiccProfile.getState());
    }

    @Test
    @SmallTest
    public void testCarrierConfigHandling() {
        testUpdateUiccProfileApplication();

        // Fake carrier name
        String fakeCarrierName = "fakeCarrierName";
        PersistableBundle carrierConfigBundle = mContextFixture.getCarrierConfigBundle();
        carrierConfigBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_NAME_OVERRIDE_BOOL, true);
        carrierConfigBundle.putString(CarrierConfigManager.KEY_CARRIER_NAME_STRING,
                fakeCarrierName);

        // broadcast CARRIER_CONFIG_CHANGED
        mContext.sendBroadcast(new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
        waitForMs(200);

        // verify that setSimOperatorNameForPhone() is called with fakeCarrierName
        ArgumentCaptor<String> stringArgumentCaptor = ArgumentCaptor.forClass(String.class);
        verify(mTelephonyManager, atLeast(1)).setSimOperatorNameForPhone(anyInt(),
                stringArgumentCaptor.capture());
        boolean carrierFound = false;
        for (String carrierName : stringArgumentCaptor.getAllValues()) {
            if (fakeCarrierName.equals(carrierName)) {
                carrierFound = true;
                break;
            }
        }
        assertTrue(carrierFound);
    }
}
