/*
 * 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;

/**
 * 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("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 {@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);
        }
    }
}
