/*
 * 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 com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;

import com.android.internal.telecom.IConnectionService;
import com.android.internal.telecom.IInCallService;

import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import android.Manifest;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.app.StatusBarManager;
import android.app.role.RoleManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentProvider;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.location.Country;
import android.location.CountryDetector;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IInterface;
import android.os.UserHandle;
import android.os.UserManager;
import android.telecom.CallAudioState;
import android.telecom.ConnectionService;
import android.telecom.Log;
import android.telecom.InCallService;
import android.telecom.PhoneAccount;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.test.mock.MockContext;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

/**
 * Controls a test {@link Context} as would be provided by the Android framework to an
 * {@code Activity}, {@code Service} or other system-instantiated component.
 *
 * The {@link Context} created by this object is "hollow" but its {@code applicationContext}
 * property points to an application context implementing all the nontrivial functionality.
 */
public class ComponentContextFixture implements TestFixture<Context> {

    public class FakeApplicationContext extends MockContext {
        @Override
        public PackageManager getPackageManager() {
            return mPackageManager;
        }

        @Override
        public String getPackageName() {
            return "com.android.server.telecom.tests";
        }

        @Override
        public String getPackageResourcePath() {
            return "/tmp/i/dont/know";
        }

        @Override
        public Context getApplicationContext() {
            return mApplicationContextSpy;
        }

        @Override
        public File getFilesDir() {
            try {
                return File.createTempFile("temp", "temp").getParentFile();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public boolean bindServiceAsUser(
                Intent serviceIntent,
                ServiceConnection connection,
                int flags,
                UserHandle userHandle) {
            // TODO: Implement "as user" functionality
            return bindService(serviceIntent, connection, flags);
        }

        @Override
        public boolean bindService(
                Intent serviceIntent,
                ServiceConnection connection,
                int flags) {
            if (mServiceByServiceConnection.containsKey(connection)) {
                throw new RuntimeException("ServiceConnection already bound: " + connection);
            }
            IInterface service = mServiceByComponentName.get(serviceIntent.getComponent());
            if (service == null) {
                throw new RuntimeException("ServiceConnection not found: "
                        + serviceIntent.getComponent());
            }
            mServiceByServiceConnection.put(connection, service);
            connection.onServiceConnected(serviceIntent.getComponent(), service.asBinder());
            return true;
        }

        @Override
        public void unbindService(
                ServiceConnection connection) {
            IInterface service = mServiceByServiceConnection.remove(connection);
            if (service == null) {
                throw new RuntimeException("ServiceConnection not found: " + connection);
            }
            connection.onServiceDisconnected(mComponentNameByService.get(service));
        }

        @Override
        public Object getSystemService(String name) {
            switch (name) {
                case Context.AUDIO_SERVICE:
                    return mAudioManager;
                case Context.TELEPHONY_SERVICE:
                    return mTelephonyManager;
                case Context.APP_OPS_SERVICE:
                    return mAppOpsManager;
                case Context.NOTIFICATION_SERVICE:
                    return mNotificationManager;
                case Context.STATUS_BAR_SERVICE:
                    return mStatusBarManager;
                case Context.USER_SERVICE:
                    return mUserManager;
                case Context.TELEPHONY_SUBSCRIPTION_SERVICE:
                    return mSubscriptionManager;
                case Context.TELECOM_SERVICE:
                    return mTelecomManager;
                case Context.CARRIER_CONFIG_SERVICE:
                    return mCarrierConfigManager;
                case Context.COUNTRY_DETECTOR:
                    return mCountryDetector;
                case Context.ROLE_SERVICE:
                    return mRoleManager;
                default:
                    return null;
            }
        }

        @Override
        public String getSystemServiceName(Class<?> svcClass) {
            if (svcClass == UserManager.class) {
                return Context.USER_SERVICE;
            } else if (svcClass == RoleManager.class) {
                return Context.ROLE_SERVICE;
            } else if (svcClass == AudioManager.class) {
                return Context.AUDIO_SERVICE;
            }
            throw new UnsupportedOperationException();
        }

        @Override
        public int getUserId() {
            return 0;
        }

        @Override
        public Resources getResources() {
            return mResources;
        }

        @Override
        public String getOpPackageName() {
            return "com.android.server.telecom.tests";
        }

        @Override
        public ApplicationInfo getApplicationInfo() {
            return mTestApplicationInfo;
        }

        @Override
        public ContentResolver getContentResolver() {
            return new ContentResolver(mApplicationContextSpy) {
                @Override
                protected IContentProvider acquireProvider(Context c, String name) {
                    Log.i(this, "acquireProvider %s", name);
                    return getOrCreateProvider(name);
                }

                @Override
                public boolean releaseProvider(IContentProvider icp) {
                    return true;
                }

                @Override
                protected IContentProvider acquireUnstableProvider(Context c, String name) {
                    Log.i(this, "acquireUnstableProvider %s", name);
                    return getOrCreateProvider(name);
                }

                private IContentProvider getOrCreateProvider(String name) {
                    if (!mIContentProviderByUri.containsKey(name)) {
                        mIContentProviderByUri.put(name, mock(IContentProvider.class));
                    }
                    return mIContentProviderByUri.get(name);
                }

                @Override
                public boolean releaseUnstableProvider(IContentProvider icp) {
                    return false;
                }

                @Override
                public void unstableProviderDied(IContentProvider icp) {
                }
            };
        }

        @Override
        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
            // TODO -- this is called by WiredHeadsetManager!!!
            return null;
        }

        @Override
        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
                String broadcastPermission, Handler scheduler) {
            return null;
        }

