/*
 * 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.car.dialer.telecom.embedded;

import com.android.car.dialer.telecom.UiCall;
import com.android.car.dialer.telecom.UiCallManager;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.IBinder;
import android.telecom.Call;
import android.telecom.Call.Details;
import android.telecom.CallAudioState;
import android.telecom.DisconnectCause;
import android.telecom.GatewayInfo;
import android.telecom.InCallService.VideoCall;
import android.telecom.TelecomManager;
import android.util.Log;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * An implementation of {@link UiCallManager} that uses {@code android.telecom.*} stack.
 */
public class TelecomUiCallManager extends UiCallManager {

    private static final String TAG = "Em.TelecomUiCallMgr";

    // Used to assign id's to UiCall objects as they're created.
    private static int nextCarPhoneCallId = 0;

    private TelecomManager mTelecomManager;
    private InCallServiceImpl mInCallService;
    private Map<UiCall, Call> mCallMapping = new HashMap<>();

    private List<CallListener> mCallListeners = new CopyOnWriteArrayList<>();

    @Override
    protected void setUp(Context context) {
        super.setUp(context);
        mTelecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
        Intent intent = new Intent(context, InCallServiceImpl.class);
        intent.setAction(InCallServiceImpl.ACTION_LOCAL_BIND);
        context.bindService(intent, mInCallServiceConnection, Context.BIND_AUTO_CREATE);
    }

    public void tearDown() {
        if (mInCallService != null) {
            mContext.unbindService(mInCallServiceConnection);
            mInCallService = null;
        }
        mCallMapping.clear();
    }

