/*
 * Copyright (C) 2019 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.car.dialer.telecom;

import android.content.Context;
import android.content.Intent;
import android.telecom.Call;

import androidx.annotation.MainThread;
import androidx.preference.PreferenceManager;

import com.android.car.dialer.Constants;
import com.android.car.dialer.R;
import com.android.car.dialer.log.L;
import com.android.car.dialer.notification.InCallNotificationController;
import com.android.car.dialer.ui.activecall.InCallActivity;
import com.android.car.dialer.ui.activecall.InCallViewModel;

import java.util.ArrayList;

/**
 * Routes a call to different path depending on its state. If there is any {@link
 * InCallServiceImpl.ActiveCallListChangedCallback} that already handles the call, i.e. the {@link
 * InCallViewModel} that actively updates the in call page, then we don't show HUN for the ringing
 * call or attempt to start the in call page again.
 */
class InCallRouter {

    private static final String TAG = "CD.InCallRouter";

    private final Context mContext;
    private final InCallNotificationController mInCallNotificationController;
    private final ArrayList<InCallServiceImpl.ActiveCallListChangedCallback>
            mActiveCallListChangedCallbacks = new ArrayList<>();
    private final ProjectionCallHandler mProjectionCallHandler;

    InCallRouter(Context context) {
        mContext = context;
        mInCallNotificationController = InCallNotificationController.get();
        mProjectionCallHandler = new ProjectionCallHandler(context);
    }

    void start() {
        mProjectionCallHandler.start();
        mActiveCallListChangedCallbacks.add(mProjectionCallHandler);
    }

    void stop() {
        mActiveCallListChangedCallbacks.remove(mProjectionCallHandler);
        mProjectionCallHandler.stop();
    }

    /**
     * Routes the added call to the correct path:
     * <ul>
     * <li> First dispatches it to the {@link InCallServiceImpl.ActiveCallListChangedCallback}s.
     * <li> If the ringing call is not handled by callbacks, it will show a HUN.
     * <li> If the call is in other state and not handled by callbacks, it will try to launch the in
     * call page.
     */
    void onCallAdded(Call call) {
        boolean isHandled = routeToActiveCallListChangedCallback(call);
        if (isHandled) {
            return;
        }

        int state = call.getState();
        if (state == Call.STATE_RINGING) {
            routeToNotification(call);
            // Otherwise, no operations. Incoming call will be displayed outside of Dialer app
            // such as cluster.
        } else if (state != Call.STATE_DISCONNECTED) {
            // Don't launch the in call page if state is disconnected.
            // Otherwise, the InCallActivity finishes right after onCreate() and flashes.
            routeToFullScreenIncomingCallPage(false);
        }
    }

    /**
     * Called by {@link InCallServiceImpl#onCallRemoved(Call)}. It notifies the {@link
     * InCallServiceImpl.ActiveCallListChangedCallback}s to update the active call list.
     */
    void onCallRemoved(Call call) {
        for (InCallServiceImpl.ActiveCallListChangedCallback callback :
                mActiveCallListChangedCallbacks) {
            callback.onTelecomCallRemoved(call);
        }
    }

    @MainThread
    void registerActiveCallListChangedCallback(
            InCallServiceImpl.ActiveCallListChangedCallback callback) {
        mActiveCallListChangedCallbacks.add(callback);
    }

    @MainThread
    void unregisterActiveCallHandler(InCallServiceImpl.ActiveCallListChangedCallback callback) {
        mActiveCallListChangedCallbacks.remove(callback);
    }

    /**
     * Dispatches the call to {@link InCallServiceImpl.ActiveCallListChangedCallback}.
     */
    private boolean routeToActiveCallListChangedCallback(Call call) {
        boolean isHandled = false;
        for (InCallServiceImpl.ActiveCallListChangedCallback callback :
                mActiveCallListChangedCallbacks) {
            if (callback.onTelecomCallAdded(call)) {
                isHandled = true;
            }
        }

        return isHandled;
    }

    /**
     * Presents the ringing call in HUN.
     */
    private void routeToNotification(Call call) {
        if (shouldShowIncomingCallHun()) {
            mInCallNotificationController.showInCallNotification(call);
        }
        call.registerCallback(new Call.Callback() {
            @Override
            public void onStateChanged(Call call, int state) {
                L.d(TAG, "Ringing call state changed to %d", state);
                if (call.getState() != Call.STATE_DISCONNECTED) {
                    // Don't launch the in call page if state is disconnected. Otherwise, the
                    // InCallActivity finishes right after onCreate() and flashes.
                    routeToFullScreenIncomingCallPage(false);
                }
                mInCallNotificationController.cancelInCallNotification(call);
                call.unregisterCallback(this);
            }
        });
    }

    /**
     * Launches {@link InCallActivity} and presents the on going call in the in call page.
     */
    void routeToFullScreenIncomingCallPage(boolean showDialpad) {
        // It has been configured not to show the fullscreen incall ui.
        if (!shouldShowFullScreenUi()) {
            return;
        }

        Intent launchIntent = new Intent(mContext, InCallActivity.class);
        launchIntent.putExtra(Constants.Intents.EXTRA_SHOW_INCOMING_CALL, showDialpad);
        mContext.startActivity(launchIntent);
    }

    private boolean shouldShowIncomingCallHun() {
        boolean shouldSuppressHunByDefault =
                mContext.getResources().getBoolean(R.bool.config_should_suppress_incoming_call_hun);
        return !PreferenceManager.getDefaultSharedPreferences(mContext)
                .getBoolean(mContext.getString(R.string.pref_no_incoming_call_hun_key),
                        shouldSuppressHunByDefault);
    }

    private boolean shouldShowFullScreenUi() {
        boolean shouldShowFullScreenUiByDefault =
                mContext.getResources().getBoolean(R.bool.config_show_fullscreen_incall_ui);
        return PreferenceManager.getDefaultSharedPreferences(mContext)
                .getBoolean(mContext.getString(R.string.pref_show_fullscreen_active_call_ui_key),
                        shouldShowFullScreenUiByDefault);
    }
}
