//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
//
// WFX satellite library | Author: Sergei Y.Kitáev
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;
using System.IO;

using DRW = System.Drawing;
using WF = System.Windows.Forms;

using CommonHelpers;

namespace WFX {

//**************************************************************************************************
public class ImageAnimation: HDisposable {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public int FrameCount
{
   get { return _FrameCount_; }
}

public bool IsReseted
{
   get { return _CurrentFrameIndex_ < 0; }
}

public int CurrentFrameIndex
{
   get { return _CurrentFrameIndex_; }
}

//--------------------------------------------------------------------------------------------------

public DRW.Image StartFrame
{
   get { return this[ 0 ]; }
}

public DRW.Image EndingFrame
{
   get { return this[ FrameCount - 1 ]; }
}

//--------------------------------------------------------------------------------------------------

/// <exception cref="ArgumentOutOfRangeException" />
public DRW.Image this[int frameIdx]
{
   get
   {
      if ( !HOps.IsBetween( frameIdx, 0, FrameCount-1 ) )
         throw new ArgumentOutOfRangeException();
      _Image_.SelectActiveFrame( _Dimension_, frameIdx );
      return (DRW.Image)_Image_.Clone();
   }
}

//==================================================================================================

/// <exception cref="ArgumentNullException" />
/// <exception cref="HOperationFailedException" />
public ImageAnimation(DRW.Image image)
{
   Initialize( image );
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="ArgumentException" />
/// <exception cref="FileNotFoundException" />
/// <exception cref="DirectoryNotFoundException" />
/// <exception cref="IOException" />
/// <exception cref="HOperationFailedException" />
public ImageAnimation(string fileName)
{
   try
   {
      Initialize( DRW.Image.FromFile( fileName ) );
   }
   catch (HOperationFailedException e)
   {
      throw new HOperationFailedException(
         HFileErrorMessage.ComposeMessage( fileName, e.Message ) );
   }
}

/// <exception cref="ArgumentNullException" />
/// <exception cref="HOperationFailedException" />
public ImageAnimation(byte[] bytes)
   :this ( new MemoryStream( bytes ) )
{}

/// <exception cref="ArgumentNullException" />
/// <exception cref="HOperationFailedException" />
public ImageAnimation(Stream stream)
   :this ( DRW.Image.FromStream( stream ) )
{}

//==================================================================================================

public void Reset()
{
   _CurrentFrameIndex_ = -1;
}

public DRW.Image GetNextFrame()
{
   return this[ _CurrentFrameIndex_ = ( CurrentFrameIndex + 1 ) % FrameCount ];
}

public DRW.Image GetLastFrame()
{
   if ( _CurrentFrameIndex_ < 0  )
      _CurrentFrameIndex_ = 0;
   return this[ _CurrentFrameIndex_ ];
}

//==================================================================================================

protected override void OnDispose(bool synchronous)
{
   if ( synchronous ) _Image_.Dispose();
}

//==================================================================================================

void Initialize(DRW.Image image)
{
   HArgChecking.VerifyNotNull( _Image_ = image );
   var guids = _Image_.FrameDimensionsList;
   if ( guids.Length == 0 )
      throw new HOperationFailedException(
         "Image frame dimensions list is empty." );
   _Dimension_ = new DRW.Imaging.FrameDimension( guids[ 0 ] );
   if ( (_FrameCount_ = _Image_.GetFrameCount( _Dimension_ )) == 0 )
      throw new HOperationFailedException(
         "Image frame sequence is empty (at zero dimension)." );
   ValidateDisposable();
}

//==================================================================================================

DRW.Image
   _Image_;
DRW.Imaging.FrameDimension
   _Dimension_;
int
   _FrameCount_,
   _CurrentFrameIndex_ = -1;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // ImageAnimation
//**************************************************************************************************

} // WFX
