unit uMenu;

interface

uses
  Classes,
  ElysionKronos;

type

  TMenuLayout = (mlVertical, mlHorizontal);

  // Not completely intermediate GUI, but going in the right direction ;)
  TMenu = class(TelObject)
  private
    fAnimUp: Boolean;

    fButtonList: TList;
    fNumButtons: Integer;

    fHoverSplit, fImageSplit, fHoverAnimation: Boolean;
    fStdRect, fHoverRect: TelRect;

    function getCount: Integer;
    function getHeight: Integer;
    function getWidth: Integer;
    procedure AnimateButton(aID: Integer);
  public
    Bounds: TelPoint;
    Spacing: Integer;

    StandardColor: TelColor;
    HoverColor: TelColor;

    constructor Create();
	destructor Destroy; Override;

    procedure setButtons(const ButtonImage, ButtonFont: String; FontSize: Integer; Buttons: array of String);
	
	function OnButtonClick(aID: Integer): Boolean; Overload;
	function OnButtonClick(Caption: String): Boolean; Overload; // Maybe improve => Runtime: O(n)

    function OnButtonMouseOver(aID: Integer): Boolean; Overload;
    function OnButtonMouseOver(Caption: String): Boolean; Overload; // Maybe improve => Runtime: O(n)

    function getButton(aID: Integer): TelButton; Overload;
    function getButton(Caption: String): TelButton; Overload; // Maybe improve => Runtime: O(n)

    procedure Draw;
    procedure Update;
  published
    property Count: Integer read getCount;
    property Height: Integer read getHeight;
    property Width: Integer read getWidth;

    property HoverSplit: Boolean read fHoverSplit write fHoverSplit;
    property ImageSplit: Boolean read fImageSplit write fImageSplit;

    property HoverAnimation: Boolean read fHoverAnimation write fHoverAnimation;
  end;

implementation

constructor TMenu.Create;
begin
  inherited Create;

  StandardColor := makeCol(192, 192, 192);
  HoverColor := makeCol(255, 255, 255);

  fButtonList := TList.Create;
  fAnimUp := true;
end;

procedure TMenu.setButtons(const ButtonImage, ButtonFont: String; FontSize: Integer; Buttons: array of String);
var
  tmpButton: TelButton;
  i: Integer;
begin


  if ((ButtonImage <> '') and (ButtonFont <> '')) then
  begin
    if Length(Buttons) >= 0 then
    begin


      (*
      // DEBUG
      TelLogger.getInstance.writeLog('Length of Array Buttons: ' + IntToStr(Length(Buttons)));
      TelLogger.getInstance.writeLog('Length of Array fNumButtons: ' + IntToStr(fNumButtons));
      TelLogger.getInstance.writeLog('Length of Array fButton:' + IntToStr(Length(fButton)));
      *)

      for i := 0 to Length(Buttons) - 1 do
      begin
        tmpButton := TelButton.Create;
        tmpButton.LoadFromFile(ButtonImage);
        tmpButton.LoadFont(ButtonFont, FontSize);

        if ImageSplit then
        begin
          fStdRect := makeRect(0, 0, tmpButton.Sprite.SurfaceWidth div 2, tmpButton.Sprite.SurfaceHeight);
          fHoverRect := makeRect(tmpButton.Sprite.SurfaceWidth div 2, 0, tmpButton.Sprite.SurfaceWidth div 2, tmpButton.Sprite.SurfaceHeight);

          tmpButton.ClipImage(fStdRect);
        end;

        tmpButton.Caption := Buttons[i];

        tmpButton.Sprite.Color := StandardColor;

        fButtonList.Add(tmpButton);
      end;
    end;
  end;
end;

destructor TMenu.Destroy;
begin
  fButtonList.Free;
end;

