unit core_Unit;

{$mode delphi}

interface

uses
  Classes, SysUtils,
  {ZenGL Modules}
    zglHeader,
  {ZenGL Modules}
  SceneUnit;

type

  //Main Core class
  TCore = class
  private
    {---private declarations---}
    ScreenW, ScreenH: integer;
    FullScreen: boolean;
    scenes: array of TScene;
    loaded: boolean;
    CursorState: boolean;
    time: double;
    procedure CoreInit();
    function FindScene(inputID: string): integer;
    {---private declarations---}
  public
    {---public declarations---}
    constructor Create;
    destructor Destroy;
    procedure Start();
    procedure SetScreenParams(w, h: integer; fullScr: boolean = False);    //Before Start
    procedure SetCaption(input: string);
    function GetScreenW(): integer;
    function GetScreenH(): integer;

    procedure AddScene(Scene: TScene);
    procedure DelScene(inputID: string);    //return index of searching scene
    procedure UnFreezeScene(inputID: string);
    procedure FreezeScene(inputID: string);
    procedure HideScene(inputID: string);
    procedure ShowScene(inputID: string);
    procedure PlayScene(inputID: string);
    procedure PauseScene(inputID: string);
    procedure SwapScenes(ID1, ID2: string);

    procedure HideCursor;
    procedure ShowCursor;

    function getTime: double;

    procedure Draw;
    procedure Init;
    procedure Proc(dt: double);
    procedure Exit;
    {---public declarations---}
  end;
//MainCoreClass

//ZenGL Registred procedures  (not in class)
procedure ZenInit;
procedure ZenDraw;
procedure ZenProc(dt: double);
procedure ZenExit;
//ZenGL Registred procedures  (not in class)

