/*
 * 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 java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;

/**
 * An object used to manipulate messages of Session Description Protocol (SDP).
 * It is mainly designed for the uses of Session Initiation Protocol (SIP).
 * Therefore, it only handles connection addresses ("c="), bandwidth limits,
 * ("b="), encryption keys ("k="), and attribute fields ("a="). Currently this
 * implementation does not support multicast sessions.
 *
 * <p>Here is an example code to create a session description.</p>
 * <pre>
 * SimpleSessionDescription description = new SimpleSessionDescription(
 *     System.currentTimeMillis(), "1.2.3.4");
 * Media media = description.newMedia("audio", 56789, 1, "RTP/AVP");
 * media.setRtpPayload(0, "PCMU/8000", null);
 * media.setRtpPayload(8, "PCMA/8000", null);
 * media.setRtpPayload(127, "telephone-event/8000", "0-15");
 * media.setAttribute("sendrecv", "");
 * </pre>
 * <p>Invoking <code>description.encode()</code> will produce a result like the
 * one below.</p>
 * <pre>
 * v=0
 * o=- 1284970442706 1284970442709 IN IP4 1.2.3.4
 * s=-
 * c=IN IP4 1.2.3.4
 * t=0 0
 * m=audio 56789 RTP/AVP 0 8 127
 * a=rtpmap:0 PCMU/8000
 * a=rtpmap:8 PCMA/8000
 * a=rtpmap:127 telephone-event/8000
 * a=fmtp:127 0-15
 * a=sendrecv
 * </pre>
 * @hide
 */
public class SimpleSessionDescription {
    private final Fields mFields = new Fields("voscbtka");
    private final ArrayList<Media> mMedia = new ArrayList<Media>();

    /**
     * Creates a minimal session description from the given session ID and
     * unicast address. The address is used in the origin field ("o=") and the
     * connection field ("c="). See {@link SimpleSessionDescription} for an
     * example of its usage.
     */
    public SimpleSessionDescription(long sessionId, String address) {
        address = (address.indexOf(':') < 0 ? "IN IP4 " : "IN IP6 ") + address;
        mFields.parse("v=0");
        mFields.parse(String.format(Locale.US, "o=- %d %d %s", sessionId,
                System.currentTimeMillis(), address));
        mFields.parse("s=-");
        mFields.parse("t=0 0");
        mFields.parse("c=" + address);
    }

    /**
     * Creates a session description from the given message.
     *
     * @throws IllegalArgumentException if message is invalid.
     */
    public SimpleSessionDescription(String message) {
        String[] lines = message.trim().replaceAll(" +", " ").split("[\r\n]+");
        Fields fields = mFields;

        for (String line : lines) {
            try {
                if (line.charAt(1) != '=') {
                    throw new IllegalArgumentException();
                }
                if (line.charAt(0) == 'm') {
                    String[] parts = line.substring(2).split(" ", 4);
                    String[] ports = parts[1].split("/", 2);
                    Media media = newMedia(parts[0], Integer.parseInt(ports[0]),
                            (ports.length < 2) ? 1 : Integer.parseInt(ports[1]),
                            parts[2]);
                    for (String format : parts[3].split(" ")) {
                        media.setFormat(format, null);
                    }
                    fields = media;
                } else {
                    fields.parse(line);
                }
            } catch (Exception e) {
                throw new IllegalArgumentException("Invalid SDP: " + line);
            }
        }
    }

    /**
     * Creates a new media description in this session description.
     *
     * @param type The media type, e.g. {@code "audio"}.
     * @param port The first transport port used by this media.
     * @param portCount The number of contiguous ports used by this media.
     * @param protocol The transport protocol, e.g. {@code "RTP/AVP"}.
     */
    public Media newMedia(String type, int port, int portCount,
            String protocol) {
        Media media = new Media(type, port, portCount, protocol);
        mMedia.add(media);
        return media;
    }

    /**
     * Returns all the media descriptions in this session description.
     */
    public Media[] getMedia() {
        return mMedia.toArray(new Media[mMedia.size()]);
    }

