/*
 * Copyright (C) 2014 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.telecomm;

import android.Manifest;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.telecomm.AudioState;
import android.telecomm.CallProperties;
import android.telecomm.CallState;
import android.telecomm.InCallService;
import android.telecomm.ParcelableCall;
import android.telecomm.PhoneCapabilities;
import android.telecomm.PropertyPresentation;
import android.util.ArrayMap;

import com.android.internal.telecomm.IInCallService;
import com.google.common.collect.ImmutableCollection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Binds to {@link IInCallService} and provides the service to {@link CallsManager} through which it
 * can send updates to the in-call app. This class is created and owned by CallsManager and retains
 * a binding to the {@link IInCallService} (implemented by the in-call app).
 */
public final class InCallController extends CallsManagerListenerBase {
    /**
     * Used to bind to the in-call app and triggers the start of communication between
     * this class and in-call app.
     */
    private class InCallServiceConnection implements ServiceConnection {
        /** {@inheritDoc} */
        @Override public void onServiceConnected(ComponentName name, IBinder service) {
            onConnected(name, service);
        }

        /** {@inheritDoc} */
        @Override public void onServiceDisconnected(ComponentName name) {
            onDisconnected(name);
        }
    }

    private final Call.Listener mCallListener = new Call.ListenerBase() {
        @Override
        public void onCallCapabilitiesChanged(Call call) {
            updateCall(call);
        }

        @Override
        public void onCannedSmsResponsesLoaded(Call call) {
            updateCall(call);
        }

        @Override
        public void onVideoCallProviderChanged(Call call) {
            updateCall(call);
        }

        @Override
        public void onStatusHintsChanged(Call call) {
            updateCall(call);
        }

        @Override
        public void onHandleChanged(Call call) {
            updateCall(call);
        }

        @Override
        public void onCallerDisplayNameChanged(Call call) {
            updateCall(call);
        }

        @Override
        public void onVideoStateChanged(Call call) {
            updateCall(call);
        }

        @Override
        public void onStartActivityFromInCall(Call call, PendingIntent intent) {
            if (!mInCallServices.isEmpty()) {
                Log.i(this, "Calling startActivity, intent: %s", intent);
                for (IInCallService inCallService : mInCallServices.values()) {
                    try {
                        inCallService.startActivity(mCallIdMapper.getCallId(call), intent);
                    } catch (RemoteException ignored) {
                    }
                }
            }
        }

        @Override
        public void onTargetPhoneAccountChanged(Call call) {
            updateCall(call);
        }

        @Override
        public void onConferenceableCallsChanged(Call call) {
            updateCall(call);
        }
    };

    /**
     * Maintains a binding connection to the in-call app(s).
     * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
     * load factor before resizing, 1 means we only expect a single thread to
     * access the map so make only a single shard
     */
    private final Map<ComponentName, InCallServiceConnection> mServiceConnections =
            new ConcurrentHashMap<ComponentName, InCallServiceConnection>(8, 0.9f, 1);

    /** The in-call app implementations, see {@link IInCallService}. */
    private final Map<ComponentName, IInCallService> mInCallServices = new ArrayMap<>();

    private final CallIdMapper mCallIdMapper = new CallIdMapper("InCall");

    /** The {@link ComponentName} of the default InCall UI. */
    private ComponentName mInCallComponentName;

    public InCallController() {
        Context context = TelecommApp.getInstance();
        Resources resources = context.getResources();

        mInCallComponentName = new ComponentName(
                resources.getString(R.string.ui_default_package),
                resources.getString(R.string.incall_default_class));
    }

    @Override
    public void onCallAdded(Call call) {
        if (mInCallServices.isEmpty()) {
            bind();
        } else {
            Log.i(this, "Adding call: %s", call);
            // Track the call if we don't already know about it.
            addCall(call);

            for (Map.Entry<ComponentName, IInCallService> entry : mInCallServices.entrySet()) {
                ComponentName componentName = entry.getKey();
                IInCallService inCallService = entry.getValue();

                ParcelableCall parcelableCall = toParcelableCall(call,
                        componentName.equals(mInCallComponentName) /* includeVideoProvider */);
                try {
                    inCallService.addCall(parcelableCall);
                } catch (RemoteException ignored) {
                }
            }
        }
    }

