using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading;

namespace StarTrinity.DistributedProxy.Controller
{
    public partial class ControllerWindow : Form
    {
        const int timerPeriod = 10 * 1000;
        System.Windows.Forms.Timer timer;
        public ControllerWindow()
        {
            InitializeComponent();
            this.Load += new EventHandler(ControllerWindow_Load);

            this.FormClosed += new FormClosedEventHandler(ControllerWindow_FormClosed);

            timer = new System.Windows.Forms.Timer();
            timer.Interval = timerPeriod;
            timer.Tick += new EventHandler(TimerCallback);
            timer.Enabled = true;
            timer.Start();

        }

        void ControllerWindow_Load(object sender, EventArgs e)
        {
            this.ShowInTaskbar = false;
            this.WindowState = FormWindowState.Minimized;
            Hide();
        }
        void TimerCallback(object o, EventArgs ea)
        {
            try
            {
                StartDpIfNotStarted();
                if (_timeOfTrialToUpdateVersion == null || _timeOfTrialToUpdateVersion.Value.AddMinutes(5) < DateTime.Now)
                    CheckAndDownloadNewVersion();
            }
            catch
            {
            }
        }

        void ControllerWindow_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (timer != null)
            {
                timer.Dispose();
                timer = null;
            }
        }
        const string updatebaseurl = "http://proxy.startrinity.com/updates/";
        const string hashurl = updatebaseurl + "md5.txt";
        const string zipurl = updatebaseurl + "update.zip";
        string GetHashcodeOfMostRecentVersion()
        {
            using (var wc = new WebClient())
            {
                return wc.DownloadString(hashurl);
            }
        }
        string GetHashCode(byte[] data)
        {
            var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();            
            var hash = md5.ComputeHash(data);

            var sb = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
                sb.Append(hash[i].ToString("x2"));
            return sb.ToString();
        }
        string GetHashcodeOfLocalVersion()
        {
            var fileName = Path.Combine(Path.GetDirectoryName(new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath), "StarTrinity.DistributedProxy.exe");
			return GetHashCode(File.ReadAllBytes(fileName)); 
        }
        DateTime? _timeOfTrialToUpdateVersion = null;
        Dictionary<string, byte[]> DownloadAndExtractZipFile()
        {
            var r = new Dictionary<string, byte[]>();
            byte[] zipData;
            using (var wc = new WebClient())
            {
                zipData = wc.DownloadData(zipurl);
            }

            var zf = new ICSharpCode.SharpZipLib.Zip.ZipFile(new MemoryStream(zipData));
            foreach (ICSharpCode.SharpZipLib.Zip.ZipEntry zipEntry in zf)
            {
			    if (!zipEntry.IsFile)
				    continue;			// Ignore directories

                var zipStream = zf.GetInputStream(zipEntry);
                var ms = new MemoryStream();
                ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(zipStream, ms, new byte[4096]);
                
                
                r.Add(zipEntry.Name, ms.ToArray());	

			}
          //  zf.
           // zs.
            		
            //using (var package = System.IO.Packaging.Package.Open(new MemoryStream(zipData)))
            //{
            //    var parts = package.GetParts();
            //    foreach (var part in parts)
            //    {
            //        using (var zipSourceStream = part.GetStream(FileMode.Open, FileAccess.Read))
            //        {				
            //        }
            //    }
            //}
            return r;
		}
        void CheckAndDownloadNewVersion()
        {
            // get hash of DP.exe
            var localHash = GetHashcodeOfLocalVersion();
            
            // request hash of latest DP.exe
            var mostRecentHash = GetHashcodeOfMostRecentVersion();

            if (localHash != mostRecentHash)
            { 
                //download ZIP
                var zipFiles = DownloadAndExtractZipFile();

                if (!zipFiles.ContainsKey("StarTrinity.DistributedProxy.exe"))
                    return; // todo report it
                var hashFromZip = GetHashCode(zipFiles["StarTrinity.DistributedProxy.exe"]);
                if (hashFromZip != mostRecentHash)
                    return; // todo report it

                // kill DP process
                try
                {
                    var dpProcesses = Process.GetProcessesByName("StarTrinity.DistributedProxy");
                    if (dpProcesses.Length != 0)
                    {
                        var dpProcess = dpProcesses[0];
                        dpProcess.CloseMainWindow();
                        dpProcess.WaitForExit(1000);
                        if (!dpProcess.HasExited)
                            dpProcess.Kill(); // todo close it normally
                        Thread.Sleep(2000);
                    }
                }
                catch
                {
                }

                _timeOfTrialToUpdateVersion = DateTime.Now;
                // replace DP
                foreach (var file in zipFiles)
                {
                    try
                    {
                        var dstFileName = Path.Combine(System.IO.Path.GetDirectoryName(new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath), file.Key);
                        File.Delete(dstFileName);
                        File.WriteAllBytes(dstFileName, file.Value);
                    }
                    catch
                    { // todo not replace 2nd time stop timer
                    }
                }

                // start DP
                StartDpIfNotStarted();
            }
        }

        void StartDpIfNotStarted()
        {
            if (Process.GetProcessesByName("StarTrinity.DistributedProxy").Length != 0)
            {
                return;
            }
            var path = System.IO.Path.GetDirectoryName(new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);
            Process.Start(Path.Combine(path, "StarTrinity.DistributedProxy.exe"));

        }
    }
}
