using System;
using System.Collections.Generic;

/*
    Copyright (c) 2010 flixmonk. (http://DVDSwarm.codeplex.com)
    All Rights Reserved.
        
    Redistribution and use in source and binary forms, with or without modification,
    are permitted provided that the following conditions are met:
        
    * Redistributions of source code must retain the above copyright notice, this list
      of conditions and the following disclaimer.
        
    * Redistributions in binary form must reproduce the above copyright notice, this
    list of conditions and the following disclaimer in the documentation and/or other
    materials provided with the distribution. 
        
    * Neither the name of The Flixmonk nor the names of its contributors may be used to
    endorse or promote products derived from this software without specific prior written
    permission.
        
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
    SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
    OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace DVDSwarm.Dvd
{
    /// <summary>
    /// Contains information about a DVD title set. Member of the IfoReader class.
    /// </summary>
    sealed public class TitleSet
    {
        #region Fields

        private AudioStream[] _audioStreams = null;
        private Int32 _id = 0;
        private string _ifoFilename = string.Empty;
        private Int64 _length = 0;
        private Int32 _parts = 0;
        private ProgramChain[] _programChains = null;
        private Int32 _programCainsTableOffset = 0;
        private Subpicture[] _subpictures = null;
        private VideoAspectRatio _videoAspectRatio = VideoAspectRatio.Aspect_Unknown;
        private string _videoBitrate = string.Empty;
        private Boolean _videoClosedCaptionLine21Field1 = false;
        private Boolean _videoClosedCaptionLine21Field2 = false;
        private string _videoCodingMode = string.Empty;
        private string _videoFilm = string.Empty;
        private Boolean _videoIsLetterBoxed = false;
        private Boolean _videoAutoLetterbox = false;
        private Boolean _videoAutoPanScan = false;
        private string _videoResolution = string.Empty;
        private string _videoStandard = string.Empty;
        private List<string> _vobFilenames = new List<string>();
        private List<Int64> _vobLengths = new List<Int64>();

        #endregion

        #region Properties

        /// <summary>
        /// Gets the audio streams for the title set. Individual ids within each program chain
        /// indicate which of these aduio streams are used by that program chain.
        /// </summary>
        public AudioStream[] AudioStreams
        {
            get
            {
                return _audioStreams;
            }
            internal set
            {
                _audioStreams = value;
            }
        }
        /// <summary>
        /// Gets and sets whether the title set is selected. It is considered selected if at
        /// lest one stream is selected.
        /// </summary>
        public Boolean Checked
        {
            get
            {
                bool result = false;

                for (Int32 i = 0; i < _programChains.Length; i++)
                {
                    if (_programChains[i].Checked)
                    {
                        result = true;
                        break;
                    }
                }

                return result;
            }
        }
        /// <summary>
        /// Gets the number of checked program chains.
        /// </summary>
        public Int32 CheckedCount
        {
            get
            {
                Int32 result = 0;

                for (Int32 i = 0; i < _programChains.Length; i++)
                {
                    if (_programChains[i].Checked)
                    {
                        result++;
                    }
                }

                return result;
            }
        }
        /// <summary>
        /// Gets the video title set id. Values start at one.
        /// </summary>
        public Int32 Id
        {
            get
            {
                return _id;
            }
        }
        /// <summary>
        /// Gets the filename of the IFO for the title set.
        /// </summary>
        public string IfoFilename
        {
            get
            {
                return _ifoFilename;
            }
            internal set
            {
                _ifoFilename = value;
            }
        }
        /// <summary>
        /// Gets the length in bytes for the title set.
        /// </summary>
        public Int64 Length
        {
            get
            {
                return _length;
            }
            internal set
            {
                _length = value;
            }
        }
        /// <summary>
        /// Gets the number of VOB parts for the title set.
        /// </summary>
        public Int32 Parts
        {
            get
            {
                return _parts;
            }
            internal set
            {
                _parts = value;
            }
        }
        /// <summary>
        /// Gets the program chains for the title set.
        /// </summary>
        public ProgramChain[] ProgramChains
        {
            get
            {
                return _programChains;
            }
            internal set
            {
                _programChains = value;
            }
        }
        /// <summary>
        /// Gets the the offset to the program chains table (VTS_PGCI) within the title set.
        /// </summary>
        public Int32 ProgramCainsTableOffset
        {
            get
            {
                return _programCainsTableOffset;
            }
            internal set
            {
                _programCainsTableOffset = value;
            }
        }
        /// <summary>
        /// Gets the subpictures for the title set. Individual ids within each program chain
        /// indicate which of these subpicture streams are used by that program chain.
        /// </summary>
        public Subpicture[] Subpictures
        {
            get
            {
                return _subpictures;
            }
            internal set
            {
                _subpictures = value;
            }
        }
        /// <summary>
        /// Gets the video aspect ratio.
        /// </summary>
        public VideoAspectRatio VideoAspectRatio
        {
            get
            {
                return _videoAspectRatio;
            }
        }
        /// <summary>
        /// Sets the video attributes for the title set.
        /// </summary>
        /// <exception cref="System.ArgumentNullException">Thrown when bytes is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when bytes length is not two bytes.</exception>
        public byte[] VideoAttributes
        {
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException("bytes");
                }
                if (value.Length != 2)
                {
                    throw new ArgumentException("bytes length must be two bytes.");
                }

                _videoAspectRatio = VideoAspectRatio.Aspect_Unknown;
                // Title set is 4:3 aspect?
                if (((value[0] >> 2) & 3) == 0)
                {
                    _videoAspectRatio = VideoAspectRatio.Aspect_1_33;
                }
                // Title set is 16:9 aspect?
                if (((value[0] >> 2) & 3) == 3)
                {
                    _videoAspectRatio = VideoAspectRatio.Aspect_1_78;
                }

                _videoBitrate = Dvd.Utility.VideoBitrateNames[((value[1] >> 5) & 1)];
                _videoCodingMode = Dvd.Utility.VideoCodingModeNames[(value[0] >> 6)];
                _videoIsLetterBoxed = ((value[1] >> 2) & 1) > 0;
                _videoFilm = Dvd.Utility.VideoFilmNames[(value[1] & 1)];
                _videoAutoPanScan = ((value[0] >> 1) & 1) == 0;
                _videoAutoLetterbox = (value[0] & 1) == 0;
                _videoStandard = Dvd.Utility.VideoStandardNames[((value[0] >> 4) & 3)];

                if (_videoStandard == "NTSC")
                {
                    _videoResolution = Dvd.Utility.VideoResolutionNtscNames[((value[1] >> 3) & 3)];
                }
                if (_videoStandard == "PAL")
                {
                    _videoResolution = Dvd.Utility.VideoResolutionPalNames[((value[1] >> 3) & 3)];
                }

                _videoClosedCaptionLine21Field1 = ((value[1] >> 6) & 1) > 0;
                _videoClosedCaptionLine21Field2 = ((value[1] >> 7) & 1) > 0;
            }
        }
        /// <summary>
        /// Gets the video bitrate type.
        /// </summary>
        public string VideoBitrate
        {
            get
            {
                return _videoBitrate;
            }
        }
        /// <summary>
        /// Gets whether the video has line 21, field 1 closed captioning.
        /// </summary>
        public Boolean VideoClosedCaptionLine21Field1
        {
            get
            {
                return _videoClosedCaptionLine21Field1;
            }
        }
        /// <summary>
        /// Gets whether the video has line 21, field 2 closed captioning.
        /// </summary>
        public Boolean VideoClosedCaptionLine21Field2
        {
            get
            {
                return _videoClosedCaptionLine21Field2;
            }
        }
        /// <summary>
        /// Gets the video coding mode.
        /// </summary>
        public string VideoCodingMode
        {
            get
            {
                return _videoCodingMode;
            }
        }
        /// <summary>
        /// Gets the video source type.
        /// </summary>
        public string VideoFilm
        {
            get
            {
                return _videoFilm;
            }
        }
        /// <summary>
        /// Gets the video framerate.
        /// </summary>
        public string VideoFramerate
        {
            get
            {
                string result = "30fps";
                if (_videoStandard == "PAL")
                {
                    result = "25fps";
                }

                return result;
            }
        }
        /// <summary>
        /// Gets whether the video is letterboxed.
        /// </summary>
        public Boolean VideoIsLetterBoxed
        {
            get
            {
                return _videoIsLetterBoxed;
            }
        }
        /// <summary>
        /// Gets whether the video is allowed to be auto letterboxed.
        /// </summary>
        public Boolean VideoAutoLetterbox
        {
            get
            {
                return _videoAutoLetterbox;
            }
        }
        /// <summary>
        /// Gets whether the video is allowed to be auto panned &amp; scanned.
        /// </summary>
        public Boolean VideoAutoPanScan
        {
            get
            {
                return _videoAutoPanScan;
            }
        }
        /// <summary>
        /// Gets the video resolution.
        /// </summary>
        public string VideoResolution
        {
            get
            {
                return _videoResolution;
            }
        }
        /// <summary>
        /// Gets the video standard.
        /// </summary>
        public string VideoStandard
        {
            get
            {
                return _videoStandard;
            }
        }
        /// <summary>
        /// Gets the filenames of the vob parts which comprise the title set.
        /// </summary>
        public List<String> VobFilenames
        {
            get
            {
                return _vobFilenames;
            }
        }
        /// <summary>
        /// Gets the lengths of the vob parts which comprise the title set.
        /// </summary>
        public List<Int64> VobLengths
        {
            get
            {
                return _vobLengths;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Creates a new instance of the TitleSet class.
        /// </summary>
        /// <param name="value">The id for the title set. Values start at one.</param>
        public TitleSet(Int32 value)
        {
            _id = value;
        }

        #endregion
    }
}
