unit View.Users;

interface

uses
  System.SysUtils, System.Classes, Web, WEBLib.Graphics, WEBLib.Forms, WEBLib.Dialogs,
  Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls, WEBLib.Controls, WEBLib.Grids, WebLib.Lists,
  XData.Web.Client, WEBLib.ExtCtrls, DB, XData.Web.JsonDataset,
  XData.Web.Dataset, XData.Web.Connection, Vcl.Forms, WEBLib.DBCtrls, JS;

type
  TFViewUsers = class(TWebForm)
    XDataWebClient1: TXDataWebClient;
    XDataWebDataSet1: TXDataWebDataSet;
    lblEntries: TWebLabel;
    btnAddUser: TWebButton;
    WebDataSource1: TWebDataSource;
    XDataWebDataSet1userID: TStringField;
    XDataWebDataSet1username: TStringField;
    XDataWebDataSet1password: TStringField;
    XDataWebDataSet1full_name: TStringField;
    XDataWebDataSet1phone_number: TStringField;
    XDataWebDataSet1email_address: TStringField;
    XDataWebDataSet1admin: TBooleanField;
    btnConfirmDelete: TWebButton;
    pnlMessage: TWebPanel;
    lblMessage: TWebLabel;
    btnCloseNotification: TWebButton;
    XDataWebDataSet1active: TBooleanField;
    procedure WebFormCreate(Sender: TObject);
    //procedure tblPhoneGridGetCellChildren(Sender: TObject; ACol, ARow: Integer;
      //AField: TField; AValue: string; AElement: TJSHTMLElementRecord);
    procedure btnConfirmDeleteClick(Sender: TObject);
    procedure btnAddUserClick(Sender: TObject);
    procedure btnCloseNotificationClick(Sender: TObject);
    //procedure btnApplyClick(Sender: TObject);
    //procedure btnSearchClick(Sender: TObject);
  private
    FChildForm: TWebForm;
    procedure ClearTable();
    procedure GeneratePagination(TotalPages: Integer);
    //function GenerateSearchOptions(): string;
    //[async] procedure Search(searchOptions: string);
    [async] procedure DelUser(username: string);
    [async] procedure EditUser(row: TJSHTMLElement);
    [async] procedure GetUsers(searchOptions: string);
    procedure HideNotification;
    procedure ShowNotification(Notification: string);
    procedure AddRowToTable(UserID, Username, Full_Name, Phone, Email: string; Admin, Active: boolean);
    //[async] procedure addUser();
    var
      PageNumber: integer;
      PageSize: integer;
      TotalPages: integer;
      StartDate: string;
      EndDate: string;
      OrderBy: string;
      cur_user: string;
      Info: string;
  public
  class function CreateForm(AElementID, Info: string): TWebForm;
  end;

var
  FViewUsers: TFViewUsers;

implementation

{$R *.dfm}

uses
  XData.Model.Classes,
  ConnectionModule,
  View.Main;

{$R *.dfm}

class function TFViewUsers.CreateForm(AElementID, Info: string): TWebForm;
// Autofills known information about a user on create
  procedure AfterCreate(AForm: TObject);
  begin
    TFViewUsers(AForm).Info := Info;
  end;

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

procedure TFViewUsers.WebFormCreate(Sender: TObject);
begin
  DMConnection.ApiConnection.Connected := True;
  PageNumber := 1;
  TotalPages := 1; // Initial total pages
  PageSize := 10;
  GetUsers('');
  if Info <> '' then
    ShowNotification(Info)
  else
    HideNotification();

end;

procedure TFViewUsers.DelUser(username: string);
var
  xdcResponse: TXDataClientResponse;
  responseString: TJSObject;
begin
    xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.DelUser',
        [username]));
    responseString :=  TJSObject(xdcResponse.Result);
    ShowNotification(string(responseString['value']));
    getUsers('');
end;

procedure TFViewUsers.EditUser(row: TJSHTMLElement);
var
  cells: TJSHTMLCollection;
  UserID: TJSNode;
  Username: TJSNode;
  FullName: TJSNode;
  PhoneNum: TJSNode;
  Email: TJSNode;
  Admin: TJSNode;
  Password: TJSNode;
  isAdmin: boolean;
  isActive: boolean;
  ButtonCancel: TJSHTMLElement;
  splitNames: TArray<string>;
  firstName: string;
  lastName: string;
  xdcResponse: TXDataClientResponse;
  responseString: TJSObject;
  editOptions: string;

begin
  cells := row.getElementsByTagName('td');
  UserID := cells[0];
  Username := cells[1];
  Password := cells[2];
  FullName := cells[3];
  PhoneNum := cells[4];
  Email := cells[5];
  Admin := cells[6];
  if TJSHTMLElement(cells[6].childNodes.item(0).childNodes.item(0)).attributes.Attrs['checked'] = nil then
    isAdmin := false
  else
    isAdmin := true;
  if TJSHTMLElement(cells[7].childNodes.item(0).childNodes.item(0)).attributes.Attrs['checked'] = nil then
    isActive := false
  else
    isActive := true;
  FViewMain.EditUser('Edit', Username.innerText, FullName.innerText, PhoneNum.innerText, Email.innerText, isAdmin, isActive);

end;

procedure TFViewUsers.GeneratePagination(TotalPages: Integer);
var
  PaginationElement, PageItem, PageLink: TJSHTMLElement;
  I, Start, Finish: Integer;
