context: //
  // Mono.Google.Picasa.PicasaPicture.cs:
  //
  // Authors:
  //	Gonzalo Paniagua Javier (gonzalo@ximian.com)
  //	Stephane Delcroix (stephane@delcroix.org)
  //
  // (C) Copyright 2006 Novell, Inc. (http://www.novell.com)
  // (C) Copyright 2007 S. Delcroix
  //
  
  // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  // 
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  
  using System;
  using System.IO;
  using System.Net;
  using System.Text;
  using System.Xml;
  using System.Globalization;
  
  namespace Mono.Google.Picasa {
  	public class PicasaPicture {
  		GoogleConnection conn;
  		PicasaAlbum album;
  		string title;
  		string description;
  		DateTime pub_date;
  		string thumbnail_url;
  		string image_url;
  		int width;
  		int height;
  		int index;
  		string id;
  		string link;
  		string tags;
  
  		internal PicasaPicture (GoogleConnection conn, PicasaAlbum album, XmlNode nodeitem, XmlNamespaceManager nsmgr)
  		{
  			this.conn = conn;
  			this.album = album;
  			ParsePicture (nodeitem, nsmgr);
  		}
  
  		public PicasaPicture (GoogleConnection conn, string aid, string pid)
  		{
  			if (conn == null)
  				throw new ArgumentNullException ("conn");
  			if (conn.User == null)
  				throw new ArgumentException ("Need authentication before being used.", "conn");
  			this.conn = conn;
  
  			if (aid == null || aid == String.Empty)
  				throw new ArgumentNullException ("aid");			
  			this.album = new PicasaAlbum (conn, aid);
  
  			if (pid == null || pid == String.Empty)
  				throw new ArgumentNullException ("pid");			
  
  			string received = conn.DownloadString (GDataApi.GetPictureEntry (conn.User, aid, pid));
  			XmlDocument doc = new XmlDocument ();
  			doc.LoadXml (received);
  			XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
  			XmlUtil.AddDefaultNamespaces (nsmgr);
  			XmlNode entry = doc.SelectSingleNode ("atom:entry", nsmgr);
  			ParsePicture (entry, nsmgr);
  		}
  
  		private void ParsePicture (XmlNode nodeitem, XmlNamespaceManager nsmgr)
  		{
  			title = nodeitem.SelectSingleNode ("atom:title", nsmgr).InnerText;
  			foreach (XmlNode xlink in nodeitem.SelectNodes ("atom:link", nsmgr)) {
  				if (xlink.Attributes.GetNamedItem ("rel").Value == "alternate") {
  					link = xlink.Attributes.GetNamedItem ("href").Value;
  					break;
  				}
  			}
  			description = nodeitem.SelectSingleNode ("media:group/media:description", nsmgr).InnerText;
  			CultureInfo info = CultureInfo.InvariantCulture;
  			pub_date = DateTime.ParseExact (nodeitem.SelectSingleNode ("atom:published", nsmgr).InnerText, GDataApi.DateFormat, info);
  			thumbnail_url = nodeitem.SelectSingleNode ("media:group/media:thumbnail", nsmgr).Attributes.GetNamedItem ("url").Value;
  			image_url = nodeitem.SelectSingleNode ("media:group/media:content", nsmgr).Attributes.GetNamedItem ("url").Value;
  			width = (int) UInt32.Parse (nodeitem.SelectSingleNode ("gphoto:width", nsmgr).InnerText);
  			height = (int) UInt32.Parse (nodeitem.SelectSingleNode ("gphoto:height", nsmgr).InnerText);
  
  			XmlNode node = nodeitem.SelectSingleNode ("gphoto:index", nsmgr);
  			index = (node != null) ? (int) UInt32.Parse (node.InnerText) : -1;
  			node = nodeitem.SelectSingleNode ("gphoto:id", nsmgr);
  			id = (node != null) ? node.InnerText : "auto" + title.GetHashCode ().ToString ();
  			tags = nodeitem.SelectSingleNode ("media:group/media:keywords", nsmgr).InnerText;
  		}
  
  		static string GetXmlForTagging (string tag)
  		{
  			XmlUtil xml = new XmlUtil ();
  			xml.WriteElementString ("title", tag);
  			xml.WriteElementStringWithAttributes ("category", null,
  					"scheme", "http://schemas.google.com/g/2005#kind", 
  					"term", "http://schemas.google.com/photos/2007#tag");
  			return xml.GetDocumentString ();
  		
  		}
  
  		public void AddTag (string tag)
  		{
  			if (tag == null)
  				throw new ArgumentNullException ("title");
  
  			string op_string = GetXmlForTagging (tag);
  			byte [] op_bytes = Encoding.UTF8.GetBytes (op_string);
  			string url = GDataApi.GetPictureFeed (conn.User, album.UniqueID, UniqueID);
  			HttpWebRequest request = conn.AuthenticatedRequest (url);
  			request.ContentType = "application/atom+xml; charset=UTF-8";
  			request.Method = "POST";
  			Stream output_stream = request.GetRequestStream ();
  			output_stream.Write (op_bytes, 0, op_bytes.Length);
  			output_stream.Close ();
  
  			HttpWebResponse response = (HttpWebResponse) request.GetResponse ();
  			string received = "";
  			using (Stream stream = response.GetResponseStream ()) {
  				StreamReader sr = new StreamReader (stream, Encoding.UTF8);
  				received = sr.ReadToEnd ();
  			}
  			response.Close ();
  	
  		}
  
  		public void DownloadToStream (Stream stream)
  		{
  			conn.DownloadToStream (image_url, stream);
  		}
  
  		public void DownloadThumbnailToStream (Stream stream)
  		{
  			conn.DownloadToStream (thumbnail_url, stream);
  		}
  
  		public PicasaAlbum Album {
  			get { return album; }
  		}
  
  		public string Title {
  			get { return title; }
  		}
  
  		public string Description {
  			get { return description; }
  		}
  
  		public DateTime Date {
  			get { return pub_date; }
  		}
  
  		public string ThumbnailURL {
  			get { return thumbnail_url; }
  		}
  
  		public string ImageURL {
  			get { return image_url; }
  		}
  
  		public int Width {
  			get { return width; }
  		}
  
  		public int Height {
  			get { return height; }
  		}
  
  		public int Index {
  			get { return index; }
  		}
  
  		public string UniqueID {
  			get { return id; }
  		}
  
  		public string Link {
  			get { return link; }
  		}
  
  		public string Tags {
  
gt: 			get { return tags; }