// Form that functions as both a way to edit or add users to the database
// Author: Cameron Hayes

unit View.EditUser;

interface

uses
  System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
  WEBLib.Forms, WEBLib.Dialogs, Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls,
  WEBLib.DBCtrls, XData.Web.Client, WEBLib.ExtCtrls, Vcl.Menus, WEBLib.Menus;

type
  TFViewEditUser = class(TWebForm)
    WebLabel2: TWebLabel;
    WebLabel3: TWebLabel;
    WebLabel5: TWebLabel;
    WebLabel6: TWebLabel;
    WebLabel7: TWebLabel;
    edtConfirmPassword: TWebEdit;
    edtEmail: TWebEdit;
    edtPassword: TWebEdit;
    btnConfirm: TWebButton;
    edtFullname: TWebEdit;
    edtUsername: TWebEdit;
    XDataWebClient1: TXDataWebClient;
    btnCancel: TWebButton;
    WebTimer1: TWebTimer;
    lblactive: TWebLabel;
    cbStatus: TWebCheckBox;
    lblRights: TWebLabel;
    edtRights: TWebEdit;
    lblAccess: TWebLabel;
    cbAccess: TWebComboBox;
    lblQB: TWebLabel;
    edtQB: TWebEdit;
    procedure WebFormCreate(Sender: TObject);
    procedure btnConfirmClick(Sender: TObject);
    procedure btnCancelClick(Sender: TObject);
    procedure WebTimer1Timer(Sender: TObject);
    procedure edtPasswordChange(Sender: TObject);
    procedure edtConfirmPasswordChange(Sender: TObject);
  private
    { Private declarations }
    FMessage: string;
    Mode: string;
    Username: string;
    Password: string;
    FullName: string;
    Status: string;
    Email: string;
    Access: string;
    Rights: string;
    Perspective: string;
    QB: string;
    [async] procedure EditUser();
    [async] function AddUser(): string;
    procedure ValidatePasswords;
  public
    { Public declarations }
    Info: string;
    class function CreateForm(AElementID, Mode, Username, Password, Name, Status, Email,
                               Access, Rights, Perspective, QB: string): TWebForm;
  end;

var
  FViewEditUser: TFViewEditUser;

implementation

uses
Windows,
View.Main,
View.Users,
VCL.Dialogs,
ConnectionModule,
Utils;

procedure TFViewEditUser.btnCancelClick(Sender: TObject);
// Cancels the edit or addition
begin
  Info := 'Failure: Changes discarded!';
  FViewMain.ShowUserForm(Info);
end;


function TFViewEditUser.AddUser: string;
// Sends UserInfo over to the server so it can be added to the database
var
  userInfo: string;
  xdcResponse: TXDataClientResponse;
  responseString: TJSObject;
begin
  userInfo := '&username=' + edtUsername.Text +
              '&fullname=' + edtFullName.Text +
              '&password=' + edtPassword.Text +
              '&status=' + BoolToStr(cbStatus.Checked) +
              '&email=' + edtEmail.Text +
              '&access=' + cbAccess.Text +
              '&newuser=' + edtUsername.Text +
              '&rights=' + edtRights.Text +
              '&QB=' + edtQB.Text;

  try
    xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.AddUser', [userInfo]));
    responseString := TJSObject(xdcResponse.Result);
    Info := string(responseString['value']);
  except
    on E: EXDataClientRequestException do
      Utils.ShowErrorModal('Could not add user: ' + E.ErrorResult.ErrorMessage);
  end;
end;


procedure TFViewEditUser.EditUser();
// Sends EditOptions over to the server so the given user can be editted
var
  editOptions: string;
  xdcResponse: TXDataClientResponse;
  responseString: TJSObject;
begin

  editOptions := 'username=' + Username +
                  '&fullname=' + edtFullName.Text +
                  '&password=' + edtPassword.Text +
                  '&status=' + BoolToStr(cbStatus.Checked) +
                  '&email=' + edtEmail.Text +
                  '&access=' + cbAccess.Text +
                  '&newuser=' + edtUsername.Text +
                  '&rights=' + edtRights.Text +
                  '&QB=' + edtQB.Text;

  console.log(editOptions);

  xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.EditUser',
        [editOptions]));
  responseString :=  TJSObject(xdcResponse.Result);
  Info := string(responseString['value']);