begin
  PaginationElement := TJSHTMLElement(document.getElementById('pagination'));
  PaginationElement.innerHTML := ''; // Clear existing pagination

  // Previous Button
  PageItem := TJSHTMLElement(document.createElement('li'));
  PageItem.className := 'page-item';
  if PageNumber = 1 then
    PageItem.classList.add('disabled');
  PageLink := TJSHTMLElement(document.createElement('a'));
  PageLink.className := 'page-link';
  PageLink.innerText := 'Previous';
  PageLink.setAttribute('href', 'javascript:void(0)');
  PageLink.addEventListener('click', procedure(Event: TJSMouseEvent)
  begin
    if PageNumber > 1 then
    begin
      Dec(PageNumber);
      GetUsers('');
    end;
  end);
  PageItem.appendChild(PageLink);
  PaginationElement.appendChild(PageItem);

  // Page Numbers

  if PageNumber <= 4 then
  Begin
    Start := 2;
    Finish := 5;
  End
  else if (PageNumber >= (TotalPages - 3)) then
  begin
    Start := TotalPages - 3;
    Finish := TotalPages - 1;
  end
  else
  begin
    Start := PageNumber - 1;
    Finish := PageNumber + 1;
  end;

  PageItem := TJSHTMLElement(document.createElement('li'));
  PageItem.className := 'page-item';
  if 1 = PageNumber then
    PageItem.classList.add('selected-number'); // Add the selected-number class
  PageLink := TJSHTMLElement(document.createElement('a'));
  PageLink.className := 'page-link';
  PageLink.innerText := '1';
  PageLink.setAttribute('href', 'javascript:void(0)');
  PageLink.addEventListener('click', procedure(Event: TJSMouseEvent)
  var
    PageNum: Integer;
  begin
    PageNum := StrToInt((Event.currentTarget as TJSHTMLElement).innerText);
    PageNumber := PageNum;
    GetUsers('');
  end);
  PageItem.appendChild(PageLink);
  PaginationElement.appendChild(PageItem);

  // Adds Elipse to pagination if page number is too big
  if PageNumber > 4 then
  begin
    PageItem := TJSHTMLElement(document.createElement('li'));
    PageItem.className := 'page-item';
    PageItem.classList.add('disabled');
    PageLink := TJSHTMLElement(document.createElement('a'));
    PageLink.className := 'page-link';
    PageLink.innerText := '...';
    PageLink.setAttribute('href', 'javascript:void(0)');
    PageItem.appendChild(PageLink);
    PaginationElement.appendChild(PageItem);
  end;


  // Adds Page, page - 1, and page + 1 to pagination
  for I := Start  to Finish do
  begin
    if ( I > 1) and (I < TotalPages) then
    begin
      PageItem := TJSHTMLElement(document.createElement('li'));
      PageItem.className := 'page-item';
      if I = PageNumber then
        PageItem.classList.add('selected-number'); // Add the selected-number class
      PageLink := TJSHTMLElement(document.createElement('a'));
      PageLink.className := 'page-link';
      PageLink.innerText := IntToStr(I);
      PageLink.setAttribute('href', 'javascript:void(0)');
      PageLink.addEventListener('click', procedure(Event: TJSMouseEvent)
      var
        PageNum: Integer;
      begin
        PageNum := StrToInt((Event.currentTarget as TJSHTMLElement).innerText);
        PageNumber := PageNum;
        GetUsers('');
      end);
      PageItem.appendChild(PageLink);
      PaginationElement.appendChild(PageItem);
    end;
  end;

  if PageNumber < TotalPages - 4 then
  begin
    PageItem := TJSHTMLElement(document.createElement('li'));
    PageItem.className := 'page-item';
    PageItem.classList.add('disabled');
    PageLink := TJSHTMLElement(document.createElement('a'));
    PageLink.className := 'page-link';
    PageLink.innerText := '...';
    PageLink.setAttribute('href', 'javascript:void(0)');
    PageItem.appendChild(PageLink);
    PaginationElement.appendChild(PageItem);
  end;

  if TotalPages <> 1 then
  begin
    PageItem := TJSHTMLElement(document.createElement('li'));
    PageItem.className := 'page-item';
    if TotalPages = PageNumber then
          PageItem.classList.add('selected-number');
    PageLink := TJSHTMLElement(document.createElement('a'));
    PageLink.className := 'page-link';
    PageLink.innerText := IntToStr(TotalPages);
    PageLink.setAttribute('href', 'javascript:void(0)');
    PageLink.addEventListener('click', procedure(Event: TJSMouseEvent)
    var
      PageNum: Integer;
    begin
      PageNum := StrToInt((Event.currentTarget as TJSHTMLElement).innerText);
      PageNumber := PageNum;
      GetUsers('');
    end);
    PageItem.appendChild(PageLink);
    PaginationElement.appendChild(PageItem);
  end;

  // Next Button
  PageItem := TJSHTMLElement(document.createElement('li'));
  PageItem.className := 'page-item';
  if PageNumber = TotalPages then
    PageItem.classList.add('disabled');
  PageLink := TJSHTMLElement(document.createElement('a'));
  PageLink.className := 'page-link';
  PageLink.innerText := 'Next';
  PageLink.setAttribute('href', 'javascript:void(0)');
  PageLink.addEventListener('click', procedure(Event: TJSMouseEvent)
  begin
    if PageNumber < TotalPages then
    begin
      Inc(PageNumber);
      GetUsers('');
    end;
  end);
  PageItem.appendChild(PageLink);
  PaginationElement.appendChild(PageItem);

end;


procedure TFViewUsers.GetUsers(searchOptions: string);
var
  xdcResponse: TXDataClientResponse;
  userList : TJSObject;
  i: integer;
  data: TJSArray;
  user: TJSObject;
  userListLength: integer;