    @Override
    public void onCallRemoved(Call call) {
        if (CallsManager.getInstance().getCalls().isEmpty()) {
            // TODO: Wait for all messages to be delivered to the service before unbinding.
            unbind();
        }
        call.removeListener(mCallListener);
        mCallIdMapper.removeCall(call);
    }

    @Override
    public void onCallStateChanged(Call call, int oldState, int newState) {
        updateCall(call);
    }

    @Override
    public void onConnectionServiceChanged(
            Call call,
            ConnectionServiceWrapper oldService,
            ConnectionServiceWrapper newService) {
        updateCall(call);
    }

    @Override
    public void onAudioStateChanged(AudioState oldAudioState, AudioState newAudioState) {
        if (!mInCallServices.isEmpty()) {
            Log.i(this, "Calling onAudioStateChanged, audioState: %s -> %s", oldAudioState,
                    newAudioState);
            for (IInCallService inCallService : mInCallServices.values()) {
                try {
                    inCallService.onAudioStateChanged(newAudioState);
                } catch (RemoteException ignored) {
                }
            }
        }
    }

    void onPostDialWait(Call call, String remaining) {
        if (!mInCallServices.isEmpty()) {
            Log.i(this, "Calling onPostDialWait, remaining = %s", remaining);
            for (IInCallService inCallService : mInCallServices.values()) {
                try {
                    inCallService.setPostDialWait(mCallIdMapper.getCallId(call), remaining);
                } catch (RemoteException ignored) {
                }
            }
        }
    }

    @Override
    public void onIsConferencedChanged(Call call) {
        Log.d(this, "onIsConferencedChanged %s", call);
        updateCall(call);
    }

    void bringToForeground(boolean showDialpad) {
        if (!mInCallServices.isEmpty()) {
            for (IInCallService inCallService : mInCallServices.values()) {
                try {
                    inCallService.bringToForeground(showDialpad);
                } catch (RemoteException ignored) {
                }
            }
        } else {
            Log.w(this, "Asking to bring unbound in-call UI to foreground.");
        }
    }

    /**
     * Unbinds an existing bound connection to the in-call app.
     */
    private void unbind() {
        ThreadUtil.checkOnMainThread();
        if (!mInCallServices.isEmpty()) {
            Log.i(this, "Unbinding from InCallService");
            for (InCallServiceConnection connection : mServiceConnections.values()) {
                TelecommApp.getInstance().unbindService(connection);
            }
            mInCallServices.clear();
        }
    }

