unit MainForm;

{$mode objfpc}{H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ComCtrls, Spin, ExtCtrls, Grids, uHCTypeDefs;

type

  { TfrmMain }

  TfrmMain = class(TForm)
    btnSetFormationGoal: TButton;
    btnVCCalc: TButton;
    btnFormSectors: TButton;
    edtVCStartLat: TEdit;
    edtBearing: TEdit;
    edtRange: TEdit;
    edtVCStartLon: TEdit;
    edtVCHdgDeg: TEdit;
    edtVCDist: TEdit;
    Label10: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    memForm: TMemo;
    memVCOut: TMemo;
    pnlSetFormationGoal: TPanel;
    SGlblDescription1: TLabel;
    GTlblGameTimeLeft: TLabel;
    GTlblGameDateTime: TLabel;
    GTbtnResume: TButton;
    GTckbPause: TCheckBox;
    GTpctStructs: TPageControl;
    GTtshStartGroup: TTabSheet;
    GTtshWeatherGroups: TTabSheet;
    GTtshHarpEvents: TTabSheet;
    Label1: TLabel;
    Label2: TLabel;
    GTlblGameTime: TLabel;
    GTHEEventList: TListBox;
    GEHEmemDetail: TMemo;
    GTtshSonoBuoy: TTabSheet;
    GTtshDeadUnits: TTabSheet;
    Label3: TLabel;
    Label4: TLabel;
    SGckbEnabled1: TCheckBox;
    SGedtLines1: TSpinEdit;
    SGlblLines1: TLabel;
    SGmemMsgLog1: TMemo;
    SLsgLineage: TStringGrid;
    tshVC: TTabSheet;
    tshForm: TTabSheet;
    tshSaveGame: TTabSheet;
    tshGT: TTabSheet;
    memDLLInit: TMemo;
    SLckbEnabled: TCheckBox;
    SLedtLines: TSpinEdit;
    SLlblLines: TLabel;
    SLmemMsgLog: TMemo;
    tshDLLInit: TTabSheet;
    tshScenLoad: TTabSheet;
    tshTimeFactor: TTabSheet;
    TFckbEnabled: TCheckBox;
    TFedtLines: TSpinEdit;
    TFlblLines: TLabel;
    TFmemMsgLog: TMemo;
    PageControl1: TPageControl;
    procedure btnFormSectorsClick(Sender: TObject);
    procedure btnSetFormationGoalClick(Sender: TObject);
    procedure btnVCCalcClick(Sender: TObject);
    procedure GTbtnResumeClick(Sender: TObject);
    procedure GTHEEventListSelectionChange(Sender: TObject; User: boolean);
  private
    { private declarations }
  public
    { public declarations }
    // ALE 20130812 Big bad pointers that hold most of the game data
    PHarpEventHead: PHCHarpoonEvent;
    PSonobuoyRegionHead: PHCSonobuoyRegion;
    PAllDeadUnitsPtr: PHCDeadListItem;
    PWeatherGroups: PHCGroup;
    PVictoryConditionsList: PHCVictoryConditions;
    // ALE 20130812 transient pointers
    PSelectedUnit: PHCUnit;
    // ALE 20130812 misc globals
    //blnInvestigatingStructs: Boolean;
    // ALE 20130908 pointers to functions exported by the GE
    HCQueueHarpoonEvent: THCQueueHarpoonEvent;
    NewPtr: THCNewPtr;
    DisposPtr: THCDisposPtr;
    HCdllCheckLatLonDepth: THCdllCheckLatLonDepth;
    HCannex_id_to_disk_id: THCannex_id_to_disk_id;
    HCdisk_id_to_annex_id: THCdisk_id_to_annex_id;
    HCMessageLogLine: THCMessageLogLine;
  end;

var
  frmMain: TfrmMain;

implementation

uses uLazFormationGlobals, uHCDefines, uHCEventHelpers, uHCGCI, uHCUtils;

{$R *.lfm}

{ TfrmMain }

procedure TfrmMain.GTbtnResumeClick(Sender: TObject);
begin
  GTHEEventList.Clear;
  GEHEmemDetail.Clear;
  GTckbPause.Checked := False;
  GTbtnResume.Enabled := False;
  GTckbPause.Enabled := True;
  byte(PDLLBusy^) := CFALSE; // ALE 20130816
end;

procedure TfrmMain.btnSetFormationGoalClick(Sender: TObject);
var
  lFormation: THCFORMATIONC;
  lRange: Double;
  lBearing: Double;
begin
  if (PActUnit <> nil) then
  begin
    if (TryStrToFloat(edtRange.Text, lRange)
        AND (TryStrToFloat(edtBearing.Text, lBearing))) then
    begin
      // ALE 20180222 set the goal formation position
      UnitFormationList.TryGetValue(PActUnit^.UUID, lFormation);
      lFormation.PositionGoal.Range:=lRange;
      lFormation.PositionGoal.Bearing:=lBearing;
      UnitFormationList.AddOrSetValue(PActUnit^.UUID, lFormation);
    end;
  end;
end;

procedure TfrmMain.btnFormSectorsClick(Sender: TObject);
var
  lDegStart, lDegEnd: short;
begin
  if (PActUnit <> nil) then
  begin
    HCFormationSectors2Deg(PActUnit^.sectors, lDegStart, lDegEnd);
    memForm.Lines.Insert(0, Format('Group=%s, Unit=%3.3d, DegStart=%d, DegEnd=%d', [PActUnit^.Group^.id, PActUnit^.id, lDegStart, lDegEnd]));
  end;
end;

procedure TfrmMain.btnVCCalcClick(Sender: TObject);
var
  lDestLatDeg, lDestLonDeg: Double;
  lDestHdgDeg: Double;
  lIter: long;
begin
  // Desired output from http://www.movable-type.co.uk/scripts/latlong-vincenty.html
  // Lat: -37.951033, Lon: 144.424868
  // DistNM: 29.68265172786, Hdg: 306.8682
  // Dest Lat: -37.65282, Lon: 143.9265
  // Dest Hdg: 307.1736
  VincentyDirect(StrToFloat(edtVCStartLat.Text), StrToFloat(edtVCStartLon.Text),
   StrToFloat(edtVCDist.Text), StrToFloat(edtVCHdgDeg.Text),
   lDestLatDeg, lDestLonDeg, lDestHdgDeg, lIter);

  memVCOut.Lines.Insert(0, Format('Dest: Lat=%2.5f, Lon=%2.5f, Hdg=%3.5f; Iterations=%d', [lDestLatDeg, lDestLonDeg, lDestHdgDeg, lIter]));
end;

procedure TfrmMain.GTHEEventListSelectionChange(Sender: TObject; User: boolean);
var
  strSel: string;
  PEvent: PHCHarpoonEvent;
  PEventMessage: PHCMessageEvent;
begin
  // ALE 20130317 User selected a group, pull up unit list.
  strSel := Copy(GTHEEventList.Items[GTHEEventList.ItemIndex], 12, 8);
  PEvent := PHarpEventHead;
  while (PEvent <> nil) do
  begin
    if (strSel = Format('%p', [PEvent])) then
      break;
    PEvent := PEvent^.Next;
  end;

  // ALE 20130816 We found the event, do something.
  GEHEmemDetail.Clear;
  GEHEmemDetail.Lines.Add(Format('Pointer to Event: 0x%p', [PEvent]));
  GEHEmemDetail.Lines.Add(Format('Pointer to next Event: 0x%p', [PEvent^.Next]));
  GEHEmemDetail.Lines.Add(Format('Event Type: %s',
    [HCEventType2String(PEvent^.flag and CommandMask)]));
  GEHEmemDetail.Lines.Add(Format(
    'Pointer to Group the Event applies to (if any): 0x%p',
    [PEvent^.ourGroup]));
  GEHEmemDetail.Lines.Add(Format('UnitID the Event applies to (if any): %3.3d',
    [PEvent^.UnitID]));
  GEHEmemDetail.Lines.Add(Format('Pointer to DataPtr: 0x%p', [PEvent^.DataPtr]));
  GEHEmemDetail.Lines.Add(Format('Event Time: %8.8d', [PEvent^.Time]));
  GEHEmemDetail.Lines.Add(Format('Event Time Type: %s',
    [HCEventTimeType2String(PEvent^.flag and TimeMask)]));
  GEHEmemDetail.Lines.Add(Format('Event in_scroll_flag: %d',
    [PEvent^.in_scroll_flag]));
  if (PEvent^.flag and CommandMask = MESSAGE_EVENT) then
  begin
    PEventMessage := PEvent^.DataPtr;
    GEHEmemDetail.Lines.Add(Format('Message: %s', [PEventMessage^.Message]));

  end;
end;

{ TfrmMain }



end.
