#ifndef OverbyteIcsNetTools1H
#define OverbyteIcsNetTools1H

#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <Vcl.ComCtrls.hpp>
#include <Vcl.Buttons.hpp>

#include "OverbyteIcsTypes.hpp"
#include "OverbyteIcsWndControl.hpp"
#include "OverbyteIcsWSocket.hpp"
#include "OverbyteIcsUtils.hpp"
#include "OverbyteIcsIniFiles.hpp"
#include "OverbyteIcsDnsHttps.hpp"
#include "OverbyteIcsDnsQuery.hpp"
#include "OverbyteIcsIpHlpApi.hpp"
#include "OverbyteIcsPing.hpp"
#include "OverbyteIcsSslBase.hpp"
#include "OverbyteIcsWhoisCli.hpp"
//start of AF_ macro guard for OverbyteIcsIpHlpApi.hpp
#pragma push_macro("AF_UNSPEC")
#pragma push_macro("AF_UNIX")
#pragma push_macro("AF_INET")
#pragma push_macro("AF_IMPLINK")
#pragma push_macro("AF_PUP")
#pragma push_macro("AF_CHAOS")
#pragma push_macro("AF_NS")
#pragma push_macro("AF_IPX")
#pragma push_macro("AF_ISO")
#pragma push_macro("AF_OSI")
#pragma push_macro("AF_ECMA")
#pragma push_macro("AF_DATAKIT")
#pragma push_macro("AF_CCITT")
#pragma push_macro("AF_SNA")
#pragma push_macro("AF_DECnet")
#pragma push_macro("AF_DLI")
#pragma push_macro("AF_LAT")
#pragma push_macro("AF_HYLINK")
#pragma push_macro("AF_APPLETALK")
#pragma push_macro("AF_NETBIOS")
#pragma push_macro("AF_VOICEVIEW")
#pragma push_macro("AF_FIREFOX")
#pragma push_macro("AF_UNKNOWN1")
#pragma push_macro("AF_BAN")
#pragma push_macro("AF_INET6")
#pragma push_macro("AF_CLUSTER")
#pragma push_macro("AF_12844")
#pragma push_macro("AF_IRDA")
#pragma push_macro("AF_NETDES")
#pragma push_macro("AF_TCNPROCESS")
#pragma push_macro("AF_TCNMESSAGE")
#pragma push_macro("AF_ICLFXBM")
#pragma push_macro("AF_MAX")
#undef AF_UNSPEC
#undef AF_UNIX
#undef AF_INET
#undef AF_IMPLINK
#undef AF_PUP
#undef AF_CHAOS
#undef AF_NS
#undef AF_IPX
#undef AF_ISO
#undef AF_OSI
#undef AF_ECMA
#undef AF_DATAKIT
#undef AF_CCITT
#undef AF_SNA
#undef AF_DECnet
#undef AF_DLI
#undef AF_LAT
#undef AF_HYLINK
#undef AF_APPLETALK
#undef AF_NETBIOS
#undef AF_VOICEVIEW
#undef AF_FIREFOX
#undef AF_UNKNOWN1
#undef AF_BAN
#undef AF_INET6
#undef AF_CLUSTER
#undef AF_12844
#undef AF_IRDA
#undef AF_NETDES
#undef AF_TCNPROCESS
#undef AF_TCNMESSAGE
#undef AF_ICLFXBM
#undef AF_MAX
#include "OverbyteIcsIpHlpApi.hpp"
#pragma pop_macro("AF_UNSPEC")
#pragma pop_macro("AF_UNIX")
#pragma pop_macro("AF_INET")
#pragma pop_macro("AF_IMPLINK")
#pragma pop_macro("AF_PUP")
#pragma pop_macro("AF_CHAOS")
#pragma pop_macro("AF_NS")
#pragma pop_macro("AF_IPX")
#pragma pop_macro("AF_ISO")
#pragma pop_macro("AF_OSI")
#pragma pop_macro("AF_ECMA")
#pragma pop_macro("AF_DATAKIT")
#pragma pop_macro("AF_CCITT")
#pragma pop_macro("AF_SNA")
#pragma pop_macro("AF_DECnet")
#pragma pop_macro("AF_DLI")
#pragma pop_macro("AF_LAT")
#pragma pop_macro("AF_HYLINK")
#pragma pop_macro("AF_APPLETALK")
#pragma pop_macro("AF_NETBIOS")
#pragma pop_macro("AF_VOICEVIEW")
#pragma pop_macro("AF_FIREFOX")
#pragma pop_macro("AF_UNKNOWN1")
#pragma pop_macro("AF_BAN")
#pragma pop_macro("AF_INET6")
#pragma pop_macro("AF_CLUSTER")
#pragma pop_macro("AF_12844")
#pragma pop_macro("AF_IRDA")
#pragma pop_macro("AF_NETDES")
#pragma pop_macro("AF_TCNPROCESS")
#pragma pop_macro("AF_TCNMESSAGE")
#pragma pop_macro("AF_ICLFXBM")
#pragma pop_macro("AF_MAX")
//end of AF_ macro guard
#include "OverbyteIcsTicks64.hpp"
#include "OverbyteIcsWhoisCli.hpp"
#include "OverbyteIcsPing.hpp"
#include "OverbyteIcsDnsQuery.hpp"
#include "OverbyteIcsDnsHttps.hpp"
#include "IcsGeoUtils.hpp"