// TODO: Make that procedure DeltaTime-dependant
procedure TMenu.AnimateButton(aID: Integer);
begin
  if TelButton(fButtonList.Items[aID]).Sprite.Color.R = 255 then fAnimUp := false;
  if TelButton(fButtonList.Items[aID]).Sprite.Color.R = 192 then fAnimUp := true;

  if fAnimUp then
  begin
    TelButton(fButtonList.Items[aID]).Sprite.Color.R := TelButton(fButtonList.Items[aID]).Sprite.Color.R + 1;
    TelButton(fButtonList.Items[aID]).Sprite.Color.G := TelButton(fButtonList.Items[aID]).Sprite.Color.G + 1;
    TelButton(fButtonList.Items[aID]).Sprite.Color.B := TelButton(fButtonList.Items[aID]).Sprite.Color.B + 1;
  end else
  begin
    TelButton(fButtonList.Items[aID]).Sprite.Color.R := TelButton(fButtonList.Items[aID]).Sprite.Color.R - 1;
    TelButton(fButtonList.Items[aID]).Sprite.Color.G := TelButton(fButtonList.Items[aID]).Sprite.Color.G - 1;
    TelButton(fButtonList.Items[aID]).Sprite.Color.B := TelButton(fButtonList.Items[aID]).Sprite.Color.B - 1;
  end;

end;

function TMenu.getCount: Integer;
begin
  Result := fButtonList.Count;
end;

function TMenu.getHeight: Integer;
begin
  Result := Self.Count * (TelButton(fButtonList.Items[0]).Height + Spacing);
end;

function TMenu.getWidth: Integer;
begin
  Result := (TelButton(fButtonList.Items[0])).Width;
end;

function TMenu.OnButtonClick(aID: Integer): Boolean;
begin
  Result := (TelButton(fButtonList.Items[aID])).OnClick;
end;

function TMenu.OnButtonClick(Caption: String): Boolean;
var
  i: Integer;
begin
  for i := 0 to fButtonList.Count - 1 do
  begin
    if (TelButton(fButtonList.Items[i]).Caption = Caption) then
    begin
      Result := (TelButton(fButtonList.Items[i])).OnClick;
      Exit;
    end;
  end;
end;

function TMenu.OnButtonMouseOver(aID: Integer): Boolean;
begin
  Result := (TelButton(fButtonList.Items[aID])).OnMouseOver;
end;

function TMenu.OnButtonMouseOver(Caption: String): Boolean;
var
  i: Integer;
begin
  for i := 0 to fButtonList.Count - 1 do
  begin
    if (TelButton(fButtonList.Items[i]).Caption = Caption) then
    begin
      Result := (TelButton(fButtonList.Items[i])).OnMouseOver;
      Exit;
    end;
  end;
end;

function TMenu.getButton(aID: Integer): TelButton;
begin
  Result := (TelButton(fButtonList.Items[aID]));
end;

function TMenu.getButton(Caption: String): TelButton;
var
  i: Integer;
begin
  for i := 0 to fButtonList.Count - 1 do
  begin
    if ((TelButton(fButtonList.Items[i])).Caption = Caption) then
    begin
      Result := (TelButton(fButtonList.Items[i]));
      Exit;
    end;
  end;
end;

procedure TMenu.Draw;
var
  i: Integer;
begin
  for i := 0 to fButtonList.Count - 1 do
  begin
    (TelButton(fButtonList.Items[i])).Position := makeP3D(Bounds.X, Bounds.Y + i * (TelButton(fButtonList.Items[i]).Height + Spacing));
    (TelButton(fButtonList.Items[i])).Draw;
  end;
end;

procedure TMenu.Update;
var
  i: Integer;
begin
  if HoverSplit then
  begin
    if (TelButton(fButtonList.Items[i])).OnMouseOver then
      (TelButton(fButtonList.Items[i])).ClipImage(fHoverRect)
      else (TelButton(fButtonList.Items[i])).ClipImage(fStdRect);
  end else
  begin
    if ((StandardColor.R <> HoverColor.R) or
        (StandardColor.G <> HoverColor.G) or
        (StandardColor.B <> HoverColor.B)) then
    begin
      for i := 0 to fButtonList.Count - 1 do
      begin
          if (TelButton(fButtonList.Items[i])).OnMouseOver then
          begin
            if HoverAnimation then AnimateButton(i)
              else (TelButton(fButtonList.Items[i])).Sprite.Color := HoverColor;
          end else (TelButton(fButtonList.Items[i])).Sprite.Color := StandardColor;
      end;
    end;
  end;

end;

end.
