/*
 * 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 com.android.server.sip;

import android.net.sip.ISipSession;
import android.net.sip.ISipSessionListener;
import android.net.sip.SipProfile;
import android.os.DeadObjectException;
import android.util.Log;

/** Class to help safely run a callback in a different thread. */
class SipSessionListenerProxy extends ISipSessionListener.Stub {
    private static final String TAG = "SipSession";

    private ISipSessionListener mListener;

    public void setListener(ISipSessionListener listener) {
        mListener = listener;
    }

    public ISipSessionListener getListener() {
        return mListener;
    }

    private void proxy(Runnable runnable) {
        // One thread for each calling back.
        // Note: Guarantee ordering if the issue becomes important. Currently,
        // the chance of handling two callback events at a time is none.
        new Thread(runnable, "SipSessionCallbackThread").start();
    }

    public void onCalling(final ISipSession session) {
        if (mListener == null) return;
        proxy(new Runnable() {
            public void run() {
                try {
                    mListener.onCalling(session);
                } catch (Throwable t) {
                    handle(t, "onCalling()");
                }
            }
        });
    }

    public void onRinging(final ISipSession session, final SipProfile caller,
            final String sessionDescription) {
        if (mListener == null) return;
        proxy(new Runnable() {
            public void run() {
                try {
                    mListener.onRinging(session, caller, sessionDescription);
                } catch (Throwable t) {
                    handle(t, "onRinging()");
                }
            }
        });
    }

    public void onRingingBack(final ISipSession session) {
        if (mListener == null) return;
        proxy(new Runnable() {
            public void run() {
                try {
                    mListener.onRingingBack(session);
                } catch (Throwable t) {
                    handle(t, "onRingingBack()");
                }
            }
        });
    }

    public void onCallEstablished(final ISipSession session,
            final String sessionDescription) {
        if (mListener == null) return;
        proxy(new Runnable() {
            public void run() {
                try {
                    mListener.onCallEstablished(session, sessionDescription);
                } catch (Throwable t) {
                    handle(t, "onCallEstablished()");
                }
            }
        });
    }

    public void onCallEnded(final ISipSession session) {
        if (mListener == null) return;
        proxy(new Runnable() {
            public void run() {
                try {
                    mListener.onCallEnded(session);
                } catch (Throwable t) {
                    handle(t, "onCallEnded()");
                }
            }
        });
    }

    public void onCallBusy(final ISipSession session) {
        if (mListener == null) return;
        proxy(new Runnable() {
            public void run() {
                try {
                    mListener.onCallBusy(session);
                } catch (Throwable t) {
                    handle(t, "onCallBusy()");
                }
            }
        });
    }

    public void onCallChangeFailed(final ISipSession session,
            final int errorCode, final String message) {
        if (mListener == null) return;
        proxy(new Runnable() {
            public void run() {
                try {
                    mListener.onCallChangeFailed(session, errorCode, message);
                } catch (Throwable t) {
                    handle(t, "onCallChangeFailed()");
                }
            }
        });
    }

    public void onError(final ISipSession session, final int errorCode,
            final String message) {
        if (mListener == null) return;
        proxy(new Runnable() {
            public void run() {
                try {
                    mListener.onError(session, errorCode, message);
                } catch (Throwable t) {
                    handle(t, "onError()");
                }
            }
        });
    }

    public void onRegistering(final ISipSession session) {
        if (mListener == null) return;
        proxy(new Runnable() {
            public void run() {
                try {
                    mListener.onRegistering(session);
                } catch (Throwable t) {
                    handle(t, "onRegistering()");
                }
            }
        });
    }

    public void onRegistrationDone(final ISipSession session,
            final int duration) {
        if (mListener == null) return;
        proxy(new Runnable() {
            public void run() {
                try {
                    mListener.onRegistrationDone(session, duration);
                } catch (Throwable t) {
                    handle(t, "onRegistrationDone()");
                }
            }
        });
    }

    public void onRegistrationFailed(final ISipSession session,
            final int errorCode, final String message) {
        if (mListener == null) return;
        proxy(new Runnable() {
            public void run() {
                try {
                    mListener.onRegistrationFailed(session, errorCode, message);
                } catch (Throwable t) {
                    handle(t, "onRegistrationFailed()");
                }
            }
        });
    }

    public void onRegistrationTimeout(final ISipSession session) {
        if (mListener == null) return;
        proxy(new Runnable() {
            public void run() {
                try {
                    mListener.onRegistrationTimeout(session);
                } catch (Throwable t) {
                    handle(t, "onRegistrationTimeout()");
                }
            }
        });
    }

    private void handle(Throwable t, String message) {
        if (t instanceof DeadObjectException) {
            mListener = null;
            // This creates race but it's harmless. Just don't log the error
            // when it happens.
        } else if (mListener != null) {
            Log.w(TAG, message, t);
        }
    }
}
