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 program cell. Member of the Program class.
    /// </summary>
    sealed public class Cell
    {
        #region Fields

        private FicSprout.Bacicworx.Media.SmpteTimecode _duration;
        private Int32 _endSector = 0;
        private string _framerate = string.Empty;
        private Int32 _id = 0;
        private Int64 _length = 0;
        private Int32 _sectorCount = 0;
        private Int32 _startSector = 0;
        private Int32 _vobID = 0;
        
        #endregion

        #region Properties

        /// <summary>
        /// Gets the duration for the cell.
        /// </summary>
        public FicSprout.Bacicworx.Media.SmpteTimecode Duration
        {
            get
            {
                return _duration;
            }
        }
        /// <summary>
        /// Gets the ending sector for the cell.
        /// </summary>
        public Int32 EndSector
        {
            get
            {
                return _endSector;
            }
        }
        /// <summary>
        /// Gets the video framerate for the cell.
        /// </summary>
        public string Framerate
        {
            get
            {
                return _framerate;
            }
        }
        /// <summary>
        /// Gets the cell number. Values start at one.
        /// </summary>
        public Int32 ID
        {
            get
            {
                return _id;
            }
        }
        /// <summary>
        /// Gets the length of the cell in bytes.
        /// </summary>
        public Int64 Length
        {
            get
            {
                return _length;
            }
        }
        /// <summary>
        /// Gets the number of sectors in the cell.
        /// </summary>
        public Int32 SectorCount
        {
            get
            {
                return _sectorCount;
            }
        }
        /// <summary>
        /// Gets the starting sector for the cell.
        /// </summary>
        public Int32 StartSector
        {
            get
            {
                return _startSector;
            }
        }
        /// <summary>
        /// Gets the vob id that caontains the cell.
        /// </summary>
        public Int32 VobID
        {
            get
            {
                return _vobID;
            }
        }
       
        #endregion

        #region Methods

        /// <summary>
        /// Creates a new instance of the Cell class.
        /// </summary>
        /// <param name="bytes">A byte array containing playback data bytes to parse.</param>
        /// <param name="bytes2">A byte array containing position data bytes to parse.</param>
        /// <exception cref="System.ArgumentNullException">Thrown when bytes is null.</exception>
        /// <exception cref="System.ArgumentNullException">Thrown when bytes2 is null.</exception>
        /// <exception cref="System.ArgumentException">Thrown when bytes length is not 24 bytes.</exception>
        /// <exception cref="System.ArgumentException">Thrown when bytes2 length is not 24 bytes.</exception>
        public Cell(byte[] bytes, byte[] bytes2)
        {
            if (bytes == null)
            {
                throw new ArgumentNullException("bytes");
            }
            if (bytes2 == null)
            {
                throw new ArgumentNullException("bytes2");
            }
            if (bytes.Length != 24)
            {
                throw new ArgumentException("bytes length must be 24 bytes.");
            }
            if (bytes2.Length != 4)
            {
                throw new ArgumentException("bytes2 length must be four bytes.");
            }

            _framerate = Dvd.Utility.ProgramChainFramerateNames[(bytes[7] >> 6) & 3];

            byte[] b = new byte[4];
            Array.Copy(bytes, 4, b, 0, b.Length);
            if (_framerate == Dvd.Utility.ProgramChainFramerateNames[1])
            {
                _duration = new FicSprout.Bacicworx.Media.SmpteTimecode(b, FicSprout.Bacicworx.Media.VideoFrameRate.Fps25, false);
            }
            if (_framerate == Dvd.Utility.ProgramChainFramerateNames[3])
            {
                _duration = new FicSprout.Bacicworx.Media.SmpteTimecode(b, FicSprout.Bacicworx.Media.VideoFrameRate.Fps30, true);
            }
            b = null;

            _startSector = (bytes[8] * 0x1000000) + (bytes[9] * 0x10000) + (bytes[0xa] * 0x100) + bytes[0xb];
            _endSector = (bytes[0x14] * 0x1000000) + (bytes[0x15] * 0x10000) + (bytes[0x16] * 0x100) + bytes[0x17];
            _sectorCount = _endSector - _startSector + 1;
            _length = _sectorCount * Dvd.Utility.DvdSectorSize;

            _vobID = (bytes2[0] * 0x100) + bytes2[1];
            _id = bytes2[3];
        }

        #endregion
    }
}
