context: // Copyright (C) 2010-2012  Simon Mika <simon@mika.se>
  //
  // This file is part of Kean.
  //
  // Kean 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 3 of the License, or
  // (at your option) any later version.
  //
  // Kean 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 Kean.  If not, see <http://www.gnu.org/licenses/>.
  //
  
  
  using System;
  using Kean.Extension;
  using Kean.Collection.Extension;
  
  namespace Kean.Uri
  {
  	public class Path :
  		Collection.Linked.List<PathLink, string>,
  		IEquatable<Path>
  	{
  		#region IString Members
  		public string String
  		{
  			get
  			{
  				string result = "";
  				PathLink tail = this.Last;
  				while (tail.NotNull())
  				{
  					result = "/" + tail.Head.PercentEncode(' ', '%', '/', '#', '?') + result;
  					tail = tail.Tail;
  				}
  				if (result.StartsWith("/."))
  					result = result.TrimStart('/');
  				return result;
  			}
  			set
  			{
  				PathLink tail = null;
  				if (value.NotNull())
  					foreach (string folder in value.TrimStart('/').Split('/'))
  						tail = new PathLink(folder.PercentDecode(), tail);
  				this.Last = tail;
  			}
  		}
  		#endregion
  		public string PlatformPath
  		{
  			get
  			{
  				string result = "";
  				PathLink tail = this.Last;
  				if (tail.NotNull())
  				{
  					string name;
  					while (tail.NotNull())
  					{
  						name = tail.Head ?? "";
  						if (tail.Tail.IsNull() && name.EndsWith(":"))
  							name += System.IO.Path.DirectorySeparatorChar;
  						result = System.IO.Path.Combine(name, result);
  						tail = tail.Tail;
  					}
  					if (System.IO.Path.DirectorySeparatorChar == '/' && !result.StartsWith("."))
  						result = System.IO.Path.DirectorySeparatorChar + result;
  				}
  				return result;
  			}
  			set
  			{
  				if (value.NotEmpty() && (value[0] == System.IO.Path.DirectorySeparatorChar || value[0] == System.IO.Path.AltDirectorySeparatorChar))
  					value = value.Substring(1);
  				PathLink tail = null;
  				if (value.NotNull())
  					foreach (string folder in value.Split(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar))
  						tail = new PathLink(folder, tail);
  				this.Last = tail;
  			}
  		}
  		public bool Empty { get { return this.Last.IsNull(); } }
  		public bool Folder { get { return this.Last.NotNull() && this.Last.Head.IsEmpty(); } }
  		public Path FolderPath { get { return this.Last.NotNull() ? new Path(this.Last.Tail) : new Path(); } }
  		public string Stem
  		{
  			get { return this.Last.NotNull() ? this.Last.Head.Get(0, -this.Extension.Length - 1) : null; }
  			set
  			{
  				if (this.Last.NotNull())
  					this.Last = new PathLink();
  				this.Last.Head = value + "." + this.Extension;
  			}
  		}
  		public string Filename
  		{
  			get { return this.Last.NotNull() ? this.Last.Head : null; }
  			set
  			{
  				if (this.Last.NotNull())
  					this.Last = new PathLink();
  				this.Last.Head = value;
  			}
  		}
  		public string Extension
  		{
  			get { return this.Last.NotNull() ? this.Last.Head.Split('.').Skip(1).Last() : null; }
  			set
  			{
  				if (this.Last.NotNull())
  					this.Last = new PathLink();
  				this.Last.Head = this.Stem + "." + value;
  			}
  		}
  		/// <summary>
  		/// Deduces the MIME type from the extension.
  		/// </summary>
  		/// <value>The MIME type if.</value>
  		public string Mime
  		{
  			get
  			{
  				string result;
  				switch (this.Extension)
  				{
  					#region extension - mime mapping
  					case "323":
  						result = "text/h323";
  						break;
  					case "3dmf":
  						result = "x-world/x-3dmf";
  						break;
  					case "3dm":
  						result = "x-world/x-3dmf";
  						break;
  					case "aab":
  						result = "application/x-authorware-bin";
  						break;
  					case "aam":
  						result = "application/x-authorware-map";
  						break;
  					case "aas":
  						result = "application/x-authorware-seg";
  						break;
  					case "abc":
  						result = "text/vnd.abc";
  						break;
  					case "acgi":
  						result = "text/html";
  						break;
  					case "acx":
  						result = "application/internet-property-stream";
  						break;
  					case "afl":
  						result = "video/animaflex";
  						break;
  					case "ai":
  						result = "application/postscript";
  						break;
  					case "aif":
  						result = "audio/aiff";
  						break;
  					case "aifc":
  						result = "audio/aiff";
  						break;
  					case "aiff":
  						result = "audio/aiff";
  						break;
  					case "aim":
  						result = "application/x-aim";
  						break;
  					case "aip":
  						result = "text/x-audiosoft-intra";
  						break;
  					case "ani":
  						result = "application/x-navi-animation";
  						break;
  					case "aos":
  						result = "application/x-nokia-9000-communicator-add-on-software";
  						break;
  					case "application":
  						result = "application/x-ms-application";
  						break;
  					case "aps":
  						result = "application/mime";
  						break;
  					case "art":
  						result = "image/x-jg";
  						break;
  					case "asf":
  						result = "video/x-ms-asf";
  						break;
  					case "asm":
  						result = "text/x-asm";
  						break;
  					case "asp":
  						result = "text/asp";
  						break;
  					case "asr":
  						result = "video/x-ms-asf";
  						break;
  					case "asx":
  						result = "application/x-mplayer2";
  						break;
  					case "au":
  						result = "audio/x-au";
  						break;
  					case "avi":
  						result = "video/avi";
  						break;
  					case "avs":
  						result = "video/avs-video";
  						break;
  					case "axs":
  						result = "application/olescript";
  						break;
  					case "bas":
  						result = "text/plain";
  						break;
  					case "bcpio":
  						result = "application/x-bcpio";
  						break;
  					case "bin":
  						result = "application/octet-stream";
  						break;
  					case "bm":
  						result = "image/bmp";
  						break;
  					case "bmp":
  						result = "image/bmp";
  						break;
  					case "boo":
  						result = "application/book";
  						break;
  					case "book":
  						result = "application/book";
  						break;
  					case "boz":
  						result = "application/x-bzip2";
  						break;
  					case "bsh":
  						result = "application/x-bsh";
  						break;
  					case "bz2":
  						result = "application/x-bzip2";
  						break;
  					case "bz":
  						result = "application/x-bzip";
  						break;
  					case "cat":
  						result = "application/vnd.ms-pki.seccat";
  						break;
  					case "ccad":
  						result = "application/clariscad";
  						break;
  					case "cco":
  						result = "application/x-cocoa";
  						break;
  					case "cc":
  						result = "text/plain";
  						break;
  					case "cdf":
  						result = "application/cdf";
  						break;
  					case "cer":
  						result = "application/pkix-cert";
  						break;
  					case "cha":
  						result = "application/x-chat";
  						break;
  					case "chat":
  						result = "application/x-chat";
  						break;
  					case "class":
  						result = "application/java";
  						break;
  					case "clp":
  						result = "application/x-msclip";
  						break;
  					case "cmx":
  						result = "image/x-cmx";
  						break;
  					case "cod":
  						result = "image/cis-cod";
  						break;
  					case "conf":
  						result = "text/plain";
  						break;
  					case "cpio":
  						result = "application/x-cpio";
  						break;
  					case "cpp":
  						result = "text/plain";
  						break;
  					case "cpt":
  						result = "application/x-cpt";
  						break;
  					case "crd":
  						result = "application/x-mscardfile";
  						break;
  					case "crl":
  						result = "application/pkix-crl";
  						break;
  					case "crt":
  						result = "application/pkix-cert";
  						break;
  					case "csh":
  						result = "application/x-csh";
  						break;
  					case "css":
  						result = "text/css";
  						break;
  					case "c":
  						result = "text/plain";
  						break;
  					case "c++":
  						result = "text/plain";
  						break;
  					case "cxx":
  						result = "text/plain";
  						break;
  					case "dcr":
  						result = "application/x-director";
  						break;
  					case "deepv":
  						result = "application/x-deepv";
  						break;
  					case "def":
  						result = "text/plain";
  						break;
  					case "deploy":
  						result = "application/octet-stream";
  						break;
  					case "der":
  						result = "application/x-x509-ca-cert";
  						break;
  					case "dib":
  						result = "image/bmp";
  						break;
  					case "dif":
  						result = "video/x-dv";
  						break;
  					case "dir":
  						result = "application/x-director";
  						break;
  					case "disco":
  						result = "text/xml";
  						break;
  					case "dll":
  						result = "application/x-msdownload";
  						break;
  					case "dl":
  						result = "video/dl";
  						break;
  					case "doc":
  						result = "application/msword";
  						break;
  					case "dot":
  						result = "application/msword";
  						break;
  					case "dp":
  						result = "application/commonground";
  						break;
  					case "drw":
  						result = "application/drafting";
  						break;
  					case "dvi":
  						result = "application/x-dvi";
  						break;
  					case "dv":
  						result = "video/x-dv";
  						break;
  					case "dwf":
  						result = "drawing/x-dwf (old)";
  						break;
  					case "dwg":
  						result = "application/acad";
  						break;
  					case "dxf":
  						result = "application/dxf";
  						break;
  					case "dxr":
  						result = "application/x-director";
  						break;
  					case "elc":
  						result = "application/x-elc";
  						break;
  					case "el":
  						result = "text/x-script.elisp";
  						break;
  					case "eml":
  						result = "message/rfc822";
  						break;
  					case "eot":
  						result = "application/vnd.bw-fontobject";
  						break;
  					case "eps":
  						result = "application/postscript";
  						break;
  					case "es":
  						result = "application/x-esrehber";
  						break;
  					case "etx":
  						result = "text/x-setext";
  						break;
  					case "evy":
  						result = "application/envoy";
  						break;
  					case "exe":
  						result = "application/octet-stream";
  						break;
  					case "f77":
  						result = "text/plain";
  						break;
  					case "f90":
  						result = "text/plain";
  						break;
  					case "fdf":
  						result = "application/vnd.fdf";
  						break;
  					case "fif":
  						result = "image/fif";
  						break;
  					case "fli":
  						result = "video/fli";
  						break;
  					case "flo":
  						result = "image/florian";
  						break;
  					case "flr":
  						result = "x-world/x-vrml";
  						break;
  					case "flx":
  						result = "text/vnd.fmi.flexstor";
  						break;
  					case "fmf":
  						result = "video/x-atomic3d-feature";
  						break;
  					case "for":
  						result = "text/plain";
  						break;
  					case "fpx":
  						result = "image/vnd.fpx";
  						break;
  					case "frl":
  						result = "application/freeloader";
  						break;
  					case "f":
  						result = "text/plain";
  						break;
  					case "funk":
  						result = "audio/make";
  						break;
  					case "g3":
  						result = "image/g3fax";
  						break;
  					case "gif":
  						result = "image/gif";
  						break;
  					case "gl":
  						result = "video/gl";
  						break;
  					case "gsd":
  						result = "audio/x-gsm";
  						break;
  					case "gsm":
  						result = "audio/x-gsm";
  						break;
  					case "gsp":
  						result = "application/x-gsp";
  						break;
  					case "gss":
  						result = "application/x-gss";
  						break;
  					case "gtar":
  						result = "application/x-gtar";
  						break;
  					case "g":
  						result = "text/plain";
  						break;
  					case "gz":
  						result = "application/x-gzip";
  						break;
  					case "gzip":
  						result = "application/x-gzip";
  						break;
  					case "hdf":
  						result = "application/x-hdf";
  						break;
  					case "help":
  						result = "application/x-helpfile";
  						break;
  					case "hgl":
  						result = "application/vnd.hp-HPGL";
  						break;
  					case "hh":
  						result = "text/plain";
  						break;
  					case "hlb":
  						result = "text/x-script";
  						break;
  					case "hlp":
  						result = "application/x-helpfile";
  						break;
  					case "hpg":
  						result = "application/vnd.hp-HPGL";
  						break;
  					case "hpgl":
  						result = "application/vnd.hp-HPGL";
  						break;
  					case "hqx":
  						result = "application/binhex";
  						break;
  					case "hta":
  						result = "application/hta";
  						break;
  					case "htc":
  						result = "text/x-component";
  						break;
  					case "h":
  						result = "text/plain";
  						break;
  					case "htmls":
  						result = "text/html";
  						break;
  					case "html":
  						result = "text/html";
  						break;
  					case "htm":
  						result = "text/html";
  						break;
  					case "htt":
  						result = "text/webviewhtml";
  						break;
  					case "htx":
  						result = "text/html";
  						break;
  					case "ice":
  						result = "x-conference/x-cooltalk";
  						break;
  					case "ico":
  						result = "image/x-icon";
  						break;
  					case "idc":
  						result = "text/plain";
  						break;
  					case "ief":
  						result = "image/ief";
  						break;
  					case "iefs":
  						result = "image/ief";
  						break;
  					case "iges":
  						result = "application/iges";
  						break;
  					case "igs":
  						result = "application/iges";
  						break;
  					case "iii":
  						result = "application/x-iphone";
  						break;
  					case "ima":
  						result = "application/x-ima";
  						break;
  					case "imap":
  						result = "application/x-httpd-imap";
  						break;
  					case "inf":
  						result = "application/inf";
  						break;
  					case "ins":
  						result = "application/x-internett-signup";
  						break;
  					case "ip":
  						result = "application/x-ip2";
  						break;
  					case "isp":
  						result = "application/x-internet-signup";
  						break;
  					case "isu":
  						result = "video/x-isvideo";
  						break;
  					case "it":
  						result = "audio/it";
  						break;
  					case "iv":
  						result = "application/x-inventor";
  						break;
  					case "ivf":
  						result = "video/x-ivf";
  						break;
  					case "ivr":
  						result = "i-world/i-vrml";
  						break;
  					case "ivy":
  						result = "application/x-livescreen";
  						break;
  					case "jam":
  						result = "audio/x-jam";
  						break;
  					case "java":
  						result = "text/plain";
  						break;
  					case "jav":
  						result = "text/plain";
  						break;
  					case "jcm":
  						result = "application/x-java-commerce";
  						break;
  					case "jfif":
  						result = "image/jpeg";
  						break;
  					case "jfif-tbnl":
  						result = "image/jpeg";
  						break;
  					case "jpeg":
  						result = "image/jpeg";
  						break;
  					case "jpe":
  						result = "image/jpeg";
  						break;
  					case "jpg":
  						result = "image/jpeg";
  						break;
  					case "jps":
  						result = "image/x-jps";
  						break;
  					case "js":
  						result = "application/x-javascript";
  						break;
  					case "jut":
  						result = "image/jutvision";
  						break;
  					case "kar":
  						result = "audio/midi";
  						break;
  					case "ksh":
  						result = "text/x-script.ksh";
  						break;
  					case "la":
  						result = "audio/nspaudio";
  						break;
  					case "lam":
  						result = "audio/x-liveaudio";
  						break;
  					case "latex":
  						result = "application/x-latex";
  						break;
  					case "list":
  						result = "text/plain";
  						break;
  					case "lma":
  						result = "audio/nspaudio";
  						break;
  					case "log":
  						result = "text/plain";
  						break;
  					case "lsp":
  						result = "application/x-lisp";
  						break;
  					case "lst":
  						result = "text/plain";
  						break;
  					case "lsx":
  						result = "text/x-la-asf";
  						break;
  					case "ltx":
  						result = "application/x-latex";
  						break;
  					case "m13":
  						result = "application/x-msmediaview";
  						break;
  					case "m14":
  						result = "application/x-msmediaview";
  						break;
  					case "m1v":
  						result = "video/mpeg";
  						break;
  					case "m2a":
  						result = "audio/mpeg";
  						break;
  					case "m2v":
  						result = "video/mpeg";
  						break;
  					case "m3u":
  						result = "audio/x-mpequrl";
  						break;
  					case "man":
  						result = "application/x-troff-man";
  						break;
  					case "manifest":
  						result = "application/x-ms-manifest";
  						break;
  					case "map":
  						result = "application/x-navimap";
  						break;
  					case "mar":
  						result = "text/plain";
  						break;
  					case "mbd":
  						result = "application/mbedlet";
  						break;
  					case "mc$":
  						result = "application/x-magic-cap-package-1.0";
  						break;
  					case "mcd":
  						result = "application/mcad";
  						break;
  					case "mcf":
  						result = "image/vasa";
  						break;
  					case "mcp":
  						result = "application/netmc";
  						break;
  					case "mdb":
  						result = "application/x-msaccess";
  						break;
  					case "me":
  						result = "application/x-troff-me";
  						break;
  					case "mht":
  						result = "message/rfc822";
  						break;
  					case "mhtml":
  						result = "message/rfc822";
  						break;
  					case "mid":
  						result = "audio/midi";
  						break;
  					case "midi":
  						result = "audio/midi";
  						break;
  					case "mif":
  						result = "application/x-mif";
  						break;
  					case "mime":
  						result = "message/rfc822";
  						break;
  					case "mjf":
  						result = "audio/x-vnd.AudioExplosion.MjuiceMediaFile";
  						break;
  					case "mjpg":
  						result = "video/x-motion-jpeg";
  						break;
  					case "mm":
  						result = "application/base64";
  						break;
  					case "mme":
  						result = "application/base64";
  						break;
  					case "mny":
  						result = "application/x-msmoney";
  						break;
  					case "mod":
  						result = "audio/mod";
  						break;
  					case "moov":
  						result = "video/quicktime";
  						break;
  					case "movie":
  						result = "video/x-sgi-movie";
  						break;
  					case "mov":
  						result = "video/quicktime";
  						break;
  					case "mp2":
  						result = "video/mpeg";
  						break;
  					case "mp3":
  						result = "audio/mpeg3";
  						break;
  					case "mpa":
  						result = "audio/mpeg";
  						break;
  					case "mpc":
  						result = "application/x-project";
  						break;
  					case "mpeg":
  						result = "video/mpeg";
  						break;
  					case "mpe":
  						result = "video/mpeg";
  						break;
  					case "mpga":
  						result = "audio/mpeg";
  						break;
  					case "mpg":
  						result = "video/mpeg";
  						break;
  					case "mpp":
  						result = "application/vnd.ms-project";
  						break;
  					case "mpt":
  						result = "application/x-project";
  						break;
  					case "mpv2":
  						result = "video/mpeg";
  						break;
  					case "mpv":
  						result = "application/x-project";
  						break;
  					case "mpx":
  						result = "application/x-project";
  						break;
  					case "mrc":
  						result = "application/marc";
  						break;
  					case "ms":
  						result = "application/x-troff-ms";
  						break;
  					case "m":
  						result = "text/plain";
  						break;
  					case "mvb":
  						result = "application/x-msmediaview";
  						break;
  					case "mv":
  						result = "video/x-sgi-movie";
  						break;
  					case "my":
  						result = "audio/make";
  						break;
  					case "mzz":
  						result = "application/x-vnd.AudioExplosion.mzz";
  						break;
  					case "nap":
  						result = "image/naplps";
  						break;
  					case "naplps":
  						result = "image/naplps";
  						break;
  					case "nc":
  
gt: 						result = "application/x-netcdf";