/*
 * Copyright (C) 2008 OpenedHand Ltd.
 * Copyright (C) 2009,2010 Nokia Corporation.
 * Copyright (C) 2012,2013 Intel Corporation.
 * Copyright (C) 2013 Cable Television Laboratories, Inc.
 *
 * Author: Jorn Baayen <jorn@openedhand.com>
 *         Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
 *                               <zeeshan.ali@nokia.com>
 *         Sivakumar Mani <siva@orexel.com>
 *
 * Rygel is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * Rygel is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

/**
 * This interface maps UPnP AVTransport:2 methods to the plugin's specific implementation.
 *
 * This interface is useful only when implementing Rygel renderer plugins.
 * Instances of this interface are retrieved from
 * rygel_media_renderer_plugin_get_player().
 */
public interface Rygel.MediaPlayer : GLib.Object {

    /* TODO: Use an enum instead. */
    /// The state as a UPnP playback state string such as PAUSED_PLAYBACK, "STOPPED" or "PLAYING"
    public abstract string playback_state { owned get; set; }

    /// The allowed playback speeds as UPnP playback speeds such as
    /// "-4","-2","-1","-1/2","1/2","1","2","4"
    public abstract string[] allowed_playback_speeds { owned get; }

    /// The current media playback speed as UPnP playback speed
    public abstract string playback_speed { owned get; set; }

    /// The URI of the current media.
    public abstract string? uri { owned get; set; }

    /// The volume as a value between 0.0 and 1.0
    public abstract double volume { get; set; }

    /// Duration of the current media in microseconds
    public abstract int64 duration { get; }

    /// Size of the current media in bytes
    public abstract int64 size { get; }

    /**
     * A DIDLLite document describing the current media URI or null.
     * The document is either the one received from a UPnP control point or
     * one generated by the implementing class.
     */
    public abstract string? metadata { owned get; set; }

    /// The mime-type of the currently-playing media
    public abstract string? mime_type { owned get; set; }

    /// The current media supports time-based seeking
    public abstract bool can_seek { get; }

    /// The current media supports byte-based seeking
    public abstract bool can_seek_bytes { get; }

    /**
     * The contents of the contentFeatures.dlna.org HTTP header,
     * containing the 4th field of the protocol info for the current
     * media URI. Or null if the header does not exist or the media
     * does not have DLNA information attached.
     */
    public abstract string? content_features { owned get; set; }

    /// The duration as a human-readable string, in HH:MM:SS format
    public string duration_as_str {
        owned get {
            return TimeUtils.time_to_string (duration);
        }
    }

    /// Position in the current media in microseconds
    public abstract int64 position { get; }

    ///Position in the current media in bytes
    public abstract int64 byte_position { get; }

    /// The position as a human-readable string, in HH:MM:SS format
    public string position_as_str {
        owned get {
            return TimeUtils.time_to_string (position);
        }
    }

    /// The User-Agent header to use in HTTP requests
    public abstract string? user_agent { owned get; set; }

    /**
     * Seek to a point in the current media that is
     * this many microseconds after the start.
     */
    public abstract bool seek (int64 time);

    /**
     * Seek to a byte position in the current media.
     */
    public abstract bool seek_bytes (int64 bytes);

    /**
     * Return the protocols supported by this renderer,
     * such as "http-get" and "rtsp".
     */
    public abstract string[] get_protocols ();

    /// Return the MIME types supported by this renderer.
    /// The mime types in this list should be all lowercase.
    public abstract string[] get_mime_types ();

    /**
     * Transform a fractional playspeed (e.g. "-1/4") to double.
     * Input values are expected to be valid rational numbers.
     */
    protected double play_speed_to_double (string speed)
    {
         string[] rational = speed.split ("/", 2);

         assert (rational[0] != "0");

         if (rational[1] == null) {
             return double.parse (rational[0]);
         }

         assert (rational[1] != "0");

         return double.parse (rational[0]) / double.parse (rational[1]);
    }
    
    /// Return the protocol info of the current track's meta-data
    public string protocol_info {
        owned get {
            if (this.metadata == null || this.uri == null) {
                return "";
            }

            // Parse meta-data
            var p = new GUPnP.DIDLLiteParser ();
            GUPnP.DIDLLiteObject item = null;

            p.item_available.connect ( (object) => { item = object; });
            try {
                p.parse_didl (this.metadata);
            } catch (Error error) {
                return "";
            }

            var resources = item.get_resources ();
            foreach (var resource in resources) {
                if (resource.uri == this.uri) {
                    return resource.protocol_info.to_string ();
                }
            }

            return "";
        }
    }
}
