unit foLogin;

// this code is under the BAF fair use license (BFUL) - https://bafbal.de/index.php?title=Bful
// the login form

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
  FMX.ListBox, FMX.Edit, FMX.Controls.Presentation, System.IniFiles, FMX.Styles,
  System.Hash, Winapi.ShlObj;

type
  TfrmLogin = class(TForm)
    lblUsername: TLabel;
    lblPassword: TLabel;
    edtUsername: TEdit;
    edtPassword: TEdit;
    lblDatabase: TLabel;
    cmbDatabase: TComboBox;
    btnOk: TButton;
    btnAbort: TButton;
    Panel1: TPanel;
  private
    FIni2: TMemIniFile;
    procedure Init;
  public
    class function Login: boolean;
  end;

var
  gvDbIndex: integer;
  gvUsername, gvPasswordHash: string;


implementation

{$R *.fmx}

uses dmMain;

{ TfrmLogin }

procedure TfrmLogin.Init;
// Loads the database connections from the ini
var
  LIni: TMemIniFile;
  LRoot, LCat, LStyleName, s: string;
  i, LCount, LScale: integer;
  LRect: TRectF;
begin
  LRoot := ExtractFilePath(ParamStr(0));
  LIni := TMemIniFile.Create(LRoot + 'BafClientFM.ini');
  try
    LCount := LIni.ReadInteger('DB', 'count', 0);
    for i := 1 to LCount do begin
      LCat := Trim(LIni.ReadString('DB', 'db_' + IntToStr(i), ''));
      if LCat <> '' then
        cmbDatabase.Items.Add(LIni.ReadString(LCat, 'Name', ''));
    end;
    cmbDatabase.ItemIndex := LIni.ReadInteger('DB', 'default', 0);
    edtUsername.Text := LIni.ReadString('LOGIN', 'username', '');
    edtPassword.Text := LIni.ReadString('LOGIN', 'password', '');
    LStyleName := LIni.ReadString('STYLE', 'name', 'BafLight.style');
    TStyleManager.SetStyleFromFile(LRoot + 'styles\' + LStyleName);

    if edtUsername.Text = '' then begin
      s := dataMain.GetSpecialFolder(CSIDL_APPDATA) + '\BAF\BafClient';
      ForceDirectories(s);
      FIni2 := TMemIniFile.Create(s + '\BafClientFM.ini');
      edtUsername.Text := FIni2.ReadString('LOGIN', 'username', '');
    end;

    LScale := LIni.ReadInteger('LOGIN', 'scale', 100);
    Panel1.Scale.X := LScale / 100;
    Panel1.Scale.Y := LScale / 100;
    ClientWidth := 218 * LScale div 100;
    ClientHeight := 251 * LScale div 100;
    Application.ProcessMessages;              // seems needed...
    ClientWidth := 218 * LScale div 100;
    ClientHeight := 251 * LScale div 100;
    LRect := Screen.Displays[0].WorkareaRect;
    Left := round((LRect.Width - Width) / 2);
    Top := round((LRect.Height - Height) / 2);
    if edtUsername.Text = '' then
      edtUsername.SetFocus
    else
      edtPassword.SetFocus;
  finally
    LIni.Free;
  end;
end;

class function TfrmLogin.Login: boolean;
var
  LForm: TfrmLogin;
begin
  LForm := TfrmLogin.Create(nil);
  try
    LForm.Init;
    result := (LForm.ShowModal = mrOk) ;
    gvDbIndex := LForm.cmbDatabase.ItemIndex + 1;
    gvUsername := LForm.edtUsername.Text;
    gvPasswordHash := THashSHA2.GetHashString(LForm.edtPassword.Text,
          THashSHA2.TSHA2Version.SHA512);

    if Assigned(LForm.FIni2) then begin
      LForm.FIni2.WriteString('LOGIN', 'username', LForm.edtUsername.Text);
      LForm.FIni2.UpdateFile;
      FreeAndNil(LForm.FIni2);
    end;
  finally
    LForm.Free;
  end;
end;

end.