    /**
     * Binds to the in-call app if not already connected by binding directly to the saved
     * component name of the {@link IInCallService} implementation.
     */
    private void bind() {
        ThreadUtil.checkOnMainThread();
        if (mInCallServices.isEmpty()) {
            mServiceConnections.clear();
            Context context = TelecommApp.getInstance();
            PackageManager packageManager = TelecommApp.getInstance().getPackageManager();
            Intent intent = new Intent(InCallService.SERVICE_INTERFACE);

            for (ResolveInfo entry : packageManager.queryIntentServices(intent, 0)) {
                ServiceInfo serviceInfo = entry.serviceInfo;
                if (serviceInfo != null) {
                    boolean hasServiceBindPermission = serviceInfo.permission != null &&
                            serviceInfo.permission.equals(
                                    Manifest.permission.BIND_INCALL_SERVICE);
                    boolean hasControlInCallPermission = packageManager.checkPermission(
                            Manifest.permission.CONTROL_INCALL_EXPERIENCE,
                            serviceInfo.packageName) == PackageManager.PERMISSION_GRANTED;

                    if (!hasServiceBindPermission) {
                        Log.w(this, "InCallService does not have BIND_INCALL_SERVICE permission: " +
                                serviceInfo.packageName);
                        continue;
                    }

                    if (!hasControlInCallPermission) {
                        Log.w(this,
                                "InCall UI does not have CONTROL_INCALL_EXPERIENCE permission: " +
                                        serviceInfo.packageName);
                        continue;
                    }

                    Log.i(this, "Attempting to bind to InCall " + serviceInfo.packageName);
                    InCallServiceConnection inCallServiceConnection = new InCallServiceConnection();
                    ComponentName componentName = new ComponentName(serviceInfo.packageName,
                            serviceInfo.name);
                    intent.setComponent(componentName);

                    if (context.bindServiceAsUser(intent, inCallServiceConnection,
                            Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
                        mServiceConnections.put(componentName, inCallServiceConnection);
                    }
                }
            }
        }
    }

    /**
     * Persists the {@link IInCallService} instance and starts the communication between
     * this class and in-call app by sending the first update to in-call app. This method is
     * called after a successful binding connection is established.
     *
     * @param componentName The service {@link ComponentName}.
     * @param service The {@link IInCallService} implementation.
     */
    private void onConnected(ComponentName componentName, IBinder service) {
        ThreadUtil.checkOnMainThread();

        IInCallService inCallService = IInCallService.Stub.asInterface(service);

        try {
            inCallService.setInCallAdapter(new InCallAdapter(CallsManager.getInstance(),
                    mCallIdMapper));
            mInCallServices.put(componentName, inCallService);
        } catch (RemoteException e) {
            Log.e(this, e, "Failed to set the in-call adapter.");
            return;
        }

        // Upon successful connection, send the state of the world to the service.
        ImmutableCollection<Call> calls = CallsManager.getInstance().getCalls();
        if (!calls.isEmpty()) {
            for (Call call : calls) {
                try {
                    // Track the call if we don't already know about it.
                    addCall(call);

                    inCallService.addCall(toParcelableCall(call,
                            componentName.equals(mInCallComponentName) /* includeVideoProvider */));
                } catch (RemoteException ignored) {
                }
            }
            onAudioStateChanged(null, CallsManager.getInstance().getAudioState());
        } else {
            unbind();
        }
    }

    /**
     * Cleans up an instance of in-call app after the service has been unbound.
     *
     * @param disconnectedComponent The {@link ComponentName} of the service which disconnected.
     */
    private void onDisconnected(ComponentName disconnectedComponent) {
        ThreadUtil.checkOnMainThread();
        if (mInCallServices.containsKey(disconnectedComponent)) {
            mInCallServices.remove(disconnectedComponent);
        }

        // If the default in-call UI has disconnected, disconnect all calls and un-bind all other
        // InCallService implementations.
        if (disconnectedComponent.equals(mInCallComponentName)) {
            Log.i(this, "In-call UI %s disconnected.", disconnectedComponent);
            CallsManager.getInstance().disconnectAllCalls();

            // Iterate through the in-call services, removing them as they are un-bound.
            Iterator<Map.Entry<ComponentName, IInCallService>> it =
                    mInCallServices.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<ComponentName, IInCallService> entry = it.next();
                ComponentName componentName = entry.getKey();

                InCallServiceConnection connection =  mServiceConnections.remove(componentName);
                it.remove();
                if (connection == null) {
                    continue;
                }

                Log.i(this, "Unbinding other InCallService %s", componentName);
                TelecommApp.getInstance().unbindService(connection);
            }
        }
    }