end;

procedure TFViewEditUser.edtConfirmPasswordChange(Sender: TObject);
begin
  ValidatePasswords;
end;

procedure TFViewEditUser.edtPasswordChange(Sender: TObject);
begin
  ValidatePasswords;
end;

class function TFViewEditUser.CreateForm(AElementID, Mode, Username, Password, Name, Status, Email,
                               Access, Rights, Perspective, QB: string): TWebForm;
// Autofills known information about a user on create
  procedure AfterCreate(AForm: TObject);
  begin
    TFViewEditUser(AForm).Mode := Mode;
    TFViewEditUser(AForm).Username := Username;
    TFViewEditUser(AForm).FullName := Name;
    TFViewEditUser(AForm).Status := Status;
    TFViewEditUser(AForm).Email := Email;
    TFViewEditUser(AForm).Access := Access;
    TFViewEditUser(AForm).Rights := Rights;
    TFViewEditUser(AForm).Perspective := Perspective;
    TFViewEditUser(AForm).QB := QB;
  end;

{$R *.dfm}
begin
  Application.CreateForm(TFViewEditUser, AElementID, Result, @AfterCreate);
end;



procedure TFViewEditUser.WebFormCreate(Sender: TObject);
// Autofills known information about a user on create
begin
  if FMessage <> '' then
    ShowToast(FMessage);
  edtUsername.Text := Username;
  edtFullName.Text := FullName;
  if Mode = 'Edit' then
  begin
    edtPassword.Text := 'hidden';
    edtConfirmPassword.Text := 'hidden';
  end;
  edtEmail.Text := Email;
  cbAccess.Text := Access;
  edtRights.Text := Rights;
  edtQB.Text :=  QB;
  if Status = 'ACTIVE' then
    cbStatus.checked := true;
end;

procedure TFViewEditUser.WebTimer1Timer(Sender: TObject);
begin
  WebTimer1.Enabled := False;
  Utils.HideSpinner('spinner');
  if (not Info.Contains('Failure')) then
  begin
    FViewMain.ShowUserForm(Info);
  end
  else
    showToast(Info);
  console.log('Info at Timer:' + Info);
end;


procedure TFViewEditUser.btnConfirmClick(Sender: TObject);
var
  FormEl: TJSHTMLFormElement;
begin
  FormEl := TJSHTMLFormElement(document.getElementById('edituserform'));

  if not FormEl.checkValidity then
  begin
    FormEl.classList.add('was-validated');
    Exit;
  end;

  Utils.ShowSpinner('spinner');

  if Mode = 'Edit' then
    EditUser
  else
    AddUser;

  WebTimer1.Enabled := True;
end;


procedure TFViewEditUser.ValidatePasswords;
var
  Pwd, Confirm: string;
  PwdInput, ConfirmInput: TJSHTMLInputElement;
begin
  PwdInput := TJSHTMLInputElement(edtPassword.ElementHandle);
  ConfirmInput := TJSHTMLInputElement(edtConfirmPassword.ElementHandle);

  Pwd := PwdInput.value.Trim;
  Confirm := ConfirmInput.value.Trim;

  // Disable confirm until password exists
  if Pwd = '' then
  begin
    ConfirmInput.disabled := True;
    ConfirmInput.value := '';
    ConfirmInput.setCustomValidity('');
    ConfirmInput.classList.remove('is-invalid');
    ConfirmInput.classList.remove('is-valid');
  end
  else
  begin
    ConfirmInput.disabled := False;

    // Live match check
    if Confirm = '' then
    begin
      ConfirmInput.setCustomValidity('');
      ConfirmInput.classList.remove('is-invalid');
      ConfirmInput.classList.remove('is-valid');
    end
    else if Confirm = Pwd then
    begin
      ConfirmInput.setCustomValidity('');
      ConfirmInput.classList.add('is-valid');
      ConfirmInput.classList.remove('is-invalid');
    end
    else
    begin
      ConfirmInput.setCustomValidity('Passwords must match');
      ConfirmInput.classList.add('is-invalid');
      ConfirmInput.classList.remove('is-valid');
    end;
  end;
end;


end.
