unit UMainMenu;

interface


uses
  Squall,
  JEN_Header,
  JEN_Math,
  Main,
  UDirector,
  USprite;

type
  TMenuElement = (elNewGame, elHighScoresel, elDelimiter, elExit);
  THighscoreElement = (elHs1, elHs2, elHs3, elHs4, elHs5, elHs6, elHs7, elHs8, elHs9, elHs10, elRetrun);
  TAction = (actNone, actGame, actHighScore, actReturn, actExit);

  TButton = class
    constructor Create(const Text: string; const pos: TVec2f;  action: TAction);
    destructor Destroy; override;
    public
      Text   : String;
      Rect   : TRectf;
      HighLight  : Single;
      Action : TAction;
      Alpha  : Single;
      isHide : Boolean;
      procedure Hide;
      procedure Show;
      procedure Update(dt: LongInt);
      procedure Draw;
  end;

  TMenuScene = class(TScene)
  private
    FChannel     : LongInt;
    FinHighScore : Boolean;
    FLoadGame    : Boolean;
    FMenuButton  : array[TMenuElement] of TButton;
    FHighScoreButton: array[THighscoreElement] of TButton;
    FBackGround  : ITexture;
    FShader      : IShaderProgram;
    FTimeUniform : IShaderUniform;
    FWidthUniform: IShaderUniform;
    FPanel       : TSprite;
  public
    function GetName: String; override;
    procedure SetInHighscore(value: Boolean);
    procedure LoadGame;
    procedure Load; override;
    procedure UnLoad; override;
    procedure Update(dt: LongInt); override;
    procedure Draw; override;


    property inHighscore: Boolean write SetInHighscore;
  end;

var
  SelectBlock : ITexture;
  PanelWidth  : Single;

const
  ElementName : array[TMenuElement] of string = ('New game', 'High Scores', '', 'Exit');
  MenuActions : array[TMenuElement] of TAction = (actGame,  actHighScore, actNone, actExit);
  HighScoreActions: array[THighscoreElement] of TAction = (actNone, actNone, actNone, actNone, actNone, actNone, actNone, actNone, actNone, actNone, actReturn);

implementation

function TMenuScene.GetName: String;
begin
  Result := 'Menu';
end;

procedure TMenuScene.SetInHighscore(value: Boolean);
var
  Melement: TMenuElement;
  Helement: THighscoreElement;
begin
  FinHighScore := Value;
  if Value then
  begin
    for Melement := Low(TMenuElement) to High(TMenuElement) do
      FMenuButton[Melement].Hide;

    for Helement := Low(THighscoreElement) to High(THighscoreElement) do
      FHighScoreButton[Helement].Show;
  end else
  begin
    for Melement := Low(TMenuElement) to High(TMenuElement) do
      FMenuButton[Melement].Show;

    for Helement := Low(THighscoreElement) to High(THighscoreElement) do
      FHighScoreButton[Helement].Hide;
  end;
end;

procedure TMenuScene.LoadGame;
var
  Melement: TMenuElement;
begin
  for Melement := Low(TMenuElement) to High(TMenuElement) do
    FMenuButton[Melement].Hide;
  FLoadGame := true;
end;

procedure TMenuScene.Load;
var
  Melement: TMenuElement;
  Helement: THighscoreElement;
  sr     : IShaderResource;
  xml    : IXML;
  node   : IXML;
begin
  FChannel := SQUALL_Sample_LoadFile('Media\DST-909Dreams.mp3', 1, 0);
  SQUALL_Sample_Play(FChannel, 1, 0, 1);

  Display.Cursor := True;
  FinHighScore := False;
  FLoadGame := False;

  ResMan.Load('Media\BackgroundMenu.dds', FBackGround);
  ResMan.Load('Media\BackgroundMenu.xml', sr);
  ResMan.Load('Media\fix.dds', SelectBlock);
  sr.Compile(FShader);
  FTimeUniform := FShader.Uniform('time', utVec1);
  FWidthUniform := FShader.Uniform('width', utVec1);

  PanelWidth   := Game.ScreenWidth * 0.25;
  FPanel := TSprite.Create(SelectBlock);
  FPanel.Pos := Vec2f(Game.ScreenWidth, Game.ScreenHeight) * 0.5;
  FPanel.AnchorPoint := Vec2f(0.5, 0.5);
  FPanel.ScaleX := (PanelWidth) * 0.25;
  FPanel.ScaleY := Game.ScreenHeight;
  FPanel.Color  := Vec4f(0,0,0,0.4);

  Helpers.CreateXMLReader(xml, 'scores.xml');

  for Melement := Low(TMenuElement) to High(TMenuElement) do
  begin
    FMenuButton[Melement] := TButton.Create(ElementName[Melement], Vec2f(Game.ScreenWidth * 0.5, Game.ScreenHeight * 0.5 + (Ord(Melement) - 0.5 - Ord(High(TMenuElement)) *0.5) * 70),  MenuActions[Melement]);
    FMenuButton[Melement].Show;
  end;

  for Helement := Low(THighscoreElement) to High(THighscoreElement) do
  begin
    if Helement <> elRetrun then
    begin
      node := xml.NodeI[Ord(Helement)];
      FHighScoreButton[Helement] := TButton.Create(node.Tag + ' ' + node.Params['score'].Value, Vec2f(Game.ScreenWidth * 0.5, Game.ScreenHeight * 0.5 + (Ord(Helement)  - 0.5 - Ord(High(THighscoreElement)) *0.5) * 50),  HighScoreActions[Helement])
    end else
      FHighScoreButton[Helement] := TButton.Create('Exit', Vec2f(Game.ScreenWidth * 0.5, Game.ScreenHeight * 0.5 + (Ord(Helement)  - 0.5 - Ord(High(THighscoreElement)) *0.5) * 50+ 40) ,  HighScoreActions[Helement])
  end;
