///////////////////////////////////////////////////////////////////////
// Copyright (C) Andru 2007                                          //
// mail: dr.andru@gmail.com                                          //
// site: http://andru.2x4.ru                                         //
//                                                                   //
// OMEGA Engine is free software.                                    //
//                                                                   //
// You may redistribute it and/or modify it under the terms of the   //
// GNU General Public License, as published by the Free Software     //
// Foundation; either version 2 of the License, or (at your option)  //
// any later version.                                                //
//                                                                   //
// this module is distributed in the hope that it will be useful,    //
// but WITHOUT ANY WARRANTY; without even the implied warranty of    //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.              //
// See the GNU General Public License for more details.              //
//                                                                   //
// You should have received a copy of the GNU General Public License //
// along with this module.  If not, write to:                        //
// 	The Free Software Foundation, Inc.,                              //
// 	51 Franklin Street, Fifth Floor                                  //
// 	Boston, MA  02110-1301, USA.                                     //
///////////////////////////////////////////////////////////////////////
unit ENGINE_TIMERS;

{$I DEFINES.pas}

interface
uses
  Windows;

type
  TTimer = record
    Active    : Boolean;
    Interval  : DWORD;
    LastTime  : Double;
    Precision : Integer;
    OnTimer   : Procedure;
    Next      : Pointer;
end;
PTimer = ^TTimer;

function Timer_Create( OnTimer : Pointer; Interval, Precision : Integer ) : PTimer; stdcall;
procedure Timer_Free( var Timer : PTimer ); stdcall;
procedure Timer_FreeAll; stdcall;

var
  CanKillTimers : Boolean;
  CTimersToKill : Integer = 0;
  TimersToKill  : array[ 0..1023 ] of PTimer;

//----------------------------------------------------------------------------//
                                 IMPLEMENTATION
//----------------------------------------------------------------------------//
uses
  ENGINE_VAR, ENGINE_CONST, ENGINE_LOG, ENGINE_UTILS, UTILS;

function Timer_Create;
  var
    new : PTimer;
begin

Result := nil;

new := app_Timer;
while new^.Next <> nil do
  new := new^.Next;

Mem_Get( new^.Next, SizeOf( TTimer ) );
PTimer( new^.Next )^.Active    := TRUE;
PTimer( new^.Next )^.Interval  := Interval;
PTimer( new^.Next )^.LastTime  := U_GetTime;
PTimer( new^.Next )^.Precision := Precision;
PTimer( new^.Next )^.OnTimer   := OnTimer;
PTimer( new^.Next )^.Next      := nil;

INC( app_Timers );

Result := new^.Next;

End;

procedure Timer_Free;
  var
    old  : PTimer;
    next : PTimer;
Begin

if not CanKillTimers Then
  begin
    INC( CTimersToKill );
    TimersToKill[ CTimersToKill ] := Timer;
    exit;
  end;

old := app_Timer;
while old^.Next <> Timer do
  old := old^.Next;

next := PTimer( old^.Next )^.Next;

Mem_Free( old^.Next );

old^.Next := next;

DEC( app_Timers );
Timer  := nil;

End;

procedure Timer_FreeAll;
  var
    oldTimer : PTimer;
Begin
app_Timers := 0;
oldTimer := app_Timer^.Next;
if oldTimer = nil Then
  Mem_Free( app_Timer );
while oldTimer <> nil do
  begin
    app_Timer := oldTimer;
    oldTimer  := oldTimer^.Next;
    Mem_Free( app_Timer );
    INC( app_Timers )
  end;
KillTimer( wnd_HWND, app_FPS_TIMER );
if ( app_Log ) and ( app_Timers > 0 ) Then
  LOG_AddMessage( LOGT_ENGINE, PChar( LOG_FREE_TIMERS + '[' + U_IntToStr( app_Timers ) + ']' ) );

Mem_Get( Pointer( app_Timer ), SizeOf( TTimer ) );
app_Timer^.Interval := 0;
app_Timer^.Next     := nil;
app_Timers := -1;
SetTimer( wnd_HWND, app_FPS_TIMER, 1000, nil );
End;

initialization
  Mem_Get( Pointer( app_Timer ), SizeOf( TTimer ) );
  app_Timer^.Interval := 0;
  app_Timer^.Next     := nil;
  app_Timers := -1;

end.