    /**
     * Informs all {@link InCallService} instances of the updated call information.  Changes to the
     * video provider are only communicated to the default in-call UI.
     *
     * @param call The {@link Call}.
     */
    private void updateCall(Call call) {
        if (!mInCallServices.isEmpty()) {
            for (Map.Entry<ComponentName, IInCallService> entry : mInCallServices.entrySet()) {
                ComponentName componentName = entry.getKey();
                IInCallService inCallService = entry.getValue();
                ParcelableCall parcelableCall = toParcelableCall(call,
                        componentName.equals(mInCallComponentName) /* includeVideoProvider */);

                Log.v(this, "updateCall %s ==> %s", call, parcelableCall);
                try {
                    inCallService.updateCall(parcelableCall);
                } catch (RemoteException ignored) {
                }
            }
        }
    }

    /**
     * Parcels all information for a {@link Call} into a new {@link ParcelableCall} instance.
     *
     * @param call The {@link Call} to parcel.
     * @param includeVideoProvider When {@code true}, the {@link IVideoProvider} is included in the
     *      parcelled call.  When {@code false}, the {@link IVideoProvider} is not included.
     * @return The {@link ParcelableCall} containing all call information from the {@link Call}.
     */
    private ParcelableCall toParcelableCall(Call call, boolean includeVideoProvider) {
        String callId = mCallIdMapper.getCallId(call);

        int capabilities = call.getCallCapabilities();
        if (CallsManager.getInstance().isAddCallCapable(call)) {
            capabilities |= PhoneCapabilities.ADD_CALL;
        }
        if (!call.isEmergencyCall()) {
            capabilities |= PhoneCapabilities.MUTE;
        }

        int properties = call.isConference() ? CallProperties.CONFERENCE : 0;

        int state = call.getState();
        if (state == CallState.ABORTED) {
            state = CallState.DISCONNECTED;
        }

        String parentCallId = null;
        Call parentCall = call.getParentCall();
        if (parentCall != null) {
            parentCallId = mCallIdMapper.getCallId(parentCall);
        }

        long connectTimeMillis = call.getConnectTimeMillis();
        List<Call> childCalls = call.getChildCalls();
        List<String> childCallIds = new ArrayList<>();
        if (!childCalls.isEmpty()) {
            connectTimeMillis = Long.MAX_VALUE;
            for (Call child : childCalls) {
                connectTimeMillis = Math.min(child.getConnectTimeMillis(), connectTimeMillis);
                childCallIds.add(mCallIdMapper.getCallId(child));
            }
        }

        if (call.isRespondViaSmsCapable()) {
            capabilities |= PhoneCapabilities.RESPOND_VIA_TEXT;
        }

        Uri handle = call.getHandlePresentation() == PropertyPresentation.ALLOWED ?
                call.getHandle() : null;
        String callerDisplayName = call.getCallerDisplayNamePresentation() ==
                PropertyPresentation.ALLOWED ?  call.getCallerDisplayName() : null;

        List<Call> conferenceableCalls = call.getConferenceableCalls();
        List<String> conferenceableCallIds = new ArrayList<String>(conferenceableCalls.size());
        for (Call otherCall : conferenceableCalls) {
            String otherId = mCallIdMapper.getCallId(otherCall);
            if (otherId != null) {
                conferenceableCallIds.add(otherId);
            }
        }

        return new ParcelableCall(
                callId,
                state,
                call.getDisconnectCause(),
                call.getDisconnectMessage(),
                call.getCannedSmsResponses(),
                capabilities,
                properties,
                connectTimeMillis,
                handle,
                call.getHandlePresentation(),
                callerDisplayName,
                call.getCallerDisplayNamePresentation(),
                call.getGatewayInfo(),
                call.getTargetPhoneAccount(),
                includeVideoProvider ? call.getVideoProvider() : null,
                parentCallId,
                childCallIds,
                call.getStatusHints(),
                call.getVideoState(),
                conferenceableCallIds,
                call.getExtras());
    }

    /**
     * Adds the call to the list of calls tracked by the {@link InCallController}.
     * @param call The call to add.
     */
    private void addCall(Call call) {
        if (mCallIdMapper.getCallId(call) == null) {
            mCallIdMapper.addCall(call);
            call.addListener(mCallListener);
        }
    }
}