        @Override
        public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle handle,
                IntentFilter filter, String broadcastPermission, Handler scheduler) {
            return null;
        }

        @Override
        public void sendBroadcast(Intent intent) {
            // TODO -- need to ensure this is captured
        }

        @Override
        public void sendBroadcast(Intent intent, String receiverPermission) {
            // TODO -- need to ensure this is captured
        }

        @Override
        public void sendBroadcastAsUser(Intent intent, UserHandle userHandle) {
            // TODO -- need to ensure this is captured
        }

        @Override
        public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
                String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
                int initialCode, String initialData, Bundle initialExtras) {
            // TODO -- need to ensure this is captured
        }

        @Override
        public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
                String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
                Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
        }

        @Override
        public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
                throws PackageManager.NameNotFoundException {
            return this;
        }

        @Override
        public int checkCallingOrSelfPermission(String permission) {
            return PackageManager.PERMISSION_GRANTED;
        }

        @Override
        public void enforceCallingOrSelfPermission(String permission, String message) {
            // Don't bother enforcing anything in mock.
        }

        @Override
        public void enforcePermission(
                String permission, int pid, int uid, String message) {
            // By default, don't enforce anything in mock.
        }

        @Override
        public void startActivityAsUser(Intent intent, UserHandle userHandle) {
            // For capturing
        }
    }

    public class FakeAudioManager extends AudioManager {

        private boolean mMute = false;
        private boolean mSpeakerphoneOn = false;
        private int mAudioStreamValue = 1;
        private int mMode = AudioManager.MODE_NORMAL;
        private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;

        public FakeAudioManager(Context context) {
            super(context);
        }

        @Override
        public void setMicrophoneMute(boolean value) {
            mMute = value;
        }

        @Override
        public boolean isMicrophoneMute() {
            return mMute;
        }

        @Override
        public void setSpeakerphoneOn(boolean value) {
            mSpeakerphoneOn = value;
        }

        @Override
        public boolean isSpeakerphoneOn() {
            return mSpeakerphoneOn;
        }

        @Override
        public void setMode(int mode) {
            mMode = mode;
        }

        @Override
        public int getMode() {
            return mMode;
        }

        @Override
        public void setRingerModeInternal(int ringerMode) {
            mRingerMode = ringerMode;
        }

        @Override
        public int getRingerModeInternal() {
            return mRingerMode;
        }

        @Override
        public void setStreamVolume(int streamTypeUnused, int index, int flagsUnused){
            mAudioStreamValue = index;
        }

        @Override
        public int getStreamVolume(int streamValueUnused) {
            return mAudioStreamValue;
        }
    }

    private final Multimap<String, ComponentName> mComponentNamesByAction =
            ArrayListMultimap.create();
    private final Map<ComponentName, IInterface> mServiceByComponentName = new HashMap<>();
    private final Map<ComponentName, ServiceInfo> mServiceInfoByComponentName = new HashMap<>();
    private final Map<IInterface, ComponentName> mComponentNameByService = new HashMap<>();
    private final Map<ServiceConnection, IInterface> mServiceByServiceConnection = new HashMap<>();

    private final Context mContext = new MockContext() {
        @Override
        public Context getApplicationContext() {
            return mApplicationContextSpy;
        }

        @Override
        public Resources getResources() {
            return mResources;
        }
    };

    // The application context is the most important object this class provides to the system
    // under test.
    private final Context mApplicationContext = new FakeApplicationContext();

    // We then create a spy on the application context allowing standard Mockito-style
    // when(...) logic to be used to add specific little responses where needed.

    private final Resources mResources = mock(Resources.class);
    private final Context mApplicationContextSpy = spy(mApplicationContext);
    private final PackageManager mPackageManager = mock(PackageManager.class);
    private final AudioManager mAudioManager = spy(new FakeAudioManager(mContext));
    private final TelephonyManager mTelephonyManager = mock(TelephonyManager.class);
    private final AppOpsManager mAppOpsManager = mock(AppOpsManager.class);
    private final NotificationManager mNotificationManager = mock(NotificationManager.class);
    private final UserManager mUserManager = mock(UserManager.class);
    private final StatusBarManager mStatusBarManager = mock(StatusBarManager.class);
    private final SubscriptionManager mSubscriptionManager = mock(SubscriptionManager.class);
    private final CarrierConfigManager mCarrierConfigManager = mock(CarrierConfigManager.class);
    private final CountryDetector mCountryDetector = mock(CountryDetector.class);
    private final Map<String, IContentProvider> mIContentProviderByUri = new HashMap<>();
    private final Configuration mResourceConfiguration = new Configuration();
    private final ApplicationInfo mTestApplicationInfo = new ApplicationInfo();
    private final RoleManager mRoleManager = mock(RoleManager.class);

    private TelecomManager mTelecomManager = null;

    public ComponentContextFixture() {
        MockitoAnnotations.initMocks(this);
        when(mResources.getConfiguration()).thenReturn(mResourceConfiguration);
        when(mResources.getString(anyInt())).thenReturn("");
        when(mResources.getStringArray(anyInt())).thenReturn(new String[0]);
        mResourceConfiguration.setLocale(Locale.TAIWAN);

        // TODO: Move into actual tests
        doReturn(false).when(mAudioManager).isWiredHeadsetOn();

        doAnswer(new Answer<List<ResolveInfo>>() {
            @Override
            public List<ResolveInfo> answer(InvocationOnMock invocation) throws Throwable {
                return doQueryIntentServices(
                        (Intent) invocation.getArguments()[0],
                        (Integer) invocation.getArguments()[1]);
            }
        }).when(mPackageManager).queryIntentServices((Intent) any(), anyInt());

        doAnswer(new Answer<List<ResolveInfo>>() {
            @Override
            public List<ResolveInfo> answer(InvocationOnMock invocation) throws Throwable {
                return doQueryIntentServices(
                        (Intent) invocation.getArguments()[0],
                        (Integer) invocation.getArguments()[1]);
            }
        }).when(mPackageManager).queryIntentServicesAsUser((Intent) any(), anyInt(), anyInt());

        // By default, tests use non-ui apps instead of 3rd party companion apps.
        when(mPackageManager.checkPermission(
                matches(Manifest.permission.CALL_COMPANION_APP), anyString()))
                .thenReturn(PackageManager.PERMISSION_DENIED);

        when(mTelephonyManager.getSubIdForPhoneAccount((PhoneAccount) any())).thenReturn(1);

        when(mTelephonyManager.getNetworkOperatorName()).thenReturn("label1");
        when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(
                TelephonyManager.MultiSimVariants.UNKNOWN);
        when(mResources.getBoolean(eq(R.bool.grant_location_permission_enabled))).thenReturn(false);
        doAnswer(new Answer<Void>(){
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                return null;
            }
        }).when(mAppOpsManager).checkPackage(anyInt(), anyString());

        when(mNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);

        when(mUserManager.getSerialNumberForUser(any(UserHandle.class))).thenReturn(-1L);

        doReturn(null).when(mApplicationContextSpy).registerReceiver(any(BroadcastReceiver.class),
                any(IntentFilter.class));
    }

    @Override
    public Context getTestDouble() {
        return mContext;
    }

    public void addConnectionService(
            ComponentName componentName,
            IConnectionService service)
            throws Exception {
        addService(ConnectionService.SERVICE_INTERFACE, componentName, service);
        ServiceInfo serviceInfo = new ServiceInfo();
        serviceInfo.permission = android.Manifest.permission.BIND_CONNECTION_SERVICE;
        serviceInfo.packageName = componentName.getPackageName();
        serviceInfo.name = componentName.getClassName();
        mServiceInfoByComponentName.put(componentName, serviceInfo);
    }

    public void addInCallService(
            ComponentName componentName,
            IInCallService service)
            throws Exception {
        addService(InCallService.SERVICE_INTERFACE, componentName, service);
        ServiceInfo serviceInfo = new ServiceInfo();
        serviceInfo.permission = android.Manifest.permission.BIND_INCALL_SERVICE;
        serviceInfo.packageName = componentName.getPackageName();
        serviceInfo.name = componentName.getClassName();
        mServiceInfoByComponentName.put(componentName, serviceInfo);
    }

    public void putResource(int id, final String value) {
        when(mResources.getText(eq(id))).thenReturn(value);
        when(mResources.getString(eq(id))).thenReturn(value);
        when(mResources.getString(eq(id), any())).thenAnswer(new Answer<String>() {
            @Override
            public String answer(InvocationOnMock invocation) {
                Object[] args = invocation.getArguments();
                return String.format(value, Arrays.copyOfRange(args, 1, args.length));
            }
        });
    }

    public void putFloatResource(int id, final float value) {
        when(mResources.getFloat(eq(id))).thenReturn(value);
    }

    public void putBooleanResource(int id, boolean value) {
        when(mResources.getBoolean(eq(id))).thenReturn(value);
    }

    public void setTelecomManager(TelecomManager telecomManager) {
        mTelecomManager = telecomManager;
    }

    public TelephonyManager getTelephonyManager() {
        return mTelephonyManager;
    }

    private void addService(String action, ComponentName name, IInterface service) {
        mComponentNamesByAction.put(action, name);
        mServiceByComponentName.put(name, service);
        mComponentNameByService.put(service, name);
    }

    private List<ResolveInfo> doQueryIntentServices(Intent intent, int flags) {
        List<ResolveInfo> result = new ArrayList<>();
        for (ComponentName componentName : mComponentNamesByAction.get(intent.getAction())) {
            ResolveInfo resolveInfo = new ResolveInfo();
            resolveInfo.serviceInfo = mServiceInfoByComponentName.get(componentName);
            resolveInfo.serviceInfo.metaData = new Bundle();
            resolveInfo.serviceInfo.metaData.putBoolean(
                    TelecomManager.METADATA_INCLUDE_EXTERNAL_CALLS, true);
            result.add(resolveInfo);
        }
        return result;
    }
}
