/*
 * 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 android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;

import java.io.ObjectStreamException;
import java.io.Serializable;
import java.text.ParseException;
import javax.sip.InvalidArgumentException;
import javax.sip.ListeningPoint;
import javax.sip.PeerUnavailableException;
import javax.sip.SipFactory;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI;
import javax.sip.address.URI;

/**
 * Defines a SIP profile, including a SIP account, domain and server information.
 * <p>You can create a {@link SipProfile} using {@link
 * SipProfile.Builder}. You can also retrieve one from a {@link SipSession}, using {@link
 * SipSession#getLocalProfile} and {@link SipSession#getPeerProfile}.</p>
 *
 * <div class="special reference">
 * <h3>Developer Guides</h3>
 * <p>For more information about using SIP, read the
 * <a href="{@docRoot}guide/topics/network/sip.html">Session Initiation Protocol</a>
 * developer guide.</p>
 * </div>
 * @deprecated {@link android.net.sip.SipManager} and associated classes are no longer supported and
 * should not be used as the basis of future VOIP apps.
 */
public class SipProfile implements Parcelable, Serializable, Cloneable {
    private static final long serialVersionUID = 1L;
    private static final int DEFAULT_PORT = 5060;
    private static final String TCP = "TCP";
    private static final String UDP = "UDP";
    private Address mAddress;
    private String mProxyAddress;
    private String mPassword;
    private String mDomain;
    private String mProtocol = UDP;
    private String mProfileName;
    private String mAuthUserName;
    private int mPort = DEFAULT_PORT;
    private boolean mSendKeepAlive = false;
    private boolean mAutoRegistration = true;
    private transient int mCallingUid = 0;

    public static final Parcelable.Creator<SipProfile> CREATOR =
            new Parcelable.Creator<SipProfile>() {
                public SipProfile createFromParcel(Parcel in) {
                    return new SipProfile(in);
                }

                public SipProfile[] newArray(int size) {
                    return new SipProfile[size];
                }
            };

    /**
     * Helper class for creating a {@link SipProfile}.
     */
    public static class Builder {
        private AddressFactory mAddressFactory;
        private SipProfile mProfile = new SipProfile();
        private SipURI mUri;
        private String mDisplayName;
        private String mProxyAddress;

        {
            try {
                mAddressFactory =
                        SipFactory.getInstance().createAddressFactory();
            } catch (PeerUnavailableException e) {
                throw new RuntimeException(e);
            }
        }

        /**
         * Creates a builder based on the given profile.
         */
        public Builder(SipProfile profile) {
            if (profile == null) throw new NullPointerException();
            try {
                mProfile = (SipProfile) profile.clone();
            } catch (CloneNotSupportedException e) {
                throw new RuntimeException("should not occur", e);
            }
            mProfile.mAddress = null;
            mUri = profile.getUri();
            mUri.setUserPassword(profile.getPassword());
            mDisplayName = profile.getDisplayName();
            mProxyAddress = profile.getProxyAddress();
            mProfile.mPort = profile.getPort();
        }

        /**
         * Constructor.
         *
         * @param uriString the URI string as "sip:<user_name>@<domain>"
         * @throws ParseException if the string is not a valid URI
         */
        public Builder(String uriString) throws ParseException {
            if (uriString == null) {
                throw new NullPointerException("uriString cannot be null");
            }
            URI uri = mAddressFactory.createURI(fix(uriString));
            if (uri instanceof SipURI) {
                mUri = (SipURI) uri;
            } else {
                throw new ParseException(uriString + " is not a SIP URI", 0);
            }
            mProfile.mDomain = mUri.getHost();
        }

        /**
         * Constructor.
         *
         * @param username username of the SIP account
         * @param serverDomain the SIP server domain; if the network address
         *      is different from the domain, use {@link #setOutboundProxy} to
         *      set server address
         * @throws ParseException if the parameters are not valid
         */
        public Builder(String username, String serverDomain)
                throws ParseException {
            if ((username == null) || (serverDomain == null)) {
                throw new NullPointerException(
                        "username and serverDomain cannot be null");
            }
            mUri = mAddressFactory.createSipURI(username, serverDomain);
            mProfile.mDomain = serverDomain;
        }

