{
  TODO
  + Падение текущей фигуры и ее остановка на линии
  + Подсветка текущей ограничивающей линии
  + Фиксация упавших фигур

  + Проверка на возможность поворота
  + Проверка на возможность добавления фигуры
  + Поправить линии

  + Сгорание фигур - как?

  + GameOver

  + Увеличение скорости
 -+ Увеличение порога блоков на сгорание / увеличение отсчета до сгорания
  + Уплотнение слева и справа
  + Вывод очков на экран
  + Вывод скорости на экран
  + Плавное исчезновение удаляемых блоков

  + GameOver - вывод очков
  + Музыка
  + Звук падения блоков
    Звук удаления блоков
  + Помощь по сгорающим блокам
    Следующая фигура

  + BUG: неправильное схлопаывание блоков
}

program multitetris;
uses
  ShareMem,
  Windows,
  uGlobal in 'uGlobal.pas',
  uSound in 'uSound.pas',
  uGameScreen.Game in 'gamescreens\uGameScreen.Game.pas',
  uGameScreen.GameOver in 'gamescreens\uGameScreen.GameOver.pas',
  uGameScreen.MainMenu in 'gamescreens\uGameScreen.MainMenu.pas',
  uGameScreen in 'gamescreens\uGameScreen.pas',
  uGameScreenManager in 'gamescreens\uGameScreenManager.pas',
  uField in 'uField.pas',
  bass in 'ext\bass.pas',
  dfTweener in 'ext\dfTweener.pas',
  glr in 'ext\glr.pas',
  glrMath in 'ext\glrMath.pas',
  glrUtils in 'ext\glrUtils.pas',
  ogl in 'ext\ogl.pas';

var
  gsManager: TpdGSManager;
  bigPause: Boolean;

  procedure OnUpdate(const dt: Double);
  begin
    if GSManager.IsQuitMessageReceived then
      R.Stop();

    if R.Input.IsKeyPressed(VK_PAUSE) then
      bigPause := not bigPause;

    if not bigPause then
    begin
      gsManager.Update(dt);
      Tweener.Update(dt);
    end;
  end;

  procedure OnMouseMove(X, Y: Integer; Shift: TglrMouseShiftState);
  begin
    if Assigned(gsManager.Current) then
      gsManager.Current.OnMouseMove(X, Y, Shift);
  end;

  procedure OnMouseDown(X, Y: Integer; MouseButton: TglrMouseButton;
    Shift: TglrMouseShiftState);
  begin
    if Assigned(gsManager.Current) then
      gsManager.Current.OnMouseDown(X, Y, MouseButton, Shift);
  end;

  procedure OnMouseUp(X, Y: Integer; MouseButton: TglrMouseButton;
    Shift: TglrMouseShiftState);
  begin
    if Assigned(gsManager.Current) then
      gsManager.Current.OnMouseUp(X, Y, MouseButton, Shift);
  end;

begin
  Randomize();
  LoadRendererLib();
  gl.Init();

  R := glrGetRenderer();
  R.Init('settings_tetris.txt');
  R.OnUpdate := OnUpdate;
  R.OnMouseMove := OnMouseMove;
  R.OnMouseDown := OnMouseDown;
  R.OnMouseUp := OnMouseUp;
  R.Camera.ProjectionMode := pmOrtho;
  R.WindowCaption := PWideChar('MultiTetris — разносторонний тетрис. Версия '
    + GAMEVERSION + ' [glRenderer ' + R.VersionText + ']');
  Factory := glrGetObjectFactory();

  InitializeGlobal();
  gsManager := TpdGSManager.Create();
  mainMenu := TpdMainMenu.Create();
  game := TpdGame.Create();
  gameOver := TpdGameOver.Create();

  mainMenu.SetGameScreenLinks(game);
  game.SetGameScreenLinks(gameOver, mainMenu);
  gameOver.SetGameScreenLinks(mainMenu, game);

  gsManager.Add(mainMenu);
  gsManager.Add(game);
  gsManager.Add(gameOver);
  {$IFDEF DEBUG}
  gsManager.Notify(game, naSwitchTo);
  {$ELSE}
  gsManager.Notify(mainMenu, naSwitchTo);
  {$ENDIF}

  R.Start();

  gsManager.Free();
  FinalizeGlobal();

  R.DeInit();
  R._Release();
  R := nil;
  UnLoadRendererLib();
end.
