using System;

/*
    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 FicSprout.Bacicworx.Media.VideoAspectRatio _videoAspectRatio =
            FicSprout.Bacicworx.Media.VideoAspectRatio.Aspect_Unknown;
        private string _videoBitrate = string.Empty;
        private bool _videoClosedCaptionLine21Field1 = false;
        private bool _videoClosedCaptionLine21Field2 = false;
        private string _videoCodingMode = string.Empty;
        private string _videoFilm = string.Empty;
        private bool _videoIsLetterBoxed = false;
        private bool _videoAutoLetterbox = false;
        private bool _videoAutoPanScan = false;
        private string _videoResolution = string.Empty;
        private string _videoStandard = string.Empty;
        private string _vobFilename = string.Empty;

        #endregion

        #region Properties

        /// <summary>
        /// Gets and sets 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 bool Checked
        {
            get
            {
                bool result = false;

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

                return result;
            }
        }
        /// <summary>
        /// Gets the video title set id. Values start at one.
        /// </summary>
        public Int32 Id
        {
            get
            {
                return _id;
            }
        }
        /// <summary>
        /// Gets and sets the filename of the IFO for the title set.
        /// </summary>
        public string IfoFilename
        {
            get
            {
                return _ifoFilename;
            }
            internal set
            {
                _ifoFilename = value;
            }
        }
        /// <summary>
        /// Gets and sets the number of parts for the title set.
        /// </summary>
        public Int32 Parts
        {
            get
            {
                return _parts;
            }
            internal set
            {
                _parts = value;
            }
        }
        /// <summary>
        /// Gets and sets the program chains for the title set.
        /// </summary>
        public ProgramChain[] ProgramChains
        {
            get
            {
                return _programChains;
            }
            internal set
            {
                _programChains = value;
            }
        }
        /// <summary>
        /// Gets and sets 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 and sets the length in bytes for the title set.
        /// </summary>
        public Int64 Length
        {
            get
            {
                return _length;
            }
            internal set
            {
                _length = value;
            }
        }
        /// <summary>
        /// Gets and sets 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 FicSprout.Bacicworx.Media.VideoAspectRatio VideoAspectRatio
        {
            get
            {
                return _videoAspectRatio;
            }
        }
        /// <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 bool VideoClosedCaptionLine21Field1
        {
            get
            {
                return _videoClosedCaptionLine21Field1;
            }
        }
        /// <summary>
        /// Gets whether the video has line 21, field 2 closed captioning.
        /// </summary>
        public bool 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 bool VideoIsLetterBoxed
        {
            get
            {
                return _videoIsLetterBoxed;
            }
        }
        /// <summary>
        /// Gets whether the video is allowed to be auto letterboxed.
        /// </summary>
        public bool VideoAutoLetterbox
        {
            get
            {
                return _videoAutoLetterbox;
            }
        }
        /// <summary>
        /// Gets whether the video is allowed to be auto panned &amp; scanned.
        /// </summary>
        public bool 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 filename of the first vob for the title set.
        /// </summary>
        public string VobFilename
        {
            get
            {
                return _vobFilename;
            }
            internal set
            {
                _vobFilename = value;
            }
        }

        #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;
        }

        /// <summary>
        /// Updates the video attributes for the title set.
        /// </summary>
        /// <param name="bytes">A byte array containing bytes to parse.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when bytes is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when bytes length is not two bytes.</exception>
        public void SetVideoAttributes(byte[] bytes)
        {
            if (bytes == null)
            {
                throw new ArgumentNullException("bytes");
            }
            if (bytes.Length != 2)
            {
                throw new ArgumentException("bytes length must be two bytes.");
            }

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

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

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

            _videoClosedCaptionLine21Field1 = ((bytes[1] >> 6) & 1) > 0;
            _videoClosedCaptionLine21Field2 = ((bytes[1] >> 7) & 1) > 0;
        }

        #endregion
    }
}