        private String fix(String uriString) {
            return (uriString.trim().toLowerCase().startsWith("sip:")
                    ? uriString
                    : "sip:" + uriString);
        }

        /**
         * Sets the username used for authentication.
         *
         * @param name authentication username of the profile
         * @return this builder object
         */
        public Builder setAuthUserName(String name) {
            mProfile.mAuthUserName = name;
            return this;
        }

        /**
         * Sets the name of the profile. This name is given by user.
         *
         * @param name name of the profile
         * @return this builder object
         */
        public Builder setProfileName(String name) {
            mProfile.mProfileName = name;
            return this;
        }

        /**
         * Sets the password of the SIP account
         *
         * @param password password of the SIP account
         * @return this builder object
         */
        public Builder setPassword(String password) {
            mUri.setUserPassword(password);
            return this;
        }

        /**
         * Sets the port number of the server. By default, it is 5060.
         *
         * @param port port number of the server
         * @return this builder object
         * @throws IllegalArgumentException if the port number is out of range
         */
        public Builder setPort(int port) throws IllegalArgumentException {
            if ((port > 65535) || (port < 1000)) {
                throw new IllegalArgumentException("incorrect port arugment: " + port);
            }
            mProfile.mPort = port;
            return this;
        }

        /**
         * Sets the protocol used to connect to the SIP server. Currently,
         * only "UDP" and "TCP" are supported.
         *
         * @param protocol the protocol string
         * @return this builder object
         * @throws IllegalArgumentException if the protocol is not recognized
         */
        public Builder setProtocol(String protocol)
                throws IllegalArgumentException {
            if (protocol == null) {
                throw new NullPointerException("protocol cannot be null");
            }
            protocol = protocol.toUpperCase();
            if (!protocol.equals(UDP) && !protocol.equals(TCP)) {
                throw new IllegalArgumentException(
                        "unsupported protocol: " + protocol);
            }
            mProfile.mProtocol = protocol;
            return this;
        }

        /**
         * Sets the outbound proxy of the SIP server.
         *
         * @param outboundProxy the network address of the outbound proxy
         * @return this builder object
         */
        public Builder setOutboundProxy(String outboundProxy) {
            mProxyAddress = outboundProxy;
            return this;
        }

        /**
         * Sets the display name of the user.
         *
         * @param displayName display name of the user
         * @return this builder object
         */
        public Builder setDisplayName(String displayName) {
            mDisplayName = displayName;
            return this;
        }

        /**
         * Sets the send keep-alive flag.
         *
         * @param flag true if sending keep-alive message is required,
         *      false otherwise
         * @return this builder object
         */
        public Builder setSendKeepAlive(boolean flag) {
            mProfile.mSendKeepAlive = flag;
            return this;
        }


        /**
         * Sets the auto. registration flag.
         *
         * @param flag true if the profile will be registered automatically,
         *      false otherwise
         * @return this builder object
         */
        public Builder setAutoRegistration(boolean flag) {
            mProfile.mAutoRegistration = flag;
            return this;
        }

        /**
         * Builds and returns the SIP profile object.
         *
         * @return the profile object created
         */
        public SipProfile build() {
            // remove password from URI
            mProfile.mPassword = mUri.getUserPassword();
            mUri.setUserPassword(null);
            try {
                if (!TextUtils.isEmpty(mProxyAddress)) {
                    SipURI uri = (SipURI)
                            mAddressFactory.createURI(fix(mProxyAddress));
                    mProfile.mProxyAddress = uri.getHost();
                } else {
                    if (!mProfile.mProtocol.equals(UDP)) {
                        mUri.setTransportParam(mProfile.mProtocol);
                    }
                    if (mProfile.mPort != DEFAULT_PORT) {
                        mUri.setPort(mProfile.mPort);
                    }
                }
                mProfile.mAddress = mAddressFactory.createAddress(
                        mDisplayName, mUri);
            } catch (InvalidArgumentException e) {
                throw new RuntimeException(e);
            } catch (ParseException e) {
                // must not occur
                throw new RuntimeException(e);
            }
            return mProfile;
        }
    }

