//  
//   Rebex Sample Code License
// 
//   Copyright 2026, REBEX CR s.r.o.
//   All rights reserved.
//   https://www.rebex.net/
// 
//   Permission to use, copy, modify, and/or distribute this software for any
//   purpose with or without fee is hereby granted.
// 
//   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//   OTHER DEALINGS IN THE SOFTWARE.
// 

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Security.Principal;
using System.Diagnostics;
using Rebex;
using Rebex.Net;

namespace Rebex.Samples
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class MainForm : System.Windows.Forms.Form
    {
        internal System.Windows.Forms.TabControl TabControl1;
        internal System.Windows.Forms.TabPage tabSynchronize;
        internal System.Windows.Forms.Panel Panel1;
        internal System.Windows.Forms.PictureBox PictureBox1;
        internal System.Windows.Forms.Label Label8;
        internal System.Windows.Forms.Button btnSynchronize;
        internal System.Windows.Forms.TabPage tabTimeDifference;
        internal System.Windows.Forms.Label Label11;
        internal System.Windows.Forms.CheckBox chbSet;
        internal System.Windows.Forms.TextBox tbOldTime;
        internal System.Windows.Forms.TextBox tbCorrectedTime;
        internal System.Windows.Forms.TextBox tbDifference;
        internal System.Windows.Forms.Label label3;
        internal System.Windows.Forms.Label label4;
        internal System.Windows.Forms.Label label5;
        internal System.Windows.Forms.Button btnDifference;
        internal System.Windows.Forms.TabPage tabServerInfo;
        internal System.Windows.Forms.Button btnStratum;
        internal System.Windows.Forms.Label label2;
        internal System.Windows.Forms.TextBox tbStratum;
        internal System.Windows.Forms.Label Label6;
        internal System.Windows.Forms.TextBox tbVersion;
        internal System.Windows.Forms.TextBox tbServerTime;
        internal System.Windows.Forms.Label Label7;
        internal System.Windows.Forms.Label Label10;
        internal System.Windows.Forms.GroupBox groupBox1;
        internal System.Windows.Forms.Label Label9;
        internal System.Windows.Forms.ComboBox cbServers;
        internal System.Windows.Forms.Label label12;
        private Label label1;
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        public MainForm()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after InitializeComponent call
            //
            CheckForIllegalCrossThreadCalls = true;
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
            this.TabControl1 = new System.Windows.Forms.TabControl();
            this.tabSynchronize = new System.Windows.Forms.TabPage();
            this.Panel1 = new System.Windows.Forms.Panel();
            this.PictureBox1 = new System.Windows.Forms.PictureBox();
            this.Label8 = new System.Windows.Forms.Label();
            this.btnSynchronize = new System.Windows.Forms.Button();
            this.tabTimeDifference = new System.Windows.Forms.TabPage();
            this.label1 = new System.Windows.Forms.Label();
            this.Label11 = new System.Windows.Forms.Label();
            this.chbSet = new System.Windows.Forms.CheckBox();
            this.tbOldTime = new System.Windows.Forms.TextBox();
            this.tbCorrectedTime = new System.Windows.Forms.TextBox();
            this.tbDifference = new System.Windows.Forms.TextBox();
            this.label3 = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.label5 = new System.Windows.Forms.Label();
            this.btnDifference = new System.Windows.Forms.Button();
            this.tabServerInfo = new System.Windows.Forms.TabPage();
            this.btnStratum = new System.Windows.Forms.Button();
            this.label2 = new System.Windows.Forms.Label();
            this.tbStratum = new System.Windows.Forms.TextBox();
            this.Label6 = new System.Windows.Forms.Label();
            this.tbVersion = new System.Windows.Forms.TextBox();
            this.tbServerTime = new System.Windows.Forms.TextBox();
            this.Label7 = new System.Windows.Forms.Label();
            this.Label10 = new System.Windows.Forms.Label();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.Label9 = new System.Windows.Forms.Label();
            this.cbServers = new System.Windows.Forms.ComboBox();
            this.label12 = new System.Windows.Forms.Label();
            this.TabControl1.SuspendLayout();
            this.tabSynchronize.SuspendLayout();
            this.Panel1.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.PictureBox1)).BeginInit();
            this.tabTimeDifference.SuspendLayout();
            this.tabServerInfo.SuspendLayout();
            this.groupBox1.SuspendLayout();
            this.SuspendLayout();
            // 
            // TabControl1
            // 
            this.TabControl1.Controls.Add(this.tabSynchronize);
            this.TabControl1.Controls.Add(this.tabTimeDifference);
            this.TabControl1.Controls.Add(this.tabServerInfo);
            this.TabControl1.Location = new System.Drawing.Point(8, 104);
            this.TabControl1.Name = "TabControl1";
            this.TabControl1.SelectedIndex = 0;
            this.TabControl1.Size = new System.Drawing.Size(400, 248);
            this.TabControl1.TabIndex = 14;
            // 
            // tabSynchronize
            // 
            this.tabSynchronize.Controls.Add(this.Panel1);
            this.tabSynchronize.Controls.Add(this.btnSynchronize);
            this.tabSynchronize.Location = new System.Drawing.Point(4, 22);
            this.tabSynchronize.Name = "tabSynchronize";
            this.tabSynchronize.Size = new System.Drawing.Size(392, 222);
            this.tabSynchronize.TabIndex = 0;
            this.tabSynchronize.Text = "Synchronize";
            // 
            // Panel1
            // 
            this.Panel1.BackColor = System.Drawing.Color.White;
            this.Panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
            this.Panel1.Controls.Add(this.PictureBox1);
            this.Panel1.Controls.Add(this.Label8);
            this.Panel1.Location = new System.Drawing.Point(0, 0);
            this.Panel1.Name = "Panel1";
            this.Panel1.Size = new System.Drawing.Size(392, 128);
            this.Panel1.TabIndex = 12;
            // 
            // PictureBox1
            // 
            this.PictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("PictureBox1.Image")));
            this.PictureBox1.Location = new System.Drawing.Point(0, 0);
            this.PictureBox1.Name = "PictureBox1";
            this.PictureBox1.Size = new System.Drawing.Size(104, 120);
            this.PictureBox1.TabIndex = 0;
            this.PictureBox1.TabStop = false;
            // 
            // Label8
            // 
            this.Label8.Location = new System.Drawing.Point(112, 17);
            this.Label8.Name = "Label8";
            this.Label8.Size = new System.Drawing.Size(264, 85);
            this.Label8.TabIndex = 11;
            this.Label8.Text = "Synchronizes local system time with the time server in a single line of code.";
            this.Label8.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            // 
            // btnSynchronize
            // 
            this.btnSynchronize.Location = new System.Drawing.Point(216, 192);
            this.btnSynchronize.Name = "btnSynchronize";
            this.btnSynchronize.Size = new System.Drawing.Size(168, 23);
            this.btnSynchronize.TabIndex = 10;
            this.btnSynchronize.Text = "Synchronize";
            this.btnSynchronize.Click += new System.EventHandler(this.btnSynchronize_Click);
            // 
            // tabTimeDifference
            // 
            this.tabTimeDifference.Controls.Add(this.label1);
            this.tabTimeDifference.Controls.Add(this.Label11);
            this.tabTimeDifference.Controls.Add(this.chbSet);
            this.tabTimeDifference.Controls.Add(this.tbOldTime);
            this.tabTimeDifference.Controls.Add(this.tbCorrectedTime);
            this.tabTimeDifference.Controls.Add(this.tbDifference);
            this.tabTimeDifference.Controls.Add(this.label3);
            this.tabTimeDifference.Controls.Add(this.label4);
            this.tabTimeDifference.Controls.Add(this.label5);
            this.tabTimeDifference.Controls.Add(this.btnDifference);
            this.tabTimeDifference.Location = new System.Drawing.Point(4, 22);
            this.tabTimeDifference.Name = "tabTimeDifference";
            this.tabTimeDifference.Size = new System.Drawing.Size(392, 222);
            this.tabTimeDifference.TabIndex = 2;
            this.tabTimeDifference.Text = "Time Difference";
            this.tabTimeDifference.Visible = false;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(320, 115);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(47, 13);
            this.label1.TabIndex = 19;
            this.label1.Text = "seconds";
            // 
            // Label11
            // 
            this.Label11.Location = new System.Drawing.Point(16, 8);
            this.Label11.Name = "Label11";
            this.Label11.Size = new System.Drawing.Size(312, 48);
            this.Label11.TabIndex = 18;
            this.Label11.Text = "Determines the time difference between the current local system time and server t" +
    "ime, calculates the correct local time and optionally sets the local time as wel" +
    "l.";
            // 
            // chbSet
            // 
            this.chbSet.Location = new System.Drawing.Point(16, 144);
            this.chbSet.Name = "chbSet";
            this.chbSet.Size = new System.Drawing.Size(200, 24);
            this.chbSet.TabIndex = 17;
            this.chbSet.Text = "Also set local system time";
            // 
            // tbOldTime
            // 
            this.tbOldTime.Location = new System.Drawing.Point(176, 64);
            this.tbOldTime.Name = "tbOldTime";
            this.tbOldTime.ReadOnly = true;
            this.tbOldTime.Size = new System.Drawing.Size(200, 20);
            this.tbOldTime.TabIndex = 14;
            // 
            // tbCorrectedTime
            // 
            this.tbCorrectedTime.Location = new System.Drawing.Point(176, 88);
            this.tbCorrectedTime.Name = "tbCorrectedTime";
            this.tbCorrectedTime.ReadOnly = true;
            this.tbCorrectedTime.Size = new System.Drawing.Size(200, 20);
            this.tbCorrectedTime.TabIndex = 15;
            // 
            // tbDifference
            // 
            this.tbDifference.Location = new System.Drawing.Point(176, 112);
            this.tbDifference.Name = "tbDifference";
            this.tbDifference.ReadOnly = true;
            this.tbDifference.Size = new System.Drawing.Size(138, 20);
            this.tbDifference.TabIndex = 16;
            // 
            // label3
            // 
            this.label3.Location = new System.Drawing.Point(16, 64);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(136, 23);
            this.label3.TabIndex = 11;
            this.label3.Text = "Current local system time:";
            // 
            // label4
            // 
            this.label4.Location = new System.Drawing.Point(16, 88);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(152, 23);
            this.label4.TabIndex = 12;
            this.label4.Text = "Time corrected using NTP:";
            // 
            // label5
            // 
            this.label5.Location = new System.Drawing.Point(16, 112);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(136, 23);
            this.label5.TabIndex = 13;
            this.label5.Text = "Time difference:";
            // 
            // btnDifference
            // 
            this.btnDifference.Location = new System.Drawing.Point(216, 192);
            this.btnDifference.Name = "btnDifference";
            this.btnDifference.Size = new System.Drawing.Size(168, 23);
            this.btnDifference.TabIndex = 10;
            this.btnDifference.Text = "Get time difference";
            this.btnDifference.Click += new System.EventHandler(this.btnDifference_Click);
            // 
            // tabServerInfo
            // 
            this.tabServerInfo.Controls.Add(this.btnStratum);
            this.tabServerInfo.Controls.Add(this.label2);
            this.tabServerInfo.Controls.Add(this.tbStratum);
            this.tabServerInfo.Controls.Add(this.Label6);
            this.tabServerInfo.Controls.Add(this.tbVersion);
            this.tabServerInfo.Controls.Add(this.tbServerTime);
            this.tabServerInfo.Controls.Add(this.Label7);
            this.tabServerInfo.Controls.Add(this.Label10);
            this.tabServerInfo.Location = new System.Drawing.Point(4, 22);
            this.tabServerInfo.Name = "tabServerInfo";
            this.tabServerInfo.Size = new System.Drawing.Size(392, 222);
            this.tabServerInfo.TabIndex = 1;
            this.tabServerInfo.Text = "Server Info";
            this.tabServerInfo.Visible = false;
            // 
            // btnStratum
            // 
            this.btnStratum.Location = new System.Drawing.Point(216, 192);
            this.btnStratum.Name = "btnStratum";
            this.btnStratum.Size = new System.Drawing.Size(168, 23);
            this.btnStratum.TabIndex = 17;
            this.btnStratum.Text = "Get server info";
            this.btnStratum.Click += new System.EventHandler(this.btnStratum_Click);
            // 
            // label2
            // 
            this.label2.Location = new System.Drawing.Point(16, 64);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(100, 23);
            this.label2.TabIndex = 15;
            this.label2.Text = "Server stratum:";
            // 
            // tbStratum
            // 
            this.tbStratum.Location = new System.Drawing.Point(176, 64);
            this.tbStratum.Name = "tbStratum";
            this.tbStratum.ReadOnly = true;
            this.tbStratum.Size = new System.Drawing.Size(200, 20);
            this.tbStratum.TabIndex = 11;
            // 
            // Label6
            // 
            this.Label6.Location = new System.Drawing.Point(16, 88);
            this.Label6.Name = "Label6";
            this.Label6.Size = new System.Drawing.Size(100, 23);
            this.Label6.TabIndex = 16;
            this.Label6.Text = "NTP version:";
            // 
            // tbVersion
            // 
            this.tbVersion.Location = new System.Drawing.Point(176, 88);
            this.tbVersion.Name = "tbVersion";
            this.tbVersion.ReadOnly = true;
            this.tbVersion.Size = new System.Drawing.Size(200, 20);
            this.tbVersion.TabIndex = 12;
            // 
            // tbServerTime
            // 
            this.tbServerTime.Location = new System.Drawing.Point(176, 112);
            this.tbServerTime.Name = "tbServerTime";
            this.tbServerTime.ReadOnly = true;
            this.tbServerTime.Size = new System.Drawing.Size(200, 20);
            this.tbServerTime.TabIndex = 13;
            // 
            // Label7
            // 
            this.Label7.Location = new System.Drawing.Point(16, 112);
            this.Label7.Name = "Label7";
            this.Label7.Size = new System.Drawing.Size(100, 23);
            this.Label7.TabIndex = 14;
            this.Label7.Text = "Server time:";
            // 
            // Label10
            // 
            this.Label10.Location = new System.Drawing.Point(16, 16);
            this.Label10.Name = "Label10";
            this.Label10.Size = new System.Drawing.Size(312, 40);
            this.Label10.TabIndex = 10;
            this.Label10.Text = "Retrieves various information from the NTP/SNTP server.";
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.Label9);
            this.groupBox1.Controls.Add(this.cbServers);
            this.groupBox1.Controls.Add(this.label12);
            this.groupBox1.Location = new System.Drawing.Point(8, 8);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(400, 78);
            this.groupBox1.TabIndex = 12;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = " Common settings ";
            // 
            // Label9
            // 
            this.Label9.Location = new System.Drawing.Point(16, 48);
            this.Label9.Name = "Label9";
            this.Label9.Size = new System.Drawing.Size(376, 24);
            this.Label9.TabIndex = 5;
            this.Label9.Text = "Select a time server hostname from a list or provide your own.";
            // 
            // cbServers
            // 
            this.cbServers.Items.AddRange(new object[] {
            "pool.ntp.org",
            "north-america.pool.ntp.org",
            "europe.pool.ntp.org",
            "asia.pool.ntp.org",
            "oceania.pool.ntp.org",
            "south-america.pool.ntp.org"});
            this.cbServers.Location = new System.Drawing.Point(120, 24);
            this.cbServers.Name = "cbServers";
            this.cbServers.Size = new System.Drawing.Size(184, 21);
            this.cbServers.TabIndex = 4;
            this.cbServers.Text = "test.rebex.net";
            // 
            // label12
            // 
            this.label12.Location = new System.Drawing.Point(16, 24);
            this.label12.Name = "label12";
            this.label12.Size = new System.Drawing.Size(72, 23);
            this.label12.TabIndex = 3;
            this.label12.Text = "Time server:";
            // 
            // MainForm
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(418, 366);
            this.Controls.Add(this.TabControl1);
            this.Controls.Add(this.groupBox1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "MainForm";
            this.Text = "Rebex Time - NTP/SNTP Sample Client";
            this.TabControl1.ResumeLayout(false);
            this.tabSynchronize.ResumeLayout(false);
            this.Panel1.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.PictureBox1)).EndInit();
            this.tabTimeDifference.ResumeLayout(false);
            this.tabTimeDifference.PerformLayout();
            this.tabServerInfo.ResumeLayout(false);
            this.tabServerInfo.PerformLayout();
            this.groupBox1.ResumeLayout(false);
            this.ResumeLayout(false);

        }
        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            // set the trial license key
            Rebex.Licensing.Key = Rebex.Samples.TrialKey.Key;


            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            Application.Run(new MainForm());
        }

        private void Synchronize()
        {
            // synchronize local time with time server       
            Ntp.SynchronizeSystemClock(cbServers.Text);

            MessageBox.Show(string.Format("Time set. Corrected local time is {0}.", DateTime.Now),
                "Time set", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        private void btnSynchronize_Click(object sender, System.EventArgs e)
        {
            // check whether elevation is needed or whether we already have admin privileges
            bool isElevated = ElevateIfNeeded();

            // only synchronize if we have admin privileges
            if (isElevated)
                Synchronize();
        }

        private void btnStratum_Click(object sender, System.EventArgs e)
        {
            // Initialize the Ntp object
            Ntp client = new Ntp(cbServers.Text);

            // Since we want to know the highest version the server supports, we 
            // must declare the highest ourselves (otherwise it would use 
            // compatibility mode).
            client.VersionNumber = 4;

            // Get the time response
            NtpResponse response = client.GetTime();
            NtpPacket packet = response.Packet;
            TimeSpan offset = response.TimeOffset.ToTimeSpan();

            // Show server stratum
            tbStratum.Text = packet.Stratum.ToString();
            // Show version
            tbVersion.Text = packet.VersionNumber.ToString();
            // Show server time
            tbServerTime.Text = (DateTime.Now + offset).ToString("yyyy-MM-dd HH:mm:ss.fff");
        }

        private void btnDifference_Click(object sender, System.EventArgs e)
        {
            // Initialize the Ntp object
            Ntp client = new Ntp(cbServers.Text);

            // Get the time response
            NtpResponse response = client.GetTime();
            TimeSpan offset = response.TimeOffset.ToTimeSpan();

            // Show local time
            tbOldTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
            // Show server time
            tbCorrectedTime.Text = (DateTime.Now + offset).ToString("yyyy-MM-dd HH:mm:ss.fff");
            // Show the time difference
            tbDifference.Text = offset.TotalSeconds.ToString();

            // Adjust the local clock
            if (chbSet.Checked && ElevateIfNeeded())
                SystemClock.AdjustClock(response);
        }

        public bool ElevateIfNeeded()
        {
            // determine wheher we currenly have admin privileges
            WindowsPrincipal pricipal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
            bool isElevated = pricipal.IsInRole(WindowsBuiltInRole.Administrator);

            // if we do, then nothing needs to be done
            if (isElevated)
                return true;

            // inform he user we are going to try elevating the application
            MessageBox.Show("In order to be able to synchronize local time with the server, this application first needs to be elevated to gain administrator permissions.", "Synchronize");

            // start a new instance of the application in elevated mode
            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.Verb = "runas";
            startInfo.FileName = Process.GetCurrentProcess().MainModule.FileName;
            startInfo.Arguments = "-sync";
            startInfo.UseShellExecute = true;
            try
            {
                Process.Start(startInfo);
                Application.Exit();
            }
            catch (Win32Exception)
            {
                // elevation not allowed
            }

            return false;
        }
    }
}
