/*
 * Copyright (C) 2010 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.net.sip;

import gov.nist.javax.sdp.fields.SDPKeywords;

import android.content.Context;
import android.media.AudioManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.media.ToneGenerator;
import android.net.Uri;
import android.net.rtp.AudioCodec;
import android.net.rtp.AudioGroup;
import android.net.rtp.AudioStream;
import android.net.rtp.RtpStream;
import android.net.wifi.WifiManager;
import android.os.Message;
import android.os.RemoteException;
import android.os.Vibrator;
import android.provider.Settings;
import android.util.Log;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.sdp.SdpException;

/**
 * Class that handles an audio call over SIP. 
 */
/** @hide */
public class SipAudioCallImpl extends SipSessionAdapter
        implements SipAudioCall {
    private static final String TAG = SipAudioCallImpl.class.getSimpleName();
    private static final boolean RELEASE_SOCKET = true;
    private static final boolean DONT_RELEASE_SOCKET = false;
    private static final String AUDIO = "audio";
    private static final int DTMF = 101;
    private static final int SESSION_TIMEOUT = 5; // in seconds

    private Context mContext;
    private SipProfile mLocalProfile;
    private SipAudioCall.Listener mListener;
    private ISipSession mSipSession;
    private SdpSessionDescription mPeerSd;

    private AudioStream mAudioStream;
    private AudioGroup mAudioGroup;
    private SdpSessionDescription.AudioCodec mCodec;
    private long mSessionId = -1L; // SDP session ID
    private boolean mInCall = false;
    private boolean mMuted = false;
    private boolean mHold = false;

    private boolean mRingbackToneEnabled = true;
    private boolean mRingtoneEnabled = true;
    private Ringtone mRingtone;
    private ToneGenerator mRingbackTone;

    private SipProfile mPendingCallRequest;
    private WifiManager mWm;
    private WifiManager.WifiLock mWifiHighPerfLock;

    private int mErrorCode = SipErrorCode.NO_ERROR;
    private String mErrorMessage;

    public SipAudioCallImpl(Context context, SipProfile localProfile) {
        mContext = context;
        mLocalProfile = localProfile;
        mWm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    }

    public void setListener(SipAudioCall.Listener listener) {
        setListener(listener, false);
    }

    public void setListener(SipAudioCall.Listener listener,
            boolean callbackImmediately) {
        mListener = listener;
        try {
            if ((listener == null) || !callbackImmediately) {
                // do nothing
            } else if (mErrorCode != SipErrorCode.NO_ERROR) {
                listener.onError(this, mErrorCode, mErrorMessage);
            } else if (mInCall) {
                if (mHold) {
                    listener.onCallHeld(this);
                } else {
                    listener.onCallEstablished(this);
                }
            } else {
                int state = getState();
                switch (state) {
                    case SipSessionState.READY_TO_CALL:
                        listener.onReadyToCall(this);
                        break;
                    case SipSessionState.INCOMING_CALL:
                        listener.onRinging(this, getPeerProfile(mSipSession));
                        break;
                    case SipSessionState.OUTGOING_CALL:
                        listener.onCalling(this);
                        break;
                    case SipSessionState.OUTGOING_CALL_RING_BACK:
                        listener.onRingingBack(this);
                        break;
                }
            }
        } catch (Throwable t) {
            Log.e(TAG, "setListener()", t);
        }
    }

    public synchronized boolean isInCall() {
        return mInCall;
    }

    public synchronized boolean isOnHold() {
        return mHold;
    }

    public void close() {
        close(true);
    }

    private synchronized void close(boolean closeRtp) {
        if (closeRtp) stopCall(RELEASE_SOCKET);
        stopRingbackTone();
        stopRinging();

        mInCall = false;
        mHold = false;
        mSessionId = -1L;
        mErrorCode = SipErrorCode.NO_ERROR;
        mErrorMessage = null;

        if (mSipSession != null) {
            try {
                mSipSession.setListener(null);
            } catch (RemoteException e) {
                // don't care
            }
            mSipSession = null;
        }
    }

    public synchronized SipProfile getLocalProfile() {
        return mLocalProfile;
    }

    public synchronized SipProfile getPeerProfile() {
        try {
            return (mSipSession == null) ? null : mSipSession.getPeerProfile();
        } catch (RemoteException e) {
            return null;
        }
    }

    public synchronized int getState() {
        if (mSipSession == null) return SipSessionState.READY_TO_CALL;
        try {
            return mSipSession.getState();
        } catch (RemoteException e) {
            return SipSessionState.REMOTE_ERROR;
        }
    }


    public synchronized ISipSession getSipSession() {
        return mSipSession;
    }

    @Override
    public void onCalling(ISipSession session) {
        Log.d(TAG, "calling... " + session);
        Listener listener = mListener;
        if (listener != null) {
            try {
                listener.onCalling(this);
            } catch (Throwable t) {
                Log.e(TAG, "onCalling()", t);
            }
        }
    }

    @Override
    public void onRingingBack(ISipSession session) {
        Log.d(TAG, "sip call ringing back: " + session);
        if (!mInCall) startRingbackTone();
        Listener listener = mListener;
        if (listener != null) {
            try {
                listener.onRingingBack(this);
            } catch (Throwable t) {
                Log.e(TAG, "onRingingBack()", t);
            }
        }
    }

    @Override
    public synchronized void onRinging(ISipSession session,
            SipProfile peerProfile, String sessionDescription) {
        try {
            if ((mSipSession == null) || !mInCall
                    || !session.getCallId().equals(mSipSession.getCallId())) {
                // should not happen
                session.endCall();
                return;
            }

            // session changing request
            try {
                mPeerSd = new SdpSessionDescription(sessionDescription);
                answerCall(SESSION_TIMEOUT);
            } catch (Throwable e) {
                Log.e(TAG, "onRinging()", e);
                session.endCall();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "onRinging()", e);
        }
    }

    @Override
    public void onCallEstablished(ISipSession session,
            String sessionDescription) {
        stopRingbackTone();
        stopRinging();
        try {
            mPeerSd = new SdpSessionDescription(sessionDescription);
            Log.d(TAG, "sip call established: " + mPeerSd);
        } catch (SdpException e) {
            Log.e(TAG, "createSessionDescription()", e);
        }

        Listener listener = mListener;
        if (listener != null) {
            try {
                if (mHold) {
                    listener.onCallHeld(this);
                } else {
                    listener.onCallEstablished(this);
                }
            } catch (Throwable t) {
                Log.e(TAG, "onCallEstablished()", t);
            }
        }
    }

    @Override
    public void onCallEnded(ISipSession session) {
        Log.d(TAG, "sip call ended: " + session);
        Listener listener = mListener;
        if (listener != null) {
            try {
                listener.onCallEnded(this);
            } catch (Throwable t) {
                Log.e(TAG, "onCallEnded()", t);
            }
        }
        close();
    }

    @Override
    public void onCallBusy(ISipSession session) {
        Log.d(TAG, "sip call busy: " + session);
        Listener listener = mListener;
        if (listener != null) {
            try {
                listener.onCallBusy(this);
            } catch (Throwable t) {
                Log.e(TAG, "onCallBusy()", t);
            }
        }
        close(false);
    }

    @Override
    public void onCallChangeFailed(ISipSession session, int errorCode,
            String message) {
        Log.d(TAG, "sip call change failed: " + message);
        mErrorCode = errorCode;
        mErrorMessage = message;
        Listener listener = mListener;
        if (listener != null) {
            try {
                listener.onError(this, mErrorCode, message);
            } catch (Throwable t) {
                Log.e(TAG, "onCallBusy()", t);
            }
        }
    }

    @Override
    public void onError(ISipSession session, int errorCode, String message) {
        Log.d(TAG, "sip session error: " + SipErrorCode.toString(errorCode)
                + ": " + message);
        mErrorCode = errorCode;
        mErrorMessage = message;
        Listener listener = mListener;
        if (listener != null) {
            try {
                listener.onError(this, errorCode, message);
            } catch (Throwable t) {
                Log.e(TAG, "onError()", t);
            }
        }
        synchronized (this) {
            if ((errorCode == SipErrorCode.DATA_CONNECTION_LOST)
                    || !isInCall()) {
                close(true);
            }
        }
    }

    public synchronized void attachCall(ISipSession session,
            String sessionDescription) throws SipException {
        mSipSession = session;
        try {
            mPeerSd = new SdpSessionDescription(sessionDescription);
            session.setListener(this);

            if (getState() == SipSessionState.INCOMING_CALL) startRinging();
        } catch (Throwable e) {
            Log.e(TAG, "attachCall()", e);
            throwSipException(e);
        }
    }

    public synchronized void makeCall(SipProfile peerProfile,
            SipManager sipManager, int timeout) throws SipException {
        try {
            mSipSession = sipManager.createSipSession(mLocalProfile, this);
            if (mSipSession == null) {
                throw new SipException(
                        "Failed to create SipSession; network available?");
            }
            mSipSession.makeCall(peerProfile, createOfferSessionDescription(),
                    timeout);
        } catch (Throwable e) {
            if (e instanceof SipException) {
                throw (SipException) e;
            } else {
                throwSipException(e);
            }
        }
    }

    public synchronized void endCall() throws SipException {
        try {
            stopRinging();
            stopCall(true);
            mInCall = false;

            // perform the above local ops first and then network op
            if (mSipSession != null) mSipSession.endCall();
        } catch (Throwable e) {
            throwSipException(e);
        }
    }

    public synchronized void holdCall(int timeout) throws SipException {
        if (mHold) return;
        try {
            mSipSession.changeCall(createHoldSessionDescription(), timeout);
            mHold = true;
        } catch (Throwable e) {
            throwSipException(e);
        }

        AudioGroup audioGroup = getAudioGroup();
        if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
    }

    public synchronized void answerCall(int timeout) throws SipException {
        try {
            stopRinging();
            mSipSession.answerCall(createAnswerSessionDescription(), timeout);
        } catch (Throwable e) {
            Log.e(TAG, "answerCall()", e);
            throwSipException(e);
        }
    }

    public synchronized void continueCall(int timeout) throws SipException {
        if (!mHold) return;
        try {
            mHold = false;
            mSipSession.changeCall(createContinueSessionDescription(), timeout);
        } catch (Throwable e) {
            throwSipException(e);
        }

        AudioGroup audioGroup = getAudioGroup();
        if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_NORMAL);
    }

    private String createOfferSessionDescription() {
        AudioCodec[] codecs = AudioCodec.getSystemSupportedCodecs();
        return createSdpBuilder(true, convert(codecs)).build();
    }

    private String createAnswerSessionDescription() {
        try {
            // choose an acceptable media from mPeerSd to answer
            SdpSessionDescription.AudioCodec codec = getCodec(mPeerSd);
            SdpSessionDescription.Builder sdpBuilder =
                    createSdpBuilder(false, codec);
            if (mPeerSd.isSendOnly(AUDIO)) {
                sdpBuilder.addMediaAttribute(AUDIO, "recvonly", (String) null);
            } else if (mPeerSd.isReceiveOnly(AUDIO)) {
                sdpBuilder.addMediaAttribute(AUDIO, "sendonly", (String) null);
            }
            return sdpBuilder.build();
        } catch (SdpException e) {
            throw new RuntimeException(e);
        }
    }

    private String createHoldSessionDescription() {
        try {
            return createSdpBuilder(false, mCodec)
                    .addMediaAttribute(AUDIO, "sendonly", (String) null)
                    .build();
        } catch (SdpException e) {
            throw new RuntimeException(e);
        }
    }

    private void grabWifiHighPerfLock() {
        if (mWifiHighPerfLock == null) {
            Log.v(TAG, "acquire wifi high perf lock");
            mWifiHighPerfLock = ((WifiManager)
                    mContext.getSystemService(Context.WIFI_SERVICE))
                    .createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, TAG);
            mWifiHighPerfLock.acquire();
        }
    }

    private void releaseWifiHighPerfLock() {
        if (mWifiHighPerfLock != null) {
            Log.v(TAG, "release wifi high perf lock");
            mWifiHighPerfLock.release();
            mWifiHighPerfLock = null;
        }
    }

    private boolean isWifiOn() {
        return (mWm.getConnectionInfo().getBSSID() == null) ? false : true;
    }

    private String createContinueSessionDescription() {
        return createSdpBuilder(true, mCodec).build();
    }

    private String getMediaDescription(SdpSessionDescription.AudioCodec codec) {
        return String.format("%d %s/%d", codec.payloadType, codec.name,
                codec.sampleRate);
    }

    private long getSessionId() {
        if (mSessionId < 0) {
            mSessionId = System.currentTimeMillis();
        }
        return mSessionId;
    }

    private SdpSessionDescription.Builder createSdpBuilder(
            boolean addTelephoneEvent,
            SdpSessionDescription.AudioCodec... codecs) {
        String localIp = getLocalIp();
        SdpSessionDescription.Builder sdpBuilder;
        try {
            long sessionVersion = System.currentTimeMillis();
            sdpBuilder = new SdpSessionDescription.Builder("SIP Call")
                    .setOrigin(mLocalProfile, getSessionId(), sessionVersion,
                            SDPKeywords.IN, SDPKeywords.IPV4, localIp)
                    .setConnectionInfo(SDPKeywords.IN, SDPKeywords.IPV4,
                            localIp);
            List<Integer> codecIds = new ArrayList<Integer>();
            for (SdpSessionDescription.AudioCodec codec : codecs) {
                codecIds.add(codec.payloadType);
            }
            if (addTelephoneEvent) codecIds.add(DTMF);
            sdpBuilder.addMedia(AUDIO, getLocalMediaPort(), 1, "RTP/AVP",
                    codecIds.toArray(new Integer[codecIds.size()]));
            for (SdpSessionDescription.AudioCodec codec : codecs) {
                sdpBuilder.addMediaAttribute(AUDIO, "rtpmap",
                        getMediaDescription(codec));
            }
            if (addTelephoneEvent) {
                sdpBuilder.addMediaAttribute(AUDIO, "rtpmap",
                        DTMF + " telephone-event/8000");
            }
            // FIXME: deal with vbr codec
            sdpBuilder.addMediaAttribute(AUDIO, "ptime", "20");
        } catch (SdpException e) {
            throw new RuntimeException(e);
        }
        return sdpBuilder;
    }

    public synchronized void toggleMute() {
        AudioGroup audioGroup = getAudioGroup();
        if (audioGroup != null) {
            audioGroup.setMode(
                    mMuted ? AudioGroup.MODE_NORMAL : AudioGroup.MODE_MUTED);
            mMuted = !mMuted;
        }
    }

    public synchronized boolean isMuted() {
        return mMuted;
    }

    public synchronized void setSpeakerMode(boolean speakerMode) {
        ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE))
                .setSpeakerphoneOn(speakerMode);
    }

    public void sendDtmf(int code) {
        sendDtmf(code, null);
    }

    public synchronized void sendDtmf(int code, Message result) {
        AudioGroup audioGroup = getAudioGroup();
        if ((audioGroup != null) && (mSipSession != null)
                && (SipSessionState.IN_CALL == getState())) {
            Log.v(TAG, "send DTMF: " + code);
            audioGroup.sendDtmf(code);
        }
        if (result != null) result.sendToTarget();
    }

    public synchronized AudioStream getAudioStream() {
        return mAudioStream;
    }

    public synchronized AudioGroup getAudioGroup() {
        if (mAudioGroup != null) return mAudioGroup;
        return ((mAudioStream == null) ? null : mAudioStream.getAudioGroup());
    }

    public synchronized void setAudioGroup(AudioGroup group) {
        if ((mAudioStream != null) && (mAudioStream.getAudioGroup() != null)) {
            mAudioStream.join(group);
        }
        mAudioGroup = group;
    }

    private SdpSessionDescription.AudioCodec getCodec(SdpSessionDescription sd) {
        HashMap<String, AudioCodec> acceptableCodecs =
                new HashMap<String, AudioCodec>();
        for (AudioCodec codec : AudioCodec.getSystemSupportedCodecs()) {
            acceptableCodecs.put(codec.name, codec);
        }
        for (SdpSessionDescription.AudioCodec codec : sd.getAudioCodecs()) {
            AudioCodec matchedCodec = acceptableCodecs.get(codec.name);
            if (matchedCodec != null) return codec;
        }
        Log.w(TAG, "no common codec is found, use PCM/0");
        return convert(AudioCodec.ULAW);
    }

    private AudioCodec convert(SdpSessionDescription.AudioCodec codec) {
        AudioCodec c = AudioCodec.getSystemSupportedCodec(codec.name);
        return ((c == null) ? AudioCodec.ULAW : c);
    }

    private SdpSessionDescription.AudioCodec convert(AudioCodec codec) {
        return new SdpSessionDescription.AudioCodec(codec.defaultType,
                codec.name, codec.sampleRate, codec.sampleCount);
    }

    private SdpSessionDescription.AudioCodec[] convert(AudioCodec[] codecs) {
        SdpSessionDescription.AudioCodec[] copies =
                new SdpSessionDescription.AudioCodec[codecs.length];
        for (int i = 0, len = codecs.length; i < len; i++) {
            copies[i] = convert(codecs[i]);
        }
        return copies;
    }

    public void startAudio() {
        try {
            startAudioInternal();
        } catch (UnknownHostException e) {
            onError(mSipSession, SipErrorCode.PEER_NOT_REACHABLE,
                    e.getMessage());
        } catch (Throwable e) {
            onError(mSipSession, SipErrorCode.CLIENT_ERROR,
                    e.getMessage());
        }
    }

    private synchronized void startAudioInternal() throws UnknownHostException {
        stopCall(DONT_RELEASE_SOCKET);
        mInCall = true;
        SdpSessionDescription peerSd = mPeerSd;
        if (isWifiOn()) grabWifiHighPerfLock();
        String peerMediaAddress = peerSd.getPeerMediaAddress(AUDIO);
        // TODO: handle multiple media fields
        int peerMediaPort = peerSd.getPeerMediaPort(AUDIO);
        Log.i(TAG, "start audiocall " + peerMediaAddress + ":" + peerMediaPort);

        int localPort = getLocalMediaPort();
        int sampleRate = 8000;
        int frameSize = sampleRate / 50; // 160

        // TODO: get sample rate from sdp
        mCodec = getCodec(peerSd);

        AudioStream audioStream = mAudioStream;
        audioStream.associate(InetAddress.getByName(peerMediaAddress),
                peerMediaPort);
        audioStream.setCodec(convert(mCodec), mCodec.payloadType);
        audioStream.setDtmfType(DTMF);
        Log.d(TAG, "start media: localPort=" + localPort + ", peer="
                + peerMediaAddress + ":" + peerMediaPort);

        audioStream.setMode(RtpStream.MODE_NORMAL);
        if (!mHold) {
            // FIXME: won't work if peer is not sending nor receiving
            if (!peerSd.isSending(AUDIO)) {
                Log.d(TAG, "   not receiving");
                audioStream.setMode(RtpStream.MODE_SEND_ONLY);
            }
            if (!peerSd.isReceiving(AUDIO)) {
                Log.d(TAG, "   not sending");
                audioStream.setMode(RtpStream.MODE_RECEIVE_ONLY);
            }

            /* The recorder volume will be very low if the device is in
             * IN_CALL mode. Therefore, we have to set the mode to NORMAL
             * in order to have the normal microphone level.
             */
            ((AudioManager) mContext.getSystemService
                    (Context.AUDIO_SERVICE))
                    .setMode(AudioManager.MODE_NORMAL);
        }

        // AudioGroup logic:
        AudioGroup audioGroup = getAudioGroup();
        if (mHold) {
            if (audioGroup != null) {
                audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
            }
            // don't create an AudioGroup here; doing so will fail if
            // there's another AudioGroup out there that's active
        } else {
            if (audioGroup == null) audioGroup = new AudioGroup();
            audioStream.join(audioGroup);
            if (mMuted) {
                audioGroup.setMode(AudioGroup.MODE_MUTED);
            } else {
                audioGroup.setMode(AudioGroup.MODE_NORMAL);
            }
        }
    }

    private void stopCall(boolean releaseSocket) {
        Log.d(TAG, "stop audiocall");
        releaseWifiHighPerfLock();
        if (mAudioStream != null) {
            mAudioStream.join(null);

            if (releaseSocket) {
                mAudioStream.release();
                mAudioStream = null;
            }
        }
    }

    private int getLocalMediaPort() {
        if (mAudioStream != null) return mAudioStream.getLocalPort();
        try {
            AudioStream s = mAudioStream =
                    new AudioStream(InetAddress.getByName(getLocalIp()));
            return s.getLocalPort();
        } catch (IOException e) {
            Log.w(TAG, "getLocalMediaPort(): " + e);
            throw new RuntimeException(e);
        }
    }

    private String getLocalIp() {
        try {
            return mSipSession.getLocalIp();
        } catch (RemoteException e) {
            // FIXME
            return "127.0.0.1";
        }
    }

    public synchronized void setRingbackToneEnabled(boolean enabled) {
        mRingbackToneEnabled = enabled;
    }

    public synchronized void setRingtoneEnabled(boolean enabled) {
        mRingtoneEnabled = enabled;
    }

    private void startRingbackTone() {
        if (!mRingbackToneEnabled) return;
        if (mRingbackTone == null) {
            // The volume relative to other sounds in the stream
            int toneVolume = 80;
            mRingbackTone = new ToneGenerator(
                    AudioManager.STREAM_VOICE_CALL, toneVolume);
        }
        mRingbackTone.startTone(ToneGenerator.TONE_CDMA_LOW_PBX_L);
    }

    private void stopRingbackTone() {
        if (mRingbackTone != null) {
            mRingbackTone.stopTone();
            mRingbackTone.release();
            mRingbackTone = null;
        }
    }

    private void startRinging() {
        if (!mRingtoneEnabled) return;
        ((Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE))
                .vibrate(new long[] {0, 1000, 1000}, 1);
        AudioManager am = (AudioManager)
                mContext.getSystemService(Context.AUDIO_SERVICE);
        if (am.getStreamVolume(AudioManager.STREAM_RING) > 0) {
            String ringtoneUri =
                    Settings.System.DEFAULT_RINGTONE_URI.toString();
            mRingtone = RingtoneManager.getRingtone(mContext,
                    Uri.parse(ringtoneUri));
            mRingtone.play();
        }
    }

    private void stopRinging() {
        ((Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE))
                .cancel();
        if (mRingtone != null) mRingtone.stop();
    }

    private void throwSipException(Throwable throwable) throws SipException {
        if (throwable instanceof SipException) {
            throw (SipException) throwable;
        } else {
            throw new SipException("", throwable);
        }
    }

    private SipProfile getPeerProfile(ISipSession session) {
        try {
            return session.getPeerProfile();
        } catch (RemoteException e) {
            return null;
        }
    }
}