    private SipProfile() {
    }

    private SipProfile(Parcel in) {
        mAddress = (Address) in.readSerializable();
        mProxyAddress = in.readString();
        mPassword = in.readString();
        mDomain = in.readString();
        mProtocol = in.readString();
        mProfileName = in.readString();
        mSendKeepAlive = (in.readInt() == 0) ? false : true;
        mAutoRegistration = (in.readInt() == 0) ? false : true;
        mCallingUid = in.readInt();
        mPort = in.readInt();
        mAuthUserName = in.readString();
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeSerializable(mAddress);
        out.writeString(mProxyAddress);
        out.writeString(mPassword);
        out.writeString(mDomain);
        out.writeString(mProtocol);
        out.writeString(mProfileName);
        out.writeInt(mSendKeepAlive ? 1 : 0);
        out.writeInt(mAutoRegistration ? 1 : 0);
        out.writeInt(mCallingUid);
        out.writeInt(mPort);
        out.writeString(mAuthUserName);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    /**
     * Gets the SIP URI of this profile.
     *
     * @return the SIP URI of this profile
     * @hide
     */
    public SipURI getUri() {
        return (SipURI) mAddress.getURI();
    }

    /**
     * Gets the SIP URI string of this profile.
     *
     * @return the SIP URI string of this profile
     */
    public String getUriString() {
        // We need to return the sip uri domain instead of
        // the SIP URI with transport, port information if
        // the outbound proxy address exists.
        if (!TextUtils.isEmpty(mProxyAddress)) {
            return "sip:" + getUserName() + "@" + mDomain;
        }
        return getUri().toString();
    }

    /**
     * Gets the SIP address of this profile.
     *
     * @return the SIP address of this profile
     * @hide
     */
    public Address getSipAddress() {
        return mAddress;
    }

    /**
     * Gets the display name of the user.
     *
     * @return the display name of the user
     */
    public String getDisplayName() {
        return mAddress.getDisplayName();
    }

    /**
     * Gets the username.
     *
     * @return the username
     */
    public String getUserName() {
        return getUri().getUser();
    }

    /**
     * Gets the username for authentication. If it is null, then the username
     * is used in authentication instead.
     *
     * @return the authentication username
     * @see #getUserName
     */
    public String getAuthUserName() {
        return mAuthUserName;
    }

    /**
     * Gets the password.
     *
     * @return the password
     */
    public String getPassword() {
        return mPassword;
    }

    /**
     * Gets the SIP domain.
     *
     * @return the SIP domain
     */
    public String getSipDomain() {
        return mDomain;
    }

    /**
     * Gets the port number of the SIP server.
     *
     * @return the port number of the SIP server
     */
    public int getPort() {
        return mPort;
    }

    /**
     * Gets the protocol used to connect to the server.
     *
     * @return the protocol
     */
    public String getProtocol() {
        return mProtocol;
    }

    /**
     * Gets the network address of the server outbound proxy.
     *
     * @return the network address of the server outbound proxy
     */
    public String getProxyAddress() {
        return mProxyAddress;
    }

    /**
     * Gets the (user-defined) name of the profile.
     *
     * @return name of the profile
     */
    public String getProfileName() {
        return mProfileName;
    }

    /**
     * Gets the flag of 'Sending keep-alive'.
     *
     * @return the flag of sending SIP keep-alive messages.
     */
    public boolean getSendKeepAlive() {
        return mSendKeepAlive;
    }

    /**
     * Gets the flag of 'Auto Registration'.
     *
     * @return the flag of registering the profile automatically.
     */
    public boolean getAutoRegistration() {
        return mAutoRegistration;
    }

    /**
     * Sets the calling process's Uid in the sip service.
     */
    public void setCallingUid(int uid) {
        mCallingUid = uid;
    }

    /**
     * Gets the calling process's Uid in the sip settings.
     *
     * @return the calling process's Uid in the sip settings.
     * @hide
     */
    @SystemApi
    public int getCallingUid() {
        return mCallingUid;
    }

    private Object readResolve() throws ObjectStreamException {
        // For compatibility.
        if (mPort == 0) mPort = DEFAULT_PORT;
        return this;
    }
}