    /**
     * Encodes the session description and all its media descriptions in a
     * string. Note that the result might be incomplete if a required field
     * has never been added before.
     */
    public String encode() {
        StringBuilder buffer = new StringBuilder();
        mFields.write(buffer);
        for (Media media : mMedia) {
            media.write(buffer);
        }
        return buffer.toString();
    }

    /**
     * Returns the connection address or {@code null} if it is not present.
     */
    public String getAddress() {
        return mFields.getAddress();
    }

    /**
     * Sets the connection address. The field will be removed if the address
     * is {@code null}.
     */
    public void setAddress(String address) {
        mFields.setAddress(address);
    }

    /**
     * Returns the encryption method or {@code null} if it is not present.
     */
    public String getEncryptionMethod() {
        return mFields.getEncryptionMethod();
    }

    /**
     * Returns the encryption key or {@code null} if it is not present.
     */
    public String getEncryptionKey() {
        return mFields.getEncryptionKey();
    }

    /**
     * Sets the encryption method and the encryption key. The field will be
     * removed if the method is {@code null}.
     */
    public void setEncryption(String method, String key) {
        mFields.setEncryption(method, key);
    }

    /**
     * Returns the types of the bandwidth limits.
     */
    public String[] getBandwidthTypes() {
        return mFields.getBandwidthTypes();
    }

    /**
     * Returns the bandwidth limit of the given type or {@code -1} if it is not
     * present.
     */
    public int getBandwidth(String type) {
        return mFields.getBandwidth(type);
    }

    /**
     * Sets the bandwith limit for the given type. The field will be removed if
     * the value is negative.
     */
    public void setBandwidth(String type, int value) {
        mFields.setBandwidth(type, value);
    }

    /**
     * Returns the names of all the attributes.
     */
    public String[] getAttributeNames() {
        return mFields.getAttributeNames();
    }

    /**
     * Returns the attribute of the given name or {@code null} if it is not
     * present.
     */
    public String getAttribute(String name) {
        return mFields.getAttribute(name);
    }

    /**
     * Sets the attribute for the given name. The field will be removed if
     * the value is {@code null}. To set a binary attribute, use an empty
     * string as the value.
     */
    public void setAttribute(String name, String value) {
        mFields.setAttribute(name, value);
    }

    /**
     * This class represents a media description of a session description. It
     * can only be created by {@link SimpleSessionDescription#newMedia}. Since
     * the syntax is more restricted for RTP based protocols, two sets of access
     * methods are implemented. See {@link SimpleSessionDescription} for an
     * example of its usage.
     */
    public static class Media extends Fields {
        private final String mType;
        private final int mPort;
        private final int mPortCount;
        private final String mProtocol;
        private ArrayList<String> mFormats = new ArrayList<String>();

        private Media(String type, int port, int portCount, String protocol) {
            super("icbka");
            mType = type;
            mPort = port;
            mPortCount = portCount;
            mProtocol = protocol;
        }

        /**
         * Returns the media type.
         */
        public String getType() {
            return mType;
        }

        /**
         * Returns the first transport port used by this media.
         */
        public int getPort() {
            return mPort;
        }

        /**
         * Returns the number of contiguous ports used by this media.
         */
        public int getPortCount() {
            return mPortCount;
        }

        /**
         * Returns the transport protocol.
         */
        public String getProtocol() {
            return mProtocol;
        }

        /**
         * Returns the media formats.
         */
        public String[] getFormats() {
            return mFormats.toArray(new String[mFormats.size()]);
        }

        /**
         * Returns the {@code fmtp} attribute of the given format or
         * {@code null} if it is not present.
         */
        public String getFmtp(String format) {
            return super.get("a=fmtp:" + format, ' ');
        }

        /**
         * Sets a format and its {@code fmtp} attribute. If the attribute is
         * {@code null}, the corresponding field will be removed.
         */
        public void setFormat(String format, String fmtp) {
            mFormats.remove(format);
            mFormats.add(format);
            super.set("a=rtpmap:" + format, ' ', null);
            super.set("a=fmtp:" + format, ' ', fmtp);
        }