begin
  if PageNumber > 0 then
  begin
    xdcResponse := await(XDataWebClient1.RawInvokeAsync('ILookupService.GetUsers',
        [searchOptions]));

    userList :=  TJSObject(xdcResponse.Result);
    data := TJSArray(userList['data']);
    userListLength := integer(userList['count']);
    ClearTable();

    XDataWebDataSet1.Close;
    XDataWebDataSet1.SetJsonData(userList['data']);
    XDataWebDataSet1.Open;
    for i := 0 to data.Length - 1 do
    begin
      user := TJSObject(data[i]);
      AddRowToTable(XDataWebDataSet1userID.AsString, XDataWebDataSet1username.AsString,
                    XDataWebDataSet1full_name.AsString, XDataWebDataSet1phone_number.AsString,
                    XDataWebDataSet1email_address.AsString, XDataWebDataSet1Admin.AsBoolean,
                    XDataWebDataSet1Active.AsBoolean);
      XDataWebDataSet1.Next;
    end;
    TotalPages := (userListLength + PageSize - 1) div PageSize;
    if (PageNumber * PageSize) < userListLength then
    begin
      lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
                            ' - ' + IntToStr(PageNumber * PageSize) +
                             ' of ' + IntToStr(userListLength);
    end
    else
    begin
       lblEntries.Caption := 'Showing entries ' + IntToStr((PageNumber - 1) * PageSize + 1) +
                            ' - ' + IntToStr(userListLength) +
                             ' of ' + IntToStr(userListLength);
    end;
    GeneratePagination(TotalPages);
  end;
end;

procedure TFViewUsers.AddRowToTable(UserID, Username, Full_Name, Phone, Email: string; Admin, Active: boolean);
// Adds rows to the table
// PhoneNumber: phone number of the location
// Caller: phone number of the caller
// Duration: duration of the call
// Transcript: transcription of the recording
// MediaUrl: Link to the recording
var
  NewRow, Cell, P, Button, cbAdmin: TJSHTMLElement;
begin
  NewRow := TJSHTMLElement(document.createElement('tr'));

  // UserID  Cell
  Cell := TJSHTMLElement(document.createElement('td'));
  Cell.setAttribute('data-label', 'UserID');
  Cell.innerText := UserID;
  NewRow.appendChild(Cell);

  // Username Cell
  Cell := TJSHTMLElement(document.createElement('td'));
  Cell.setAttribute('data-label', 'Username');
  Cell.innerText := Username;
  NewRow.appendChild(Cell);

  // Password Cell
  Cell := TJSHTMLElement(document.createElement('td'));
  Cell.setAttribute('data-label', 'Password');
  Cell.innerText := 'hidden';
  NewRow.appendChild(Cell);

  // Full Name Cell
  Cell := TJSHTMLElement(document.createElement('td'));
  Cell.setAttribute('data-label', 'Full Name');
  Cell.innerText := Full_Name;
  NewRow.appendChild(Cell);

  // Phone Cell
  Cell := TJSHTMLElement(document.createElement('td'));
  Cell.setAttribute('data-label', 'Phone Number');
  Cell.innerText := Phone;
  NewRow.appendChild(Cell);

  // Email Cell
  Cell := TJSHTMLElement(document.createElement('td'));
  Cell.setAttribute('data-label', 'Email Address');
  Cell.innerText := Email;
  NewRow.appendChild(Cell);

  // Admin Cell
  Cell := TJSHTMLElement(document.createElement('td'));
  cbAdmin := TJSHTMLElement(document.createElement('a'));
  //Button.className := 'btn btn-primary';
  //Button.setAttribute('href', MediaUrl);
  if Admin then
    cbAdmin.innerHTML := '<input type="checkbox" id="cbadminuser" checked>'
  else
    cbAdmin.innerHTML := '<input type="checkbox" id="cbadminuser">';
  Cell.appendChild(cbAdmin);
  Cell.setAttribute('data-label', 'Admin');
  NewRow.appendChild(Cell);

  // Admin Cell
  Cell := TJSHTMLElement(document.createElement('td'));
  cbAdmin := TJSHTMLElement(document.createElement('a'));
  //Button.className := 'btn btn-primary';
  //Button.setAttribute('href', MediaUrl);
  if Active then
    cbAdmin.innerHTML := '<input type="checkbox" id="cbactive" checked>'
  else
    cbAdmin.innerHTML := '<input type="checkbox" id="cbactive">';
  Cell.appendChild(cbAdmin);
  Cell.setAttribute('data-label', 'Active');
  NewRow.appendChild(Cell);

  // Edit Button Cell
  Cell := TJSHTMLElement(document.createElement('td'));
  Cell.setAttribute('data-label', 'Edit');
  Button := TJSHTMLElement(document.createElement('a'));
  Button.className := 'btn btn-primary';
  Button.innerHTML := '<i class="far fa-edit fa-fw"></i><span>Edit</span>';
  Button.addEventListener('click', procedure(Event: TJSMouseEvent)
  begin
    EditUser(TJSHTMLElement(NewRow));
  end);
  Cell.appendChild(Button);
  NewRow.appendChild(Cell);

  // Delete Button Cell
  Cell := TJSHTMLElement(document.createElement('td'));
  Cell.setAttribute('data-label', 'Delete');
  Button := TJSHTMLElement(document.createElement('a'));
  Button.className := 'btn btn-primary';
  Button.innerHTML := '<i class="fas fa-times fa-fw"></i>';
  Button.addEventListener('click', procedure(Event: TJSMouseEvent)
  begin
    cur_user := Username;
    asm
      var modal = document.getElementById('confirmation_modal');

      if (modal && modal.parentNode !== document.body) {
        document.body.appendChild(modal);  // Pull modal out of nested z-index hell
      }

      var bsModal = new bootstrap.Modal(modal, { keyboard: false });
      bsModal.show();
    end;
  end);
  Cell.appendChild(Button);
  NewRow.appendChild(Cell);

  // Appends new rows to the table body
  TJSHTMLElement(document.getElementById('tblPhoneGrid').getElementsByTagName('tbody')[0]).appendChild(NewRow);