#include <array>
#include <memory>
#include <vector>

class TToolsForm : public TForm
{
__published:
    //start of settings saved in the ini file
    TRadioGroup *DNCacheLAN;
    TCheckBox *DNCacheLog;
    TEdit *DNCacheMax;
    TRadioGroup *DNCacheMethod;
    TRadioGroup *IpConnType;
    TEdit *IpConnsSecs;
    TComboBox *IpFamily;
    TComboBox *LocalIPv4;
    TComboBox *LocalIPv6;
    TComboBox *LookupHost;
    TCheckBox *MonIpAddrChanges;
    TRadioGroup *NameDnsOpt;
    TComboBox *NameHostName;
    TCheckBox *NameProtoTCP;
    TComboBox *NameQueryType;
    TComboBox *NameServerIP;
    TComboBox *NameServerPublic;
    TEdit *NeigbDevCache;
    TEdit *NeigbDevIPv4;
    TEdit *NeigbDevIPv6;
    TEdit *NeigbDevScan;
    TEdit *NeigbDevTot;
    TCheckBox *NeighbPermAddr;
    TEdit *PingCount;
    TCheckBox *PingLog;
    TComboBox *PingQueryName;
    TEdit *PingTimeoutMs;
    TEdit *ResolveIpRem;
    TEdit *RevExtra;
    TComboBox *RevLookAddr;
    TEdit *TraceErrors;
    TRadioGroup *WhoisMethod;
    TComboBox *WhoisQueryName;
    TComboBox *WhoisServer;
    //start of controls not saved
    TLabel *Label8;
    TLabel *Label9;
    TPanel *Panel1;
    TLabel *Label2;
    TLabel *Label4;
    TLabel *Label11;
    TButton *doExit;
    TPageControl *PageControl1;
    TTabSheet *TabConnections;
    TGroupBox *BoxIpConnections;
    TLabel *LabelInterval;
    TButton *doLogIpConns;
    TButton *doIpConnStop;
    TButton *doIpConnUpdate;
    TButton *doIpConnStart;
    TListView *IpConnsListV;
    TTabSheet *TabNeighbDev;
    TGroupBox *BoxNeigbDevs;
    TLabel *Label3;
    TLabel *Label5;
    TLabel *Label6;
    TLabel *Label7;
    TLabel *Label10;
    TButton *doNeigbDevStart;
    TButton *doNeigbDevStop;
    TButton *doDeviceLogMac;
    TButton *doDeviceLogIp;
    TButton *doDeviceEmptyCache;
    TButton *doDevicesClear;
    TListView *NeigbDevListV;
    TTabSheet *TabAdaptors;
    TGroupBox *BoxNetAdapt;
    TButton *doLogAdaptors;
    TButton *doLogNetParams;
    TButton *doUpdAdaptors;
    TListView *AdaptorListV;
    TListView *NetParamsListV;
    TTabSheet *TabInterfaces;
    TGroupBox *BoxNetInterfaces;
    TButton *doLogInterfaces;
    TButton *doUpdInterfaces;
    TListView *InterfacesListV;
    TTabSheet *TabIpAddr;
    TGroupBox *BoxIpAddresses;
    TButton *doLogIpAddr;
    TButton *doUpdIpAddr;
    TListView *IpAddressListV;
    TTabSheet *TabIpRouting;
    TGroupBox *BoxIpRouting;
    TLabel *Label12;
    TButton *doLogIpRouting;
    TButton *doLogIpPath;
    TButton *dpUpdIpRouting;
    TButton *doUpdIpPaths;
    TListView *IpRoutingListV;
    TListView *IpPathsListV;
    TTabSheet *TabArp;
    TGroupBox *BoxArp;
    TLabel *Label1;
    TButton *doResolveIP;
    TButton *doLogARP;
    TButton *doLogNeighbIPs;
    TButton *doUpdNeigbIps;
    TButton *doNetBIOS;
    TListView *NeighbListV;
    TTabSheet *TabStats;
    TGroupBox *BoxNetStats;
    TButton *doListStats;
    TButton *doUpdStats;
    TListBox *ListStatsTCP;
    TListBox *ListStatsUDP;
    TListBox *ListStatsIcmpIn;
    TListBox *ListStatsIcmpOut;
    TTabSheet *TabWhois;
    TGroupBox *BoxWhois;
    TLabel *Label13;
    TLabel *Label14;
    TLabel *Label15;
    TButton *doWhoisQuery;
    TButton *doWhoisAbort;
    TBitBtn *doWhoisClear;
    TMemo *WhoisMemo;
    TTabSheet *TabPing;
    TGroupBox *BoxPingTrace;
    TLabel *Label17;
    TLabel *Label16;
    TLabel *Labe26;
    TLabel *Label18;
    TLabel *LabelTraceDest;
    TButton *doPingSync;
    TButton *doPingThread;
    TButton *doTraceRoute;
    TButton *doPingAbort;
    TBitBtn *doPingClear;
    TListView *PingListView;
    TTabSheet *TabDNSLookup;
    TGroupBox *BoxDNSLookup;
    TLabel *Label20;
    TLabel *Label26;
    TComboBox *NameServerHttps;
    TButton *doDnsRev;
    TButton *doDNSAll;
    TButton *doDNSQuery;
    TBitBtn *doDelNameHost;
    TComboBox *NameServerAuto;
    TButton *doDnsBothA;
    TMemo *NameLookupMemo;
    TTabSheet *TabAddrLookup;
    TGroupBox *BoxAddrLookup;
    TGroupBox *BoxAddrForward;
    TLabel *Label19;
    TLabel *Label21;
    TLabel *Label22;
    TEdit *LookupAddr;
    TButton *doAddrLookUp;
    TEdit *LookupOfficial;
    TBitBtn *doDelAddrLook;
    TGroupBox *BoxAddrRev;
    TLabel *Label23;
    TLabel *Label24;
    TLabel *Label25;
    TButton *doAddrRevLook;
    TEdit *RevLookHost;
    TBitBtn *DelRevLookAddr;
    TGroupBox *BoxBulkDns;
    TLabel *Label29;
    TLabel *Label28;
    TMemo *BulkNamesMemo;
    TMemo *BulkResultMemo;
    TButton *doBulkDnsLookup;
    TGroupBox *BoxDnsCache;
    TLabel *Label27;
    TButton *doDNCacheList;
    TButton *doDNCacheClear;
    TTimer *CommonTimer;
    TIcsWhoisCli *IcsWhoisCli1;
    TPing *IcsPing1;
    TDnsQuery *IcsDnsQuery1;
    TDnsQueryHttps *IcsDnsQueryHttps1;
    TIcsNeighbDevices *IcsNeighbDevices1;
    TIcsIpChanges *IcsIpChanges1;
    void __fastcall FormCreate(TObject *Sender);
    void __fastcall FormShow(TObject *Sender);
    void __fastcall FormClose(TObject *Sender, TCloseAction &Action);
    void __fastcall doLogIpConnsClick(TObject *Sender);
    void __fastcall doLogARPClick(TObject *Sender);
    void __fastcall doLogAdaptorsClick(TObject *Sender);
    void __fastcall doLogNetParamsClick(TObject *Sender);
    void __fastcall doLogInterfacesClick(TObject *Sender);
    void __fastcall doLogIpAddrClick(TObject *Sender);
    void __fastcall doLogIpRoutingClick(TObject *Sender);
    void __fastcall doListStatsClick(TObject *Sender);
    void __fastcall doLogNeighbIPsClick(TObject *Sender);
    void __fastcall doLogIpPathClick(TObject *Sender);
    void __fastcall doResolveIPClick(TObject *Sender);
    void __fastcall doDeviceLogMacClick(TObject *Sender);
    void __fastcall doDeviceLogIpClick(TObject *Sender);
    void __fastcall doDeviceEmptyCacheClick(TObject *Sender);
    void __fastcall doDevicesClearClick(TObject *Sender);
    void __fastcall doNeigbDevStartClick(TObject *Sender);
    void __fastcall doNeigbDevStopClick(TObject *Sender);
    void __fastcall NeigbDevListVData(TObject *Sender, TListItem *Item);
    void __fastcall IpConnsListVData(TObject *Sender, TListItem *Item);
    void __fastcall doIpConnUpdateClick(TObject *Sender);
    void __fastcall doExitClick(TObject *Sender);
    void __fastcall CommonTimerTimer(TObject *Sender);
    void __fastcall doIpConnStartClick(TObject *Sender);
    void __fastcall doIpConnStopClick(TObject *Sender);
    void __fastcall doUpdAdaptorsClick(TObject *Sender);
    void __fastcall doUpdInterfacesClick(TObject *Sender);
    void __fastcall doUpdIpAddrClick(TObject *Sender);
    void __fastcall doUpdIpPathsClick(TObject *Sender);
    void __fastcall dpUpdIpRoutingClick(TObject *Sender);
    void __fastcall doUpdNeigbIpsClick(TObject *Sender);
    void __fastcall doUpdStatsClick(TObject *Sender);
    void __fastcall doWhoisQueryClick(TObject *Sender);
    void __fastcall IcsWhoisCli1QueryDone(TObject *Sender, System::Word ErrCode);
    void __fastcall doWhoisAbortClick(TObject *Sender);
    void __fastcall doWhoisClearClick(TObject *Sender);
    void __fastcall doPingClearClick(TObject *Sender);
    void __fastcall doPingThreadClick(TObject *Sender);
    void __fastcall doPingSyncClick(TObject *Sender);
    void __fastcall doPingAbortClick(TObject *Sender);
    void __fastcall doTraceRouteClick(TObject *Sender);
    void __fastcall IcsPing1DnsLookupDone(TObject *Sender, System::Word Error);
    void __fastcall IcsPing1EchoReply(TObject *Sender, TObject *Icmp, int Status);
    void __fastcall IcsPing1EchoRequest(TObject *Sender, TObject *Icmp);
    void __fastcall doDNSQueryClick(TObject *Sender);
    void __fastcall doDNSAllClick(TObject *Sender);
    void __fastcall doDnsRevClick(TObject *Sender);
    void __fastcall doAddrRevLookClick(TObject *Sender);
    void __fastcall doAddrLookUpClick(TObject *Sender);
    void __fastcall doDelNameHostClick(TObject *Sender);
    void __fastcall doDelAddrLookClick(TObject *Sender);
    void __fastcall DelRevLookAddrClick(TObject *Sender);
    void __fastcall IcsDnsQuery1LogEvent(TObject *Sender, const System::UnicodeString Msg);
    void __fastcall IcsDnsQuery1RequestDone(TObject *Sender, System::Word Error);
    void __fastcall doBulkDnsLookupClick(TObject *Sender);
    void __fastcall BulkNamesMemoDblClick(TObject *Sender);
    void __fastcall doDNCacheListClick(TObject *Sender);
    void __fastcall doDNCacheClearClick(TObject *Sender);
    void __fastcall DNCacheChangeClick(TObject *Sender);
    void __fastcall MonIpAddrChangesClick(TObject *Sender);
    void __fastcall doNetBIOSClick(TObject *Sender);
    void __fastcall doDnsBothAClick(TObject *Sender);
    void __fastcall IcsIpChanges1IpChangesEvent(const TIpAddrInfo &IpAddrInfo, TMibNoticationType NotificationType);

private:
    static constexpr int TraceMax = 32;
    static constexpr int MaxErrors = 8;