var
  corePointer: TCore; {Core Pointer}   {You don't say???}

implementation

procedure TCore.SetCaption(input: string);
begin
  wnd_SetCaption(input);
end;

constructor TCore.Create;
begin
  corePointer := self;
  scenes := nil;
  loaded := False;
end;

destructor TCore.Destroy;
begin
  corePointer := nil;
end;

procedure TCore.CoreInit();
begin
  scr_SetOptions(ScreenW, ScreenH, REFRESH_MAXIMUM, FullScreen, True);
  //add change method
  //   wnd_ShowCursor(True);  // Разрешаем курсор мыши.    //add change method
  wnd_SetCaption('Cubiz.PixelWars');                 //add change method
  zgl_Reg(SYS_LOAD, @ZenInit);      // for what?
  zgl_Reg(SYS_DRAW, @ZenDraw);     // aadd method
  zgl_Reg(SYS_EXIT, @ZenExit);       //add method
  zgl_Reg(SYS_UPDATE, @ZenProc);
  //zgl_Disable(APP_USE_AUTOPAUSE);
  zgl_Init();
end;

procedure TCore.Start();
begin
  randomize;
  loaded := True;
  CoreInit;
end;

procedure TCore.SetScreenParams(w, h: integer; fullScr: boolean = False);
begin
  ScreenW := w;
  ScreenH := h;
  FullScreen := fullScr;
  scr_SetVSync(True);
  scr_SetOptions(ScreenW, ScreenH, REFRESH_DEFAULT, FullScreen, True);
end;

function TCore.GetScreenW(): integer;
begin
  Result := ScreenW;
end;

function TCore.GetScreenH(): integer;
begin
  Result := ScreenH;
end;

procedure TCore.Init;
var
  i: integer;
begin
  snd_Init();
  if length(scenes) >= 0 then
    for i := 0 to length(scenes) - 1 do
      scenes[i].Init();
end;

procedure TCore.Draw;
var
  i: integer;
begin
  if length(scenes) <> 0 then
    for i := 0 to length(scenes) - 1 do
      if scenes[i].GetVisible = True then
      begin
        if scenes[i].ID <> 'cursor' then
          scenes[i].Draw();
      end;
  if FindScene('cursor') >= 0 then
    if CursorState = True then
      scenes[FindScene('cursor')].Draw();
end;

procedure TCore.Proc(dt: double);
var
  i: integer;
begin
  time += dt;
  if length(scenes) <> 0 then
    for i := 0 to length(scenes) - 1 do
      if scenes[i].GetFreezed = False then
        scenes[i].Proc(dt);
  //Debug
  //wnd_setCaption(IntToStr(zgl_GET(RENDER_FPS)));
  //wnd_setCaption(floattostr(dt));
end;

procedure TCore.Exit;
var
  i: integer;
begin
  if length(scenes) <> 0 then
    for i := length(scenes) - 1 downto 0 do
    begin
      if scenes[i] <> nil then
        //3333DECb !!!!
      begin
        DelScene(scenes[i].ID);
      end;
    end;
end;

procedure TCore.AddScene(Scene: TScene);
var
  lastElement: integer;
begin
  lastElement := Length(scenes); {Last element in array}
  setlength(scenes, lastElement + 1);
  scenes[lastElement] := Scene;
  if loaded = True then
    scenes[lastelement].Init();
end;

procedure TCore.DelScene(inputID: string);
var
  i: integer;
  tempnum: integer;
begin
  tempnum := Self.FindScene(inputID);
  if tempnum >= 0 then
  begin
    Scenes[tempnum].Exit;
    Scenes[tempnum].ClearTimers;
    Scenes[tempnum].Free;
    for i := tempnum to length(Scenes) - 2 do
      Scenes[i] := Scenes[i + 1];
    setlength(Scenes, length(Scenes) - 1);
  end;
end;

function TCore.FindScene(inputID: string): integer;
var
  i: integer;
begin
  Result := -1;
  for i := 0 to length(scenes) - 1 do
  begin
    if scenes[i].GetID = LowerCase(inputID) then
    begin
      Result := i;
      break;
    end;
  end;
end;

procedure TCore.UnFreezeScene(inputID: string);
var
  a: integer;
begin
  a := FindScene(LowerCase(inputID));
  if a >= 0 then
    Scenes[a].Unfreeze();
end;

procedure TCore.FreezeScene(inputID: string);
var
  a: integer;
begin
  a := FindScene(LowerCase(inputID));
  if a >= 0 then
    Scenes[a].Freeze();
end;

procedure TCore.HideScene(inputID: string);
var
  a: integer;
begin
  a := FindScene(LowerCase(inputID));
  if a >= 0 then
    Scenes[a].Hide();
end;

procedure TCore.ShowScene(inputID: string);
var
  a: integer;
begin
  a := FindScene(LowerCase(inputID));
  if a >= 0 then
    Scenes[a].Show();
end;

procedure TCore.PlayScene(inputID: string);
begin
  UnfreezeScene(inputID);
  ShowScene(inputID);
end;

procedure TCore.PauseScene(inputID: string);
begin
  FreezeScene(inputID);
  HideScene(inputID);
end;

procedure TCore.SwapScenes(ID1, ID2: string);
var
  Swapper1, Swapper2: integer;
  buffer: TScene;
begin
  Swapper1 := Self.FindScene(ID1);
  Swapper2 := Self.FindScene(ID2);
  if (swapper1 >= 0) and (swapper2 >= 0) then
  begin
    buffer := Scenes[Swapper1];
    Scenes[Swapper1] := Scenes[Swapper2];
    Scenes[Swapper2] := buffer;
  end;
end;

{cursor}
procedure TCore.HideCursor;
begin
  CursorState := False;
end;

procedure TCore.ShowCursor;
begin
  CursorState := True;
end;

function TCore.getTime: double;
begin
  Result := time;
end;

//ZenGL Registred procedures  (not in class)
procedure ZenInit;
begin
  CorePointer.Init;
end;

procedure ZenDraw;
begin
  CorePointer.Draw;
end;

procedure ZenProc(dt: double);
begin
  CorePointer.proc(dt);
end;

procedure ZenExit;
begin
  CorePointer.Exit;
end;

//ZenGL Registred procedures  (not in class)

end.