end;

procedure TFViewUsers.btnAddUserClick(Sender: TObject);
begin
  //Info := '';
  FViewMain.EditUser('Add', '', '', '', '', false, true);
end;

procedure TFViewUsers.btnCloseNotificationClick(Sender: TObject);
begin
  HideNotification;
end;

procedure TFViewUsers.HideNotification;
begin
  pnlMessage.ElementHandle.hidden := True;
end;

procedure TFViewUsers.ShowNotification(Notification: string);
var
  splitNotification: TArray<string>;
begin
  if Notification <> '' then
  begin
    splitNotification := Notification.Split([':']);
    if(splitNotification[0] = 'Success') then
    begin
      asm
        var messageDiv = document.getElementById('view.login.message');
        messageDiv.classList.remove('alert-danger');
        messageDiv.classList.add('alert-success');
      end;
    end
    else
    begin
      asm
        var messageDiv = document.getElementById('view.login.message');
        messageDiv.classList.remove('alert-success');
        messageDiv.classList.add('alert-danger');
      end;
    end;
    lblMessage.Caption := splitNotification[1];
    pnlMessage.ElementHandle.hidden := False;
  end;
end;

procedure TFViewUsers.btnConfirmDeleteClick(Sender: TObject);
begin
  DelUser(cur_user);
end;

procedure TFViewUsers.ClearTable();
var
  tbody: TJSHTMLElement;
begin
  tbody := TJSHTMLElement(document.getElementById('tblPhoneGrid').getElementsByTagName('tbody')[0]);
  tbody.innerHTML := '';
end;

{function TFViewUsers.GenerateSearchOptions(): string;
var
searchOptions: string;
begin
  PageSize := StrToInt(wcbPageSize.Text);
  StartDate := dtpStartDate.Text;
  EndDate := dtpEndDate.Text;
  OrderBy := wcbSortBy.Text;
  searchOptions := '&phonenumber=' + wcbLocation.Value +
                    '&pagenumber=' + IntToStr(PageNumber) +
                    '&pagesize=' + IntToStr(PageSize) +
                    '&startdate=' + StartDate +
                    '&enddate=' + EndDate +
                    '&orderby=' + OrderBy;
  Result := searchOptions;
end; }

end.