    String FBuffLogLines;
    std::unique_ptr<TStringList> FWorkStrings;
    TNetLuid FLocalIpLuid{};
    TNetworkParams FNetworkParams;
    TConnRows FIpConnRows;
    __int64 FIpConnUpdateTrg = 0;
    __int64 FNameServerTrg = 0;
    std::array<String, TraceMax + 1> FTraceAddr;
    std::vector<std::unique_ptr<TPingThread>> FThreads;
    std::unique_ptr<TIcsDomainNameCache> FNameCache;
    std::unique_ptr<TIcsGeoTools> FGeoTools;
    int FTraceErrs = 0;
    int FTraceMaxErrors = MaxErrors;
    int FPendingPings = 0;
    int FPendingLookups = 0;
    int FPingRun = 0;
    TSocketFamily FTraceSocketFamily = sfAny;
    String FTraceIPAddr;
    bool FTraceDoneFlag = false;
    bool FStopFlag = false;
    bool FPingBusy = false;
    bool FIpConnUpdating = false;
    bool FInitialized = false;
    bool FClosing = false;

    void AddLogLine(const String &S);
    void AddLogLines(TStrings *SL);
    void __fastcall OnNeigbDevDevUpd(TObject *Sender);
    void __fastcall OnNeigbDevLogEvent(TObject *Sender, const System::UnicodeString Msg);
    TSocketFamily SelectedFamily();
    int GetIpFamilyAF();
    void PingSetButtons(bool Enable);
    void PumpMessages();
    TPingThread *NewPingThread(int PingId, const String &Host, TSocketFamily Family, int Timeout, int TTL,
                               bool LookupReply, TNotifyEvent OnDone);
    void RunPingThreads();
    void RunTraceRoute();
    void __fastcall PingThreadTermPing(TObject *Sender);
    void __fastcall PingThreadTermTrace(TObject *Sender);
    bool SetupNameServer();
    void SetDnsButtons(bool Value);
    void SetLocalIPs();
    void __fastcall IcsAppLog(TObject *Sender, const System::UnicodeString Msg);
    void __fastcall IcsGeoEvent(TObject *Sender, const System::UnicodeString IpStr, System::UnicodeString &Geo);
    void LoadGeoDatabases();
    void __fastcall BulkNameUpdateEvent(TObject *Sender, int ItemNr);
    void __fastcall NameLookUpdateEvent(TObject *Sender, int ItemNr);
    void __fastcall PingNameUpdateEvent(TObject *Sender, int ItemNr);
    void __fastcall IpConnNameUpdateEvent(TObject *Sender, int ItemNr);

public:
    __fastcall TToolsForm(TComponent *Owner);
    __fastcall ~TToolsForm();
};

extern PACKAGE TToolsForm *ToolsForm;

#endif