end;

procedure TMenuScene.UnLoad;
var
  Melement: TMenuElement;
  Helement: THighscoreElement;
begin
  SQUALL_Sample_Stop(FChannel);
  SQUALL_Sample_Unload(FChannel);
  FShader := nil;
  FBackGround := nil;
  SelectBlock := nil;
  FPanel.Free;
  for Melement := Low(TMenuElement) to High(TMenuElement) do
    FMenuButton[Melement].Free;
  for Helement := Low(THighscoreElement) to High(THighscoreElement) do
    FHighScoreButton[Helement].Free;
end;

procedure TMenuScene.Update;
var
  Melement: TMenuElement;
  Helement: THighscoreElement;
begin
  if FLoadGame then
  begin
    if PanelWidth = 0 then
    begin
       Helpers.Sleep(1000);
       Game.SceneDirector.LoadScene('Game');
    end;

    PanelWidth := Max(PanelWidth - dt * 0.5, 0);
  end else
    if FinHighscore then
      PanelWidth := Min(PanelWidth + dt * 0.5, Game.ScreenWidth * 0.6)
    else
      PanelWidth := Max(PanelWidth - dt * 0.5, Game.ScreenWidth *  0.25);

  FPanel.ScaleX := (PanelWidth) * 0.25;

  for Melement := Low(TMenuElement) to High(TMenuElement) do
    FMenuButton[Melement].Update(dt);

  for Helement := Low(THighscoreElement) to High(THighscoreElement) do
    FHighScoreButton[Helement].Update(dt);
end;

procedure TMenuScene.Draw;
var
  Melement: TMenuElement;
  Helement: THighscoreElement;
  time   : Single;
  width  : Single;
begin

  Render2d.BeginDraw(FShader, FBackGround.Frame);
  time := Helpers.Time * 0.0002;
  width := PanelWidth/Game.ScreenWidth;
  FTimeUniform.Value(time);
  FWidthUniform.Value(width);
  Render2d.DrawQuad(0, 0, Game.ScreenWidth, Game.ScreenHeight, 0);
  Render2d.EndDraw;

  FPanel.Draw;

  Render2d.BatchBegin;
  for Melement := Low(TMenuElement) to High(TMenuElement) do
    FMenuButton[Melement].Draw;

  for Helement := Low(THighscoreElement) to High(THighscoreElement) do
    FHighScoreButton[Helement].Draw;
  Render2d.BatchEnd;
end;

constructor TButton.Create(const Text: string; const pos: TVec2f; action: TAction);
begin
  Game.Font.Scale := 0.10;

  Self.Action := Action;
  Self.Text := Text;
  Self.Rect := Rectf(pos, Game.Font.GetTextWidth(PWideChar(Text)), 500 * Game.Font.Scale);
  Self.Rect.Offset(Self.Rect.Size * Vec2f(-0.5, 0));
  HighLight := 0;
  Alpha := 0;
  isHide := True;
end;

destructor TButton.Destroy;
begin

end;

procedure TButton.Show;
begin
  isHide := False;
end;

procedure TButton.Hide;
begin
  isHide := True;
end;

procedure TButton.Update(dt: LongInt);
begin
  if isHide then
  begin
    HighLight := Max(HighLight - dt * 0.01, 0.0);
    Alpha := Max(Alpha - dt * 0.005, 0.0);
    Exit;
  end;

  Alpha :=  Min(Alpha + dt * 0.005, 1);

  if Rect.Contains(Input.Mouse.Pos) then
    HighLight := Min(HighLight + dt * 0.007, 0.2)
  else
    HighLight := Max(HighLight - dt * 0.003, 0.0);

  if Input.Hit[ikMouseL] and Rect.Contains(Input.Mouse.Pos) then
  begin
    case Action of
      actGame: TMenuScene(Game.SceneDirector.CurrectScene).LoadGame;
      actHighScore: TMenuScene(Game.SceneDirector.CurrectScene).inHighScore := True;
      actExit: Engine.Finish;
      actReturn:TMenuScene(Game.SceneDirector.CurrectScene).inHighScore := False;
    end;
  end;

end;

procedure TButton.Draw;
begin
   if Text = '' then
    Exit;


  game.Font.Color := Vec4f(0.8, 0.9, 1, Alpha);
  Render2d.DrawSprite(SelectBlock.Frame, (Game.ScreenWidth - PanelWidth) * 0.5, Self.Rect.Location.y, PanelWidth, Self.Rect.Height, Vec4f(1, 1, 1, HighLight));
  Game.Font.Print(PWideChar(Text), Self.Rect.Location.x, Self.Rect.Location.y);
  { Game.BluredFont.SetGradColors(Vec4f(1, 0.7, 0.5, 1), Vec4f(1, 0.3, 0.1, 1));
   Game.BluredFont.EdgeSmooth := 2;
   Game.BluredFont.Print(PWideChar(Text), Self.Rect.Location.x, Self.Rect.Location.y);
         }
   end;


end.