    @Override
    public void addListener(CallListener listener) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "addListener: " + listener);
        }
        mCallListeners.add(listener);
    }

    @Override
    public void removeListener(CallListener listener) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "removeListener: " + listener);
        }
        mCallListeners.remove(listener);
    }

    @Override
    public void placeCall(String number) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "placeCall: " + number);
        }
        Uri uri = Uri.fromParts("tel", number, null);
        Log.d(TAG, "android.telecom.TelecomManager#placeCall: " + uri);
        mTelecomManager.placeCall(uri, null);
    }

    @Override
    public void answerCall(UiCall uiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "answerCall: " + uiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.answer(0);
        }
    }

    @Override
    public void rejectCall(UiCall uiCall, boolean rejectWithMessage, String textMessage) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "rejectCall: " + uiCall + ", rejectWithMessage: " + rejectWithMessage
                    + "textMessage: " + textMessage);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.reject(rejectWithMessage, textMessage);
        }
    }

    @Override
    public void disconnectCall(UiCall uiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "disconnectCall: " + uiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.disconnect();
        }
    }

    @Override
    public List<UiCall> getCalls() {
        return new ArrayList<>(mCallMapping.keySet());
    }

    @Override
    public boolean getMuted() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "getMuted");
        }
        if (mInCallService == null) {
            return false;
        }
        CallAudioState audioState = mInCallService.getCallAudioState();
        return audioState != null && audioState.isMuted();
    }

    @Override
    public void setMuted(boolean muted) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "setMuted: " + muted);
        }
        if (mInCallService == null) {
            return;
        }
        mInCallService.setMuted(muted);
    }

    @Override
    public int getSupportedAudioRouteMask() {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "getSupportedAudioRouteMask");
        }

        CallAudioState audioState = getCallAudioStateOrNull();
        return audioState != null ? audioState.getSupportedRouteMask() : 0;
    }

    @Override
    public int getAudioRoute() {
        CallAudioState audioState = getCallAudioStateOrNull();
        int audioRoute = audioState != null ? audioState.getRoute() : 0;
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "getAudioRoute " + audioRoute);
        }
        return audioRoute;
    }

    @Override
    public void setAudioRoute(int audioRoute) {
        // In case of embedded where the CarKitt is always connected to one kind of speaker we
        // should simply ignore any setAudioRoute requests.
        Log.w(TAG, "setAudioRoute ignoring request " + audioRoute);
    }

    @Override
    public void holdCall(UiCall uiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "holdCall: " + uiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.hold();
        }
    }

    @Override
    public void unholdCall(UiCall uiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "unholdCall: " + uiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.unhold();
        }
    }

    @Override
    public void playDtmfTone(UiCall uiCall, char digit) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "playDtmfTone: call: " + uiCall + ", digit: " + digit);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.playDtmfTone(digit);
        }
    }

    @Override
    public void stopDtmfTone(UiCall uiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "stopDtmfTone: call: " + uiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.stopDtmfTone();
        }
    }

    @Override
    public void postDialContinue(UiCall uiCall, boolean proceed) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "postDialContinue: call: " + uiCall + ", proceed: " + proceed);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.postDialContinue(proceed);
        }
    }

    @Override
    public void conference(UiCall uiCall, UiCall otherUiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "conference: call: " + uiCall + ", otherCall: " + otherUiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        Call otherTelecomCall = mCallMapping.get(otherUiCall);
        if (telecomCall != null) {
            telecomCall.conference(otherTelecomCall);
        }
    }

    @Override
    public void splitFromConference(UiCall uiCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "splitFromConference: call: " + uiCall);
        }

        Call telecomCall = mCallMapping.get(uiCall);
        if (telecomCall != null) {
            telecomCall.splitFromConference();
        }
    }

    private UiCall doTelecomCallAdded(final Call telecomCall) {
        Log.d(TAG, "doTelecomCallAdded: " + telecomCall);

        UiCall uiCall = getOrCreateCallContainer(telecomCall);
        telecomCall.registerCallback(new TelecomCallListener(this, uiCall));
        for (CallListener listener : mCallListeners) {
            listener.onCallAdded(uiCall);
        }
        Log.d(TAG, "Call backs registered");

        if (telecomCall.getState() == Call.STATE_SELECT_PHONE_ACCOUNT) {
            // TODO(b/26189994): need to show Phone Account picker to let user choose a phone
            // account. It should be an account from TelecomManager#getCallCapablePhoneAccounts
            // list.
            Log.w(TAG, "Need to select phone account for the given call: " + telecomCall + ", "
                    + "but this feature is not implemented yet.");
            telecomCall.disconnect();
        }
        return uiCall;
    }

    private void doTelecomCallRemoved(Call telecomCall) {
        UiCall uiCall = getOrCreateCallContainer(telecomCall);

        mCallMapping.remove(uiCall);

        for (CallListener listener : mCallListeners) {
            listener.onCallRemoved(uiCall);
        }
    }

    private void doCallAudioStateChanged(CallAudioState audioState) {
        for (CallListener listener : mCallListeners) {
            listener.onAudioStateChanged(audioState.isMuted(), audioState.getRoute(),
                    audioState.getSupportedRouteMask());
        }
    }

    private void onStateChanged(UiCall uiCall, int state) {
        for (CallListener listener : mCallListeners) {
            listener.onStateChanged(uiCall, state);
        }
    }

    private void onCallUpdated(UiCall uiCall) {
        for (CallListener listener : mCallListeners) {
            listener.onCallUpdated(uiCall);
        }
    }

    private static class TelecomCallListener extends Call.Callback {
        private final WeakReference<TelecomUiCallManager> mCarTelecomMangerRef;
        private final WeakReference<UiCall> mCallContainerRef;

        TelecomCallListener(TelecomUiCallManager carTelecomManager, UiCall uiCall) {
            mCarTelecomMangerRef = new WeakReference<>(carTelecomManager);
            mCallContainerRef = new WeakReference<>(uiCall);
        }

        @Override
        public void onStateChanged(Call telecomCall, int state) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onStateChanged: " + state);
            }
            TelecomUiCallManager manager = mCarTelecomMangerRef.get();
            UiCall call = mCallContainerRef.get();
            if (manager != null && call != null) {
                call.setState(state);
                manager.onStateChanged(call, state);
            }
        }

        @Override
        public void onParentChanged(Call telecomCall, Call parent) {
            doCallUpdated(telecomCall);
        }

        @Override
        public void onCallDestroyed(Call telecomCall) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onCallDestroyed");
            }
        }

        @Override
        public void onDetailsChanged(Call telecomCall, Details details) {
            doCallUpdated(telecomCall);
        }

        @Override
        public void onVideoCallChanged(Call telecomCall, VideoCall videoCall) {
            doCallUpdated(telecomCall);
        }

        @Override
        public void onCannedTextResponsesLoaded(Call telecomCall,
                List<String> cannedTextResponses) {
            doCallUpdated(telecomCall);
        }

        @Override
        public void onChildrenChanged(Call telecomCall, List<Call> children) {
            doCallUpdated(telecomCall);
        }

        private void doCallUpdated(Call telecomCall) {
            TelecomUiCallManager manager = mCarTelecomMangerRef.get();
            UiCall uiCall = mCallContainerRef.get();
            if (manager != null && uiCall != null) {
                updateCallContainerFromTelecom(uiCall, telecomCall);
                manager.onCallUpdated(uiCall);
            }
        }
    }

    private ServiceConnection mInCallServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder binder) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onServiceConnected: " + name + ", service: " + binder);
            }
            mInCallService = ((InCallServiceImpl.LocalBinder) binder).getService();
            mInCallService.registerCallback(mInCallServiceCallback);

            // The InCallServiceImpl could be bound when we already have some active calls, let's
            // notify UI about these calls.
            for (Call telecomCall : mInCallService.getCalls()) {
                UiCall uiCall = doTelecomCallAdded(telecomCall);
                onStateChanged(uiCall, uiCall.getState());
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Log.d(TAG, "onServiceDisconnected: " + name);
            }
            mInCallService.unregisterCallback(mInCallServiceCallback);
        }

        private InCallServiceImpl.Callback mInCallServiceCallback =
                new InCallServiceImpl.Callback() {

            @Override
            public void onTelecomCallAdded(Call telecomCall) {
                doTelecomCallAdded(telecomCall);
            }

            @Override
            public void onTelecomCallRemoved(Call telecomCall) {
                doTelecomCallRemoved(telecomCall);
            }

            @Override
            public void onCallAudioStateChanged(CallAudioState audioState) {
                doCallAudioStateChanged(audioState);
            }
        };
    };

    private UiCall getOrCreateCallContainer(Call telecomCall) {
        for (Map.Entry<UiCall, Call> entry : mCallMapping.entrySet()) {
            if (entry.getValue() == telecomCall) {
                return entry.getKey();
            }
        }

        UiCall uiCall = new UiCall(nextCarPhoneCallId++);
        updateCallContainerFromTelecom(uiCall, telecomCall);
        mCallMapping.put(uiCall, telecomCall);
        return uiCall;
    }

    private static void updateCallContainerFromTelecom(UiCall uiCall, Call telecomCall) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "updateCallContainerFromTelecom: call: " + uiCall + ", telecomCall: "
                    + telecomCall);
        }

        uiCall.setState(telecomCall.getState());
        uiCall.setHasChildren(!telecomCall.getChildren().isEmpty());
        uiCall.setHasParent(telecomCall.getParent() != null);

        Call.Details details = telecomCall.getDetails();
        if (details == null) {
            return;
        }

        uiCall.setConnectTimeMillis(details.getConnectTimeMillis());

        DisconnectCause cause = details.getDisconnectCause();
        uiCall.setDisconnectCause(cause == null ? null : cause.getLabel());

        GatewayInfo gatewayInfo = details.getGatewayInfo();
        uiCall.setGatewayInfoOriginalAddress(
                gatewayInfo == null ? null : gatewayInfo.getOriginalAddress());

        String number = "";
        if (gatewayInfo != null) {
            number = gatewayInfo.getOriginalAddress().getSchemeSpecificPart();
        } else if (details.getHandle() != null) {
            number = details.getHandle().getSchemeSpecificPart();
        }
        uiCall.setNumber(number);

    }

    private CallAudioState getCallAudioStateOrNull() {
        return mInCallService != null ? mInCallService.getCallAudioState() : null;
    }
}