        /**
         * Removes a format and its {@code fmtp} attribute.
         */
        public void removeFormat(String format) {
            mFormats.remove(format);
            super.set("a=rtpmap:" + format, ' ', null);
            super.set("a=fmtp:" + format, ' ', null);
        }

        /**
         * Returns the RTP payload types.
         */
        public int[] getRtpPayloadTypes() {
            int[] types = new int[mFormats.size()];
            int length = 0;
            for (String format : mFormats) {
                try {
                    types[length] = Integer.parseInt(format);
                    ++length;
                } catch (NumberFormatException e) { }
            }
            return Arrays.copyOf(types, length);
        }

        /**
         * Returns the {@code rtpmap} attribute of the given RTP payload type
         * or {@code null} if it is not present.
         */
        public String getRtpmap(int type) {
            return super.get("a=rtpmap:" + type, ' ');
        }

        /**
         * Returns the {@code fmtp} attribute of the given RTP payload type or
         * {@code null} if it is not present.
         */
        public String getFmtp(int type) {
            return super.get("a=fmtp:" + type, ' ');
        }

        /**
         * Sets a RTP payload type and its {@code rtpmap} and {@code fmtp}
         * attributes. If any of the attributes is {@code null}, the
         * corresponding field will be removed. See
         * {@link SimpleSessionDescription} for an example of its usage.
         */
        public void setRtpPayload(int type, String rtpmap, String fmtp) {
            String format = String.valueOf(type);
            mFormats.remove(format);
            mFormats.add(format);
            super.set("a=rtpmap:" + format, ' ', rtpmap);
            super.set("a=fmtp:" + format, ' ', fmtp);
        }

        /**
         * Removes a RTP payload and its {@code rtpmap} and {@code fmtp}
         * attributes.
         */
        public void removeRtpPayload(int type) {
            removeFormat(String.valueOf(type));
        }

        private void write(StringBuilder buffer) {
            buffer.append("m=").append(mType).append(' ').append(mPort);
            if (mPortCount != 1) {
                buffer.append('/').append(mPortCount);
            }
            buffer.append(' ').append(mProtocol);
            for (String format : mFormats) {
                buffer.append(' ').append(format);
            }
            buffer.append("\r\n");
            super.write(buffer);
        }
    }

    /**
     * This class acts as a set of fields, and the size of the set is expected
     * to be small. Therefore, it uses a simple list instead of maps. Each field
     * has three parts: a key, a delimiter, and a value. Delimiters are special
     * because they are not included in binary attributes. As a result, the
     * private methods, which are the building blocks of this class, all take
     * the delimiter as an argument.
     */
    private static class Fields {
        private final String mOrder;
        private final ArrayList<String> mLines = new ArrayList<String>();

        Fields(String order) {
            mOrder = order;
        }

        /**
         * Returns the connection address or {@code null} if it is not present.
         */
        public String getAddress() {
            String address = get("c", '=');
            if (address == null) {
                return null;
            }
            String[] parts = address.split(" ");
            if (parts.length != 3) {
                return null;
            }
            int slash = parts[2].indexOf('/');
            return (slash < 0) ? parts[2] : parts[2].substring(0, slash);
        }

        /**
         * Sets the connection address. The field will be removed if the address
         * is {@code null}.
         */
        public void setAddress(String address) {
            if (address != null) {
                address = (address.indexOf(':') < 0 ? "IN IP4 " : "IN IP6 ") +
                        address;
            }
            set("c", '=', address);
        }

        /**
         * Returns the encryption method or {@code null} if it is not present.
         */
        public String getEncryptionMethod() {
            String encryption = get("k", '=');
            if (encryption == null) {
                return null;
            }
            int colon = encryption.indexOf(':');
            return (colon == -1) ? encryption : encryption.substring(0, colon);
        }

        /**
         * Returns the encryption key or {@code null} if it is not present.
         */
        public String getEncryptionKey() {
            String encryption = get("k", '=');
            if (encryption == null) {
                return null;
            }
            int colon = encryption.indexOf(':');
            return (colon == -1) ? null : encryption.substring(0, colon + 1);
        }

