unit View.Main;

interface

uses
  System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
  WEBLib.Forms, WEBLib.Dialogs, WEBLib.ExtCtrls, Vcl.Controls, Vcl.StdCtrls,
  WEBLib.StdCtrls, Data.DB, XData.Web.JsonDataset, XData.Web.Dataset,
  App.Types, ConnectionModule, XData.Web.Client, View.Map, View.Units, View.Complaints;

type
  TFViewMain = class(TWebForm)
    lblUsername: TWebLabel;
    wllblLogout: TWebLinkLabel;
    pnlMain: TWebPanel;
    WebMessageDlg1: TWebMessageDlg;
    lblAppTitle: TWebLabel;
    WebMemo1: TWebMemo;
    xdwcBadgeCounts: TXDataWebClient;
    lblCallsList: TWebLinkLabel;
    lblUsers: TWebLinkLabel;
    btnMap: TWebButton;
    btnComplaints: TWebButton;
    btnUnits: TWebButton;
    tmrBadgeCounts: TWebTimer;
    lblMainTitle: TWebLabel;
    pnlMap: TWebPanel;
    pnlUnits: TWebPanel;
    pnlComplaints: TWebPanel;
    procedure WebFormCreate(Sender: TObject);
    procedure mnuLogoutClick(Sender: TObject);
    procedure wllblLogoutClick(Sender: TObject);
    procedure btnUnitsClick(Sender: TObject);
    procedure btnComplaintsClick(Sender: TObject);
    procedure btnMapClick(Sender: TObject);
    procedure tmrBadgeCountsTimer(Sender: TObject);
  private
    { Private declarations }
    FUserInfo: string;
    FChildForm: TWebForm;
    FMapForm: TFViewMap;
    FUnitsForm: TFViewUnits;
    FComplaintsForm: TFViewComplaints;
    FLogoutProc: TLogoutProc;
    [async] procedure RefreshBadgesAsync;
    procedure ShowUnitDetails(UnitId: string);
    procedure SetHeaderTitle(const title: string);
  public
    { Public declarations }
    class procedure Display(LogoutProc: TLogoutProc);
    procedure ShowForm( AFormClass: TWebFormClass );
    procedure ShowComplaintDetails(ComplaintId: string);
    procedure SetActiveNavButton(const BtnId: string);
    procedure ShowMapFocusUnit(const unitId: string);
    procedure ShowMapFocusComplaint(const complaintId: string);
    procedure HidePanel(aPanel: TWebPanel);
    procedure ShowPanel(aPanel: TWebPanel);
  end;

var
  FViewMain: TFViewMain;

implementation

uses
  Auth.Service,
  View.Login,
  View.UserProfile,
  View.ComplaintDetails,
  View.Admin,
  View.Users,
  View.EditUser,
  View.UnitDetails,
  Utils;

{$R *.dfm}

procedure TFViewMain.WebFormCreate(Sender: TObject);
var
  userName: string;
begin
  userName := JS.toString(AuthService.TokenPayload.Properties['user_name']);
  lblUsername.Caption := ' ' + userName.ToLower + ' ';
  FChildForm := nil;
  if (not (JS.toBoolean(AuthService.TokenPayload.Properties['user_admin'])))  then
    lblUsers.Visible := false;
  Utils.HideSpinner('spinner');
  ShowForm(TFViewMap);
  RefreshBadgesAsync;
end;

procedure TFViewMain.SetHeaderTitle(const title: string);
var el: TJSElement;
begin
  el := Document.getElementById('lbl_main_title');
  if el <> nil then
    el.innerHTML := title
  else
    console.log('SetHeaderTitle: lbl_main_title not found');
end;


procedure TFViewMain.mnuLogoutClick(Sender: TObject);
begin
  FLogoutProc;
end;


procedure TFViewMain.wllblLogoutClick(Sender: TObject);
begin
  FLogoutProc;
end;


procedure TFViewMain.btnComplaintsClick(Sender: TObject);
begin
  ShowForm(TFViewComplaints);
end;


procedure TFViewMain.btnMapClick(Sender: TObject);
begin
  ShowForm(TFViewMap);
end;


procedure TFViewMain.btnUnitsClick(Sender: TObject);
begin
  ShowForm(TFViewUnits);
end;


class procedure TFViewMain.Display(LogoutProc: TLogoutProc);
begin
  if Assigned(FViewMain) then
    FViewMain.Free;
  FViewMain := TFViewMain.CreateNew;
  FViewMain.FLogoutProc := LogoutProc;
end;


procedure TFViewMain.ShowForm(AFormClass: TWebFormClass);
begin
  // Map (cached in pnlMapHost -> ElementID = 'pnl_map')
  if AFormClass = TFViewMap then
  begin
    HidePanel(pnlMain);
    HidePanel(pnlUnits);
    HidePanel(pnlComplaints);
    ShowPanel(pnlMap);

    SetHeaderTitle('Map');
    SetActiveNavButton('view.main.btnmap');

    if not Assigned(FMapForm) then
      Application.CreateForm(TFViewMap, pnlMap.ElementID, TWebForm(FMapForm));

    FChildForm := FMapForm;
    Exit;
  end;

  if AFormClass = TFViewUnits then
  begin
    HidePanel(pnlMain);
    HidePanel(pnlMap);
    HidePanel(pnlComplaints);
    ShowPanel(pnlUnits);

    SetHeaderTitle('Units');
    SetActiveNavButton('view.main.btnunits');

    if not Assigned(FUnitsForm) then
      Application.CreateForm(TFViewUnits, pnlUnits.ElementID, TWebForm(FUnitsForm));

    FChildForm := FUnitsForm;
    Exit;
  end;

  if AFormClass = TFViewComplaints then
  begin
    HidePanel(pnlMain);
    HidePanel(pnlMap);
    HidePanel(pnlUnits);
    ShowPanel(pnlComplaints);

    SetHeaderTitle('Complaints');
    SetActiveNavButton('view.main.btncomplaints');

    if not Assigned(FComplaintsForm) then
      Application.CreateForm(TFViewComplaints, pnlComplaints.ElementID, TWebForm(FComplaintsForm));

    FChildForm := FComplaintsForm;
    Exit;
  end;

  // Everything else: use pnlMain
  HidePanel(pnlMap);
  HidePanel(pnlUnits);
  HidePanel(pnlComplaints);
  ShowPanel(pnlMain);

  if Assigned(FChildForm) and (FChildForm <> FMapForm) and (FChildForm <> FUnitsForm) and (FChildForm <> FComplaintsForm) then
    FChildForm.Free;

  Application.CreateForm(AFormClass, pnlMain.ElementID, FChildForm);
end;

procedure TFViewMain.HidePanel(aPanel: TWebPanel);
var
  el: TJSHTMLElement;
begin
  if (aPanel = nil) or (aPanel.ElementHandle = nil) then
    Exit;

  el := TJSHTMLElement(aPanel.ElementHandle);
  el.classList.add('d-none');
end;

procedure TFViewMain.ShowPanel(aPanel: TWebPanel);
var
  el: TJSHTMLElement;
begin
  if (aPanel = nil) or (aPanel.ElementHandle = nil) then
    Exit;

  el := TJSHTMLElement(aPanel.ElementHandle);
  el.classList.remove('d-none');
end;

procedure TFViewMain.ShowComplaintDetails(ComplaintId: string);
begin
  SetHeaderTitle('Complaint Details');

  HidePanel(pnlMap);
  HidePanel(pnlUnits);
  HidePanel(pnlComplaints);
  ShowPanel(pnlMain);

  if Assigned(FChildForm) and (FChildForm <> FMapForm) and (FChildForm <> FUnitsForm) and (FChildForm <> FComplaintsForm) then
    FChildForm.Free;

  FChildForm := TFViewComplaintDetails.CreateForm(pnlMain.ElementID, ComplaintId);
end;

procedure TFViewMain.ShowUnitDetails(UnitId: string);
begin
  SetHeaderTitle('Unit Details');

  HidePanel(pnlMap);
  HidePanel(pnlUnits);
  HidePanel(pnlComplaints);
  ShowPanel(pnlMain);

  if Assigned(FChildForm) and (FChildForm <> FMapForm) and (FChildForm <> FUnitsForm) and (FChildForm <> FComplaintsForm) then
    FChildForm.Free;

  FChildForm := TFViewUnitDetails.CreateForm(pnlMain.ElementID, UnitId);
end;


procedure TFViewMain.SetActiveNavButton(const btnId: string);
var
  m, c, u: TJSHTMLElement;
begin
  m := TJSHTMLElement(btnMap.ElementHandle);
  c := TJSHTMLElement(btnComplaints.ElementHandle);
  u := TJSHTMLElement(btnUnits.ElementHandle);

  // clear
  m.classList.remove('active');
  c.classList.remove('active');
  u.classList.remove('active');

  // set
  if btnId = 'view.main.btnmap' then
    m.classList.add('active')
  else if btnId = 'view.main.btncomplaints' then
    c.classList.add('active')
  else if btnId = 'view.main.btnunits' then
    u.classList.add('active');
end;


procedure TFViewMain.tmrBadgeCountsTimer(Sender: TObject);
begin
  console.log('Badges Refreshed');
  RefreshBadgesAsync;
end;


[async] procedure TFViewMain.RefreshBadgesAsync;
var
  resp: TXDataClientResponse;
  badgeObj: TJSObject;
  el: TJSElement;
begin
  try
    resp := await(xdwcBadgeCounts.RawInvokeAsync('IApiService.GetBadgeCounts', []));
    badgeObj := TJSObject(resp.Result);

    el := Document.getElementById('view.main.badgecomplaints');
    if Assigned(el) then
      TJSHtmlElement(el).innerText := string(badgeObj['BadgeComplaints']);

    el := Document.getElementById('view.main.badgeunits');
    if Assigned(el) then
      TJSHtmlElement(el).innerText := string(badgeObj['BadgeUnits']);
  except
    on E: Exception do
    begin
      el := Document.getElementById('view.main.badgecomplaints');
      if Assigned(el) then TJSHtmlElement(el).innerText := '—';
      el := Document.getElementById('view.main.badgeunits');
      if Assigned(el) then TJSHtmlElement(el).innerText := '—';
      Console.Log('Badge refresh error: ' + E.Message);
    end;
  end;
end;


procedure TFViewMain.ShowMapFocusUnit(const unitId: string);
var
  pendingUnitId: string;
begin
  ShowForm(TFViewMap);

  pendingUnitId := unitId;

  window.setTimeout(
    procedure
    begin
      if (FChildForm <> nil) and (FChildForm is TFViewMap) then
        TFViewMap(FChildForm).FocusUnit(pendingUnitId);
    end, 50);
end;

procedure TFViewMain.ShowMapFocusComplaint(const complaintId: string);
var
  pendingComplaintId: string;
begin
  ShowForm(TFViewMap);

   pendingComplaintId := complaintId;

  window.setTimeout(
    procedure
    begin
      if (FChildForm <> nil) and (FChildForm is TFViewMap) then
        TFViewMap(FChildForm).FocusComplaint(pendingComplaintId);
    end, 50);
end;


end.
