//
// VideoTrack.cs:
//
// Author:
//   Julien Moutte <julien@fluendo.com>
//
// Copyright (C) 2011 FLUENDO S.A.
//
// This library is free software; you can redistribute it and/or modify
// it  under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307
// USA
//

using System.Collections.Generic;

namespace TagLib.Matroska
{
	/// <summary>
	/// Enumeration describing supported Video Aspect Ratio types.
	/// </summary>
	public enum VideoAspectRatioType
	{
		/// <summary>
		/// Free Aspect Ratio.
		/// </summary>
		AspectRatioModeFree = 0x0,
		/// <summary>
		/// Keep Aspect Ratio.
		/// </summary>
		AspectRatioModeKeep = 0x1,
		/// <summary>
		/// Fixed Aspect Ratio.
		/// </summary>
		AspectRatioModeFixed = 0x2
	}

	/// <summary>
	/// Describes a Matroska Video Track.
	/// </summary>
	public class VideoTrack : Track, IVideoCodec
	{
		#region Private fields

#pragma warning disable 414 // Assigned, never used
		readonly ulong width;
		readonly ulong height;
		readonly ulong disp_width;
		readonly ulong disp_height;
		readonly double framerate;
		readonly bool interlaced;
		readonly VideoAspectRatioType ratio_type;
		readonly ByteVector fourcc;
#pragma warning restore 414

		readonly List<EBMLreader> unknown_elems = new List<EBMLreader> ();

		#endregion

		#region Constructors

		/// <summary>
		/// Constructs a <see cref="VideoTrack" /> parsing from provided
		/// file data.
		/// Parsing will be done reading from _file at position references by 
		/// parent element's data section.
		/// </summary>
		/// <param name="_file"><see cref="File" /> instance to read from.</param>
		/// <param name="element">Parent <see cref="EBMLreader" />.</param>
		public VideoTrack (File _file, EBMLreader element)
			: base (_file, element)
		{
			// Here we handle the unknown elements we know, and store the rest
			foreach (EBMLreader elem in base.UnknownElements) {
				var matroska_id = elem.ID;


				switch (matroska_id) {
				case MatroskaID.TrackVideo: {
						ulong i = 0;

						while (i < elem.DataSize) {
							EBMLreader child = new EBMLreader (_file, elem.DataOffset + i);

							matroska_id = child.ID;

							switch (matroska_id) {
							case MatroskaID.VideoDisplayWidth:
								disp_width = child.ReadULong ();
								break;
							case MatroskaID.VideoDisplayHeight:
								disp_height = child.ReadULong ();
								break;
							case MatroskaID.VideoPixelWidth:
								width = child.ReadULong ();
								break;
							case MatroskaID.VideoPixelHeight:
								height = child.ReadULong ();
								break;
							case MatroskaID.VideoFrameRate:
								framerate = child.ReadDouble ();
								break;
							case MatroskaID.VideoFlagInterlaced:
								interlaced = child.ReadBool ();
								break;
							case MatroskaID.VideoAspectRatioType:
								ratio_type = (VideoAspectRatioType)child.ReadULong ();
								break;
							case MatroskaID.VideoColourSpace:
								fourcc = child.ReadBytes ();
								break;
							default:
								unknown_elems.Add (child);
								break;
							}

							i += child.Size;
						}
						break;
					}

				case MatroskaID.TrackDefaultDuration:
					ulong tmp = elem.ReadULong ();
					framerate = 1000000000.0 / tmp;
					break;

				default:
					unknown_elems.Add (elem);
					break;
				}
			}
		}

		#endregion

		#region Public fields

		/// <summary>
		/// List of unknown elements encountered while parsing.
		/// </summary>
		public new List<EBMLreader> UnknownElements {
			get { return unknown_elems; }
		}

		#endregion

		#region Public methods

		#endregion

		#region ICodec

		/// <summary>
		/// This type of track only has video media type.
		/// </summary>
		public override MediaTypes MediaTypes {
			get { return MediaTypes.Video; }
		}

		#endregion

		#region IVideoCodec

		/// <summary>
		/// Describes video track width in pixels.
		/// </summary>
		public int VideoWidth {
			get { return (int)width; }
		}

		/// <summary>
		/// Describes video track height in pixels.
		/// </summary>
		public int VideoHeight {
			get { return (int)height; }
		}

		#endregion
	}
}