        /**
         * Sets the encryption method and the encryption key. The field will be
         * removed if the method is {@code null}.
         */
        public void setEncryption(String method, String key) {
            set("k", '=', (method == null || key == null) ?
                    method : method + ':' + key);
        }

        /**
         * Returns the types of the bandwidth limits.
         */
        public String[] getBandwidthTypes() {
            return cut("b=", ':');
        }

        /**
         * Returns the bandwidth limit of the given type or {@code -1} if it is
         * not present.
         */
        public int getBandwidth(String type) {
            String value = get("b=" + type, ':');
            if (value != null) {
                try {
                    return Integer.parseInt(value);
                } catch (NumberFormatException e) { }
                setBandwidth(type, -1);
            }
            return -1;
        }

        /**
         * Sets the bandwith limit for the given type. The field will be removed
         * if the value is negative.
         */
        public void setBandwidth(String type, int value) {
            set("b=" + type, ':', (value < 0) ? null : String.valueOf(value));
        }

        /**
         * Returns the names of all the attributes.
         */
        public String[] getAttributeNames() {
            return cut("a=", ':');
        }

        /**
         * Returns the attribute of the given name or {@code null} if it is not
         * present.
         */
        public String getAttribute(String name) {
            return get("a=" + name, ':');
        }

        /**
         * Sets the attribute for the given name. The field will be removed if
         * the value is {@code null}. To set a binary attribute, use an empty
         * string as the value.
         */
        public void setAttribute(String name, String value) {
            set("a=" + name, ':', value);
        }

        private void write(StringBuilder buffer) {
            for (int i = 0; i < mOrder.length(); ++i) {
                char type = mOrder.charAt(i);
                for (String line : mLines) {
                    if (line.charAt(0) == type) {
                        buffer.append(line).append("\r\n");
                    }
                }
            }
        }

        /**
         * Invokes {@link #set} after splitting the line into three parts.
         */
        private void parse(String line) {
            char type = line.charAt(0);
            if (mOrder.indexOf(type) == -1) {
                return;
            }
            char delimiter = '=';
            if (line.startsWith("a=rtpmap:") || line.startsWith("a=fmtp:")) {
                delimiter = ' ';
            } else if (type == 'b' || type == 'a') {
                delimiter = ':';
            }
            int i = line.indexOf(delimiter);
            if (i == -1) {
                set(line, delimiter, "");
            } else {
                set(line.substring(0, i), delimiter, line.substring(i + 1));
            }
        }

        /**
         * Finds the key with the given prefix and returns its suffix.
         */
        private String[] cut(String prefix, char delimiter) {
            String[] names = new String[mLines.size()];
            int length = 0;
            for (String line : mLines) {
                if (line.startsWith(prefix)) {
                    int i = line.indexOf(delimiter);
                    if (i == -1) {
                        i = line.length();
                    }
                    names[length] = line.substring(prefix.length(), i);
                    ++length;
                }
            }
            return Arrays.copyOf(names, length);
        }

        /**
         * Returns the index of the key.
         */
        private int find(String key, char delimiter) {
            int length = key.length();
            for (int i = mLines.size() - 1; i >= 0; --i) {
                String line = mLines.get(i);
                if (line.startsWith(key) && (line.length() == length ||
                        line.charAt(length) == delimiter)) {
                    return i;
                }
            }
            return -1;
        }

        /**
         * Sets the key with the value or removes the key if the value is
         * {@code null}.
         */
        private void set(String key, char delimiter, String value) {
            int index = find(key, delimiter);
            if (value != null) {
                if (value.length() != 0) {
                    key = key + delimiter + value;
                }
                if (index == -1) {
                    mLines.add(key);
                } else {
                    mLines.set(index, key);
                }
            } else if (index != -1) {
                mLines.remove(index);
            }
        }

        /**
         * Returns the value of the key.
         */
        private String get(String key, char delimiter) {
            int index = find(key, delimiter);
            if (index == -1) {
                return null;
            }
            String line = mLines.get(index);
            int length = key.length();
            return (line.length() == length) ? "" : line.substring(length + 1);
        }
    }
}
