/*
 * 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 android.telecom;

import com.android.internal.telecom.IConnectionService;

import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * A conference provided to a {@link ConnectionService} by another {@code ConnectionService} through
 * {@link ConnectionService#conferenceRemoteConnections}. Once created, a {@code RemoteConference}
 * can be used to control the conference call or monitor changes through
 * {@link RemoteConnection.Callback}.
 *
 * @see ConnectionService#onRemoteConferenceAdded
 */
public final class RemoteConference {

    /**
     * Callback base class for {@link RemoteConference}.
     */
    public abstract static class Callback {
        /**
         * Invoked when the state of this {@code RemoteConferece} has changed. See
         * {@link #getState()}.
         *
         * @param conference The {@code RemoteConference} invoking this method.
         * @param oldState The previous state of the {@code RemoteConference}.
         * @param newState The new state of the {@code RemoteConference}.
         */
        public void onStateChanged(RemoteConference conference, int oldState, int newState) {}

        /**
         * Invoked when this {@code RemoteConference} is disconnected.
         *
         * @param conference The {@code RemoteConference} invoking this method.
         * @param disconnectCause The ({@see DisconnectCause}) associated with this failed
         *     conference.
         */
        public void onDisconnected(RemoteConference conference, DisconnectCause disconnectCause) {}

        /**
         * Invoked when a {@link RemoteConnection} is added to the conference call.
         *
         * @param conference The {@code RemoteConference} invoking this method.
         * @param connection The {@link RemoteConnection} being added.
         */
        public void onConnectionAdded(RemoteConference conference, RemoteConnection connection) {}

        /**
         * Invoked when a {@link RemoteConnection} is removed from the conference call.
         *
         * @param conference The {@code RemoteConference} invoking this method.
         * @param connection The {@link RemoteConnection} being removed.
         */
        public void onConnectionRemoved(RemoteConference conference, RemoteConnection connection) {}

        /**
         * Indicates that the call capabilities of this {@code RemoteConference} have changed.
         * See {@link #getConnectionCapabilities()}.
         *
         * @param conference The {@code RemoteConference} invoking this method.
         * @param connectionCapabilities The new capabilities of the {@code RemoteConference}.
         */
        public void onConnectionCapabilitiesChanged(
                RemoteConference conference,
                int connectionCapabilities) {}

        /**
         * Indicates that the call properties of this {@code RemoteConference} have changed.
         * See {@link #getConnectionProperties()}.
         *
         * @param conference The {@code RemoteConference} invoking this method.
         * @param connectionProperties The new properties of the {@code RemoteConference}.
         * @hide
         */
        public void onConnectionPropertiesChanged(
                RemoteConference conference,
                int connectionProperties) {}


        /**
         * Invoked when the set of {@link RemoteConnection}s which can be added to this conference
         * call have changed.
         *
         * @param conference The {@code RemoteConference} invoking this method.
         * @param conferenceableConnections The list of conferenceable {@link RemoteConnection}s.
         */
        public void onConferenceableConnectionsChanged(
                RemoteConference conference,
                List<RemoteConnection> conferenceableConnections) {}

        /**
         * Indicates that this {@code RemoteConference} has been destroyed. No further requests
         * should be made to the {@code RemoteConference}, and references to it should be cleared.
         *
         * @param conference The {@code RemoteConference} invoking this method.
         */
        public void onDestroyed(RemoteConference conference) {}

        /**
         * Handles changes to the {@code RemoteConference} extras.
         *
         * @param conference The {@code RemoteConference} invoking this method.
         * @param extras The extras containing other information associated with the conference.
         */
        public void onExtrasChanged(RemoteConference conference, @Nullable Bundle extras) {}
    }

    private final String mId;
    private final IConnectionService mConnectionService;

    private final Set<CallbackRecord<Callback>> mCallbackRecords = new CopyOnWriteArraySet<>();
    private final List<RemoteConnection> mChildConnections = new CopyOnWriteArrayList<>();
    private final List<RemoteConnection> mUnmodifiableChildConnections =
            Collections.unmodifiableList(mChildConnections);
    private final List<RemoteConnection> mConferenceableConnections = new ArrayList<>();
    private final List<RemoteConnection> mUnmodifiableConferenceableConnections =
            Collections.unmodifiableList(mConferenceableConnections);

    private int mState = Connection.STATE_NEW;
    private DisconnectCause mDisconnectCause;
    private int mConnectionCapabilities;
    private int mConnectionProperties;
    private Bundle mExtras;

    /** @hide */
    RemoteConference(String id, IConnectionService connectionService) {
        mId = id;
        mConnectionService = connectionService;
    }

    /** @hide */
    String getId() {
        return mId;
    }

    /** @hide */
    void setDestroyed() {
        for (RemoteConnection connection : mChildConnections) {
            connection.setConference(null);
        }
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final RemoteConference conference = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onDestroyed(conference);
                }
            });
        }
    }

    /** @hide */
    void setState(final int newState) {
        if (newState != Connection.STATE_ACTIVE &&
                newState != Connection.STATE_HOLDING &&
                newState != Connection.STATE_DISCONNECTED) {
            Log.w(this, "Unsupported state transition for Conference call.",
                    Connection.stateToString(newState));
            return;
        }

        if (mState != newState) {
            final int oldState = mState;
            mState = newState;
            for (CallbackRecord<Callback> record : mCallbackRecords) {
                final RemoteConference conference = this;
                final Callback callback = record.getCallback();
                record.getHandler().post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onStateChanged(conference, oldState, newState);
                    }
                });
            }
        }
    }

    /** @hide */
    void addConnection(final RemoteConnection connection) {
        if (!mChildConnections.contains(connection)) {
            mChildConnections.add(connection);
            connection.setConference(this);
            for (CallbackRecord<Callback> record : mCallbackRecords) {
                final RemoteConference conference = this;
                final Callback callback = record.getCallback();
                record.getHandler().post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onConnectionAdded(conference, connection);
                    }
                });
            }
        }
    }

    /** @hide */
    void removeConnection(final RemoteConnection connection) {
        if (mChildConnections.contains(connection)) {
            mChildConnections.remove(connection);
            connection.setConference(null);
            for (CallbackRecord<Callback> record : mCallbackRecords) {
                final RemoteConference conference = this;
                final Callback callback = record.getCallback();
                record.getHandler().post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onConnectionRemoved(conference, connection);
                    }
                });
            }
        }
    }

    /** @hide */
    void setConnectionCapabilities(final int connectionCapabilities) {
        if (mConnectionCapabilities != connectionCapabilities) {
            mConnectionCapabilities = connectionCapabilities;
            for (CallbackRecord<Callback> record : mCallbackRecords) {
                final RemoteConference conference = this;
                final Callback callback = record.getCallback();
                record.getHandler().post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onConnectionCapabilitiesChanged(
                                conference, mConnectionCapabilities);
                    }
                });
            }
        }
    }

    /** @hide */
    void setConnectionProperties(final int connectionProperties) {
        if (mConnectionProperties != connectionProperties) {
            mConnectionProperties = connectionProperties;
            for (CallbackRecord<Callback> record : mCallbackRecords) {
                final RemoteConference conference = this;
                final Callback callback = record.getCallback();
                record.getHandler().post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onConnectionPropertiesChanged(
                                conference, mConnectionProperties);
                    }
                });
            }
        }
    }

    /** @hide */
    void setConferenceableConnections(List<RemoteConnection> conferenceableConnections) {
        mConferenceableConnections.clear();
        mConferenceableConnections.addAll(conferenceableConnections);
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final RemoteConference conference = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onConferenceableConnectionsChanged(
                            conference, mUnmodifiableConferenceableConnections);
                }
            });
        }
    }

    /** @hide */
    void setDisconnected(final DisconnectCause disconnectCause) {
        if (mState != Connection.STATE_DISCONNECTED) {
            mDisconnectCause = disconnectCause;
            setState(Connection.STATE_DISCONNECTED);
            for (CallbackRecord<Callback> record : mCallbackRecords) {
                final RemoteConference conference = this;
                final Callback callback = record.getCallback();
                record.getHandler().post(new Runnable() {
                    @Override
                    public void run() {
                        callback.onDisconnected(conference, disconnectCause);
                    }
                });
            }
        }
    }

    /** @hide */
    void putExtras(final Bundle extras) {
        if (mExtras == null) {
            mExtras = new Bundle();
        }
        mExtras.putAll(extras);

        notifyExtrasChanged();
    }

    /** @hide */
    void removeExtras(List<String> keys) {
        if (mExtras == null || keys == null || keys.isEmpty()) {
            return;
        }
        for (String key : keys) {
            mExtras.remove(key);
        }

        notifyExtrasChanged();
    }

    private void notifyExtrasChanged() {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final RemoteConference conference = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(new Runnable() {
                @Override
                public void run() {
                    callback.onExtrasChanged(conference, mExtras);
                }
            });
        }
    }

    /**
     * Returns the list of {@link RemoteConnection}s contained in this conference.
     *
     * @return A list of child connections.
     */
    public final List<RemoteConnection> getConnections() {
        return mUnmodifiableChildConnections;
    }

    /**
     * Gets the state of the conference call. See {@link Connection} for valid values.
     *
     * @return A constant representing the state the conference call is currently in.
     */
    public final int getState() {
        return mState;
    }

    /**
     * Returns the capabilities of the conference. See {@code CAPABILITY_*} constants in class
     * {@link Connection} for valid values.
     *
     * @return A bitmask of the capabilities of the conference call.
     */
    public final int getConnectionCapabilities() {
        return mConnectionCapabilities;
    }

    /**
     * Returns the properties of the conference. See {@code PROPERTY_*} constants in class
     * {@link Connection} for valid values.
     *
     * @return A bitmask of the properties of the conference call.
     */
    public final int getConnectionProperties() {
        return mConnectionProperties;
    }

    /**
     * Obtain the extras associated with this {@code RemoteConnection}.
     *
     * @return The extras for this connection.
     */
    public final Bundle getExtras() {
        return mExtras;
    }

    /**
     * Disconnects the conference call as well as the child {@link RemoteConnection}s.
     */
    public void disconnect() {
        try {
            mConnectionService.disconnect(mId);
        } catch (RemoteException e) {
        }
    }

    /**
     * Removes the specified {@link RemoteConnection} from the conference. This causes the
     * {@link RemoteConnection} to become a standalone connection. This is a no-op if the
     * {@link RemoteConnection} does not belong to this conference.
     *
     * @param connection The remote-connection to remove.
     */
    public void separate(RemoteConnection connection) {
        if (mChildConnections.contains(connection)) {
            try {
                mConnectionService.splitFromConference(connection.getId());
            } catch (RemoteException e) {
            }
        }
    }

    /**
     * Merges all {@link RemoteConnection}s of this conference into a single call. This should be
     * invoked only if the conference contains the capability
     * {@link Connection#CAPABILITY_MERGE_CONFERENCE}, otherwise it is a no-op. The presence of said
     * capability indicates that the connections of this conference, despite being part of the
     * same conference object, are yet to have their audio streams merged; this is a common pattern
     * for CDMA conference calls, but the capability is not used for GSM and SIP conference calls.
     * Invoking this method will cause the unmerged child connections to merge their audio
     * streams.
     */
    public void merge() {
        try {
            mConnectionService.mergeConference(mId);
        } catch (RemoteException e) {
        }
    }

    /**
     * Swaps the active audio stream between the conference's child {@link RemoteConnection}s.
     * This should be invoked only if the conference contains the capability
     * {@link Connection#CAPABILITY_SWAP_CONFERENCE}, otherwise it is a no-op. This is only used by
     * {@link ConnectionService}s that create conferences for connections that do not yet have
     * their audio streams merged; this is a common pattern for CDMA conference calls, but the
     * capability is not used for GSM and SIP conference calls. Invoking this method will change the
     * active audio stream to a different child connection.
     */
    public void swap() {
        try {
            mConnectionService.swapConference(mId);
        } catch (RemoteException e) {
        }
    }

    /**
     * Puts the conference on hold.
     */
    public void hold() {
        try {
            mConnectionService.hold(mId);
        } catch (RemoteException e) {
        }
    }

    /**
     * Unholds the conference call.
     */
    public void unhold() {
        try {
            mConnectionService.unhold(mId);
        } catch (RemoteException e) {
        }
    }

    /**
     * Returns the {@link DisconnectCause} for the conference if it is in the state
     * {@link Connection#STATE_DISCONNECTED}. If the conference is not disconnected, this will
     * return null.
     *
     * @return The disconnect cause.
     */
    public DisconnectCause getDisconnectCause() {
        return mDisconnectCause;
    }

    /**
     * Requests that the conference start playing the specified DTMF tone.
     *
     * @param digit The digit for which to play a DTMF tone.
     */
    public void playDtmfTone(char digit) {
        try {
            mConnectionService.playDtmfTone(mId, digit);
        } catch (RemoteException e) {
        }
    }

    /**
     * Stops the most recent request to play a DTMF tone.
     *
     * @see #playDtmfTone
     */
    public void stopDtmfTone() {
        try {
            mConnectionService.stopDtmfTone(mId);
        } catch (RemoteException e) {
        }
    }

    /**
     * Request to change the conference's audio routing to the specified state. The specified state
     * can include audio routing (Bluetooth, Speaker, etc) and muting state.
     *
     * @see android.telecom.AudioState
     * @deprecated Use {@link #setCallAudioState(CallAudioState)} instead.
     * @hide
     */
    @SystemApi
    @Deprecated
    public void setAudioState(AudioState state) {
        setCallAudioState(new CallAudioState(state));
    }

    /**
     * Request to change the conference's audio routing to the specified state. The specified state
     * can include audio routing (Bluetooth, Speaker, etc) and muting state.
     */
    public void setCallAudioState(CallAudioState state) {
        try {
            mConnectionService.onCallAudioStateChanged(mId, state);
        } catch (RemoteException e) {
        }
    }


    /**
     * Returns a list of independent connections that can me merged with this conference.
     *
     * @return A list of conferenceable connections.
     */
    public List<RemoteConnection> getConferenceableConnections() {
        return mUnmodifiableConferenceableConnections;
    }

    /**
     * Register a callback through which to receive state updates for this conference.
     *
     * @param callback The callback to notify of state changes.
     */
    public final void registerCallback(Callback callback) {
        registerCallback(callback, new Handler());
    }

    /**
     * Registers a callback through which to receive state updates for this conference.
     * Callbacks will be notified using the specified handler, if provided.
     *
     * @param callback The callback to notify of state changes.
     * @param handler The handler on which to execute the callbacks.
     */
    public final void registerCallback(Callback callback, Handler handler) {
        unregisterCallback(callback);
        if (callback != null && handler != null) {
            mCallbackRecords.add(new CallbackRecord(callback, handler));
        }
    }

    /**
     * Unregisters a previously registered callback.
     *
     * @see #registerCallback
     *
     * @param callback The callback to unregister.
     */
    public final void unregisterCallback(Callback callback) {
        if (callback != null) {
            for (CallbackRecord<Callback> record : mCallbackRecords) {
                if (record.getCallback() == callback) {
                    mCallbackRecords.remove(record);
                    break;
                }
            }
        }
    }
}
