#define ZGL_IMPORT

#include <memory.h>
#include <math.h>
#include "zglHeader.h"

zglPFont      fntMain;
zglPTexture   texBack;
bool          debug;
zglTPEngine2D particles;
zglPEmitter2D emitterFire[3];
zglPEmitter2D emitterDiamond;
zglPEmitter2D emitterRain;

char resource[256];

char* GetResource( char* FileName )
{
#ifndef __MACOSX__
  sprintf_s( resource, "../data/%s", FileName );
  return resource;
#else
  return FileName;
#endif
}

void Init()
{
  texBack = tex_LoadFromFile( GetResource( "back02.png" ), TEX_NO_COLORKEY, TEX_DEFAULT_2D );

  fntMain = font_LoadFromFile( GetResource( "font.zfi" ) );

  // EN: Load three types of fire emitters.
  // RU: Загрузка трёх разных видов эмиттеров огня.
  emitterFire[ 0 ] = emitter2d_LoadFromFile( GetResource( "emitter_fire00.zei" ) );
  emitterFire[ 1 ] = emitter2d_LoadFromFile( GetResource( "emitter_fire01.zei" ) );
  emitterFire[ 2 ] = emitter2d_LoadFromFile( GetResource( "emitter_fire02.zei" ) );

  // EN: Set own particels engine.
  // RU: Установка собственного движка эмиттеров.
  pengine2d_Set( &particles );

  // EN: Add 6 fire emitters to particles engine. Second parameter of function returns pointer to instance of new emitter, which can be processed manually.
  //     This instance will be  NULL after the death, so check everything.
  // RU: Добавляем в движок 6 эмиттеров огня. Второй параметр функции позволяет получить указатель на конкретный экземпляр эмиттера, который можно будет обрабатывать вручную.
  //     Данный экземпляр после смерти будет содержать NULL, поэтому используйте проверку.
  pengine2d_AddEmitter( emitterFire[ 0 ], NULL, 642, 190 );
  pengine2d_AddEmitter( emitterFire[ 0 ], NULL, 40, 368 );
  pengine2d_AddEmitter( emitterFire[ 0 ], NULL, 246, 368 );
  pengine2d_AddEmitter( emitterFire[ 1 ], NULL, 532, 244 );
  pengine2d_AddEmitter( emitterFire[ 1 ], NULL, 318, 422 );
  pengine2d_AddEmitter( emitterFire[ 1 ], NULL, 583, 420 );
  pengine2d_AddEmitter( emitterFire[ 2 ], NULL, 740, 525 );

  emitterDiamond = emitter2d_LoadFromFile( GetResource( "emitter_diamond.zei" ) );
  pengine2d_AddEmitter( emitterDiamond, NULL, 0, 0 );

  emitterRain = emitter2d_LoadFromFile( GetResource( "emitter_rain.zei" ) );
  pengine2d_AddEmitter( emitterRain, NULL, 0, 0 );
}

void Draw()
{
  batch2d_Begin();

  ssprite2d_Draw( texBack, 0, 0, 800, 600, 0, 255, FX_BLEND );

  // EN: Rendering of all emitters in current particles engine.
  // RU: Рендеринг всех эмиттеров в текущем движке частиц.
  pengine2d_Draw();

  if ( debug )
    for ( int i = 0; i < particles.Count.Emitters; i++ )
      pr2d_Rect( particles.List[ i ]->BBox.MinX, particles.List[ i ]->BBox.MinY,
                  particles.List[ i ]->BBox.MaxX - particles.List[ i ]->BBox.MinX,
                  particles.List[ i ]->BBox.MaxY - particles.List[ i ]->BBox.MinY, 0xFF0000, 255, 0 );

  char text[64];
  sprintf_s( text, "FPS: %i", (int)zgl_Get( RENDER_FPS ) );
  text_Draw( fntMain, 0, 0, text, 0 );

  sprintf_s( text, "Particles: %i", particles.Count.Particles );
  text_Draw( fntMain, 0, 20, text, 0 );

  sprintf_s( text, "Debug(F1): %s", debug ? "TRUE" : "FALSE" );
  text_Draw( fntMain, 0, 40, text, 0 );

  batch2d_End();
}

void Timer()
{
  if ( key_Press( K_ESCAPE ) ) zgl_Exit();
  if ( key_Press( K_F1 ) ) debug = !debug;

  key_ClearState();
}

void Update( double dt )
{
  // EN: Process all emitters in current particles engine.
  // RU: Обработка всех эмиттеров в текущем движке частиц.
  pengine2d_Proc( dt );
}

void Quit()
{
  // RU: Очищаем память от созданных эмиттеров.
  // EN: Free allocated memory for emitters.
  pengine2d_Set( &particles );
  pengine2d_ClearAll();
}

int main()
{
  if ( !zglLoad( libZenGL ) ) return 0;

  timer_Add( (void*)&Timer, 16, FALSE, NULL );

  zgl_Reg( SYS_LOAD, (void*)&Init );
  zgl_Reg( SYS_DRAW, (void*)&Draw );
  zgl_Reg( SYS_UPDATE, (void*)&Update );
  zgl_Reg( SYS_EXIT, (void*)&Quit );

  wnd_SetCaption( "13 - Particles" );

  wnd_ShowCursor( TRUE );

  scr_SetOptions( 800, 600, REFRESH_MAXIMUM, FALSE, FALSE );

  zgl_Init( 0, 0 );

  zglFree();
  return 0;
}