{$mode objfpc}{$H+}
unit uMapSettings;

// CC 20260402 non-modal dialog for per-ring-type, per-side range ring toggles
// CC 20260921 widened into a paged settings dialog; range rings are one page,
//  overlay toggles (formation zones) are another
// CC 20260924 course display moved here from the main panel; every control
//  applies live, so Close just closes

interface

uses
  Classes, SysUtils, Forms, Controls, StdCtrls, ComCtrls, ExtCtrls,
  uRangeRings, uMapConfig;

type
  TfrmMapSettings = class(TForm)
    pcSettings: TPageControl;
    tshRangeRings: TTabSheet;
    tshOverlays: TTabSheet;
    lblBlue: TLabel;
    lblRed: TLabel;
    lblGreen: TLabel;
    lblUnknown: TLabel;
    lblASuW: TLabel;
    lblAAW: TLabel;
    lblSurfRadar: TLabel;
    lblAirRadar: TLabel;
    lblAirRange: TLabel;
    lblBingo: TLabel;
    chkASuWBlu: TCheckBox;
    chkASuWRed: TCheckBox;
    chkASuWGrn: TCheckBox;
    chkASuWUnk: TCheckBox;
    chkAAWBlu: TCheckBox;
    chkAAWRed: TCheckBox;
    chkAAWGrn: TCheckBox;
    chkAAWUnk: TCheckBox;
    chkSRBlu: TCheckBox;
    chkSRRed: TCheckBox;
    chkSRGrn: TCheckBox;
    chkSRUnk: TCheckBox;
    chkARBlu: TCheckBox;
    chkARRed: TCheckBox;
    chkARGrn: TCheckBox;
    chkARUnk: TCheckBox;
    chkAirBlu: TCheckBox;
    chkAirRed: TCheckBox;
    chkAirGrn: TCheckBox;
    chkAirUnk: TCheckBox;
    chkBngBlu: TCheckBox;
    chkBngRed: TCheckBox;
    chkBngGrn: TCheckBox;
    chkBngUnk: TCheckBox;
    rgFormationZones: TRadioGroup;  // CC 20260924 None / Selected Group / All Groups
    rgCourseMode: TRadioGroup;      // CC 20260924 moved from the main panel
    cgCourse: TCheckGroup;          // CC 20260924 moved from the main panel
    lblOverlaysHint: TLabel;        // CC 20260924
    btnOK: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure btnOKClick(Sender: TObject);
  private
    FChecks: array[0..RING_COUNT-1, 0..3] of TCheckBox;
    FOnSettingsChanged: TNotifyEvent;  // CC 20260922
    FLoading: Boolean;                 // CC 20260924 LCL fires OnClick on programmatic changes
    procedure CommitSettings;          // CC 20260922
    procedure SettingClicked(Sender: TObject);                      // CC 20260924
    procedure CourseSideClicked(Sender: TObject; Index: Integer);   // CC 20260924
    procedure UpdateCourseSidesEnabled;                             // CC 20260924
  public
    procedure LoadFromGlobal;
    procedure SaveToGlobal;
    // CC 20260922 fired after settings are committed so the owner can re-render
    property OnSettingsChanged: TNotifyEvent read FOnSettingsChanged write FOnSettingsChanged;
  end;

var
  frmMapSettings: TfrmMapSettings;

implementation

{$R *.lfm}

procedure TfrmMapSettings.FormCreate(Sender: TObject);
var
  r, s: Integer;
begin
  FChecks[RING_ASuW, 0] := chkASuWBlu;
  FChecks[RING_ASuW, 1] := chkASuWRed;
  FChecks[RING_ASuW, 2] := chkASuWGrn;
  FChecks[RING_ASuW, 3] := chkASuWUnk;
  FChecks[RING_AAW, 0] := chkAAWBlu;
  FChecks[RING_AAW, 1] := chkAAWRed;
  FChecks[RING_AAW, 2] := chkAAWGrn;
  FChecks[RING_AAW, 3] := chkAAWUnk;
  FChecks[RING_SURF_RADAR, 0] := chkSRBlu;
  FChecks[RING_SURF_RADAR, 1] := chkSRRed;
  FChecks[RING_SURF_RADAR, 2] := chkSRGrn;
  FChecks[RING_SURF_RADAR, 3] := chkSRUnk;
  FChecks[RING_AIR_RADAR, 0] := chkARBlu;
  FChecks[RING_AIR_RADAR, 1] := chkARRed;
  FChecks[RING_AIR_RADAR, 2] := chkARGrn;
  FChecks[RING_AIR_RADAR, 3] := chkARUnk;
  FChecks[RING_AIR_RANGE, 0] := chkAirBlu;
  FChecks[RING_AIR_RANGE, 1] := chkAirRed;
  FChecks[RING_AIR_RANGE, 2] := chkAirGrn;
  FChecks[RING_AIR_RANGE, 3] := chkAirUnk;
  FChecks[RING_BINGO, 0] := chkBngBlu;
  FChecks[RING_BINGO, 1] := chkBngRed;
  FChecks[RING_BINGO, 2] := chkBngGrn;
  FChecks[RING_BINGO, 3] := chkBngUnk;
  pcSettings.ActivePage := tshRangeRings;  // CC 20260921

  // CC 20260924 live apply: every control commits as soon as it changes
  for r := 0 to RING_COUNT - 1 do
    for s := 0 to 3 do
      FChecks[r, s].OnClick := @SettingClicked;
  rgFormationZones.OnClick := @SettingClicked;
  rgCourseMode.OnClick := @SettingClicked;
  cgCourse.OnItemClick := @CourseSideClicked;

  LoadFromGlobal;
end;

procedure TfrmMapSettings.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  frmMapSettings := nil;
  CloseAction := caFree;
end;

// CC 20260924 plain Close again (FormClose frees it). The r1050 Hide/Release
//  workaround existed only because the form thread never ran LCL's release queue
procedure TfrmMapSettings.btnOKClick(Sender: TObject);
begin
  Close;
end;

// CC 20260922 store, persist, and notify the owner
procedure TfrmMapSettings.CommitSettings;
begin
  SaveToGlobal;
  SaveMapSettings;
  if Assigned(FOnSettingsChanged) then
    FOnSettingsChanged(Self);
end;

// CC 20260924 a control change while the dialog is open applies straight away
procedure TfrmMapSettings.SettingClicked(Sender: TObject);
begin
  if FLoading then Exit;
  UpdateCourseSidesEnabled;
  CommitSettings;
end;

procedure TfrmMapSettings.CourseSideClicked(Sender: TObject; Index: Integer);
begin
  SettingClicked(Sender);
end;

// CC 20260924 the side filter only means something in All Groups mode
procedure TfrmMapSettings.UpdateCourseSidesEnabled;
begin
  cgCourse.Enabled := rgCourseMode.ItemIndex = COURSE_ALL;
end;

procedure TfrmMapSettings.LoadFromGlobal;
var
  r, s: Integer;
begin
  FLoading := True;  // CC 20260924
  try
    for r := 0 to RING_COUNT - 1 do
      for s := 0 to 3 do
        FChecks[r, s].Checked := gMapSettings.RangeCircles[r, s];     // CC 20260922
    rgFormationZones.ItemIndex := gMapSettings.FormationZoneMode;     // CC 20260924
    rgCourseMode.ItemIndex := gMapSettings.CourseMode;                // CC 20260924
    for s := 0 to SIDE_COUNT - 1 do
      cgCourse.Checked[s] := gMapSettings.CourseSides[s];
    UpdateCourseSidesEnabled;
  finally
    FLoading := False;
  end;
end;

procedure TfrmMapSettings.SaveToGlobal;
var
  r, s: Integer;
begin
  for r := 0 to RING_COUNT - 1 do
    for s := 0 to 3 do
      gMapSettings.RangeCircles[r, s] := FChecks[r, s].Checked;     // CC 20260922
  gMapSettings.FormationZoneMode := rgFormationZones.ItemIndex;     // CC 20260924
  if (rgCourseMode.ItemIndex >= COURSE_NONE) and (rgCourseMode.ItemIndex <= COURSE_ALL) then
    gMapSettings.CourseMode := rgCourseMode.ItemIndex;              // CC 20260924
  for s := 0 to SIDE_COUNT - 1 do
    gMapSettings.CourseSides[s] := cgCourse.Checked[s];
end;

end.
