aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Scripting/Tango.Scripting.Basic/CompilationResult.cs
Commit message (Collapse)AuthorAgeFilesLines
* Scripting refactoring.Roy Ben Shabat2020-04-191-0/+21
using FluentFTP;
using Ionic.Zip;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.ServiceModel;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Tango.Core.Commands;
using Tango.Core.DI;
using Tango.Core.Helpers;
using Tango.Core.IO;
using Tango.Logging;
using Tango.MachineStudio.Common.Authentication;
using Tango.MachineStudio.Common.Navigation;
using Tango.MachineStudio.Common.Notifications;
using Tango.MachineStudio.Common.StudioApplication;
using Tango.MachineStudio.Common.Update;
using Tango.SharedUI;
using Tango.MachineStudio.UI.Messages;

namespace Tango.MachineStudio.UI.ViewModels
{
    public enum UpdateStatus
    {
        None,
        CheckingForUpdate,
        UpToDate,
        UpdateAvailable,
        Downloading,
        Updating,
        UpdateCompleted,
        Error,
    }

    public class UpdateViewVM : ViewModel
    {
        private String _appPath = AppDomain.CurrentDomain.BaseDirectory;
        private LogManager logManager = LogManager.Default;

        private INotificationProvider _notification;
        private INavigationManager _navigation;
        private IStudioApplicationManager _application;
        private IAuthenticationProvider _authentication;
        private CheckForUpdatesResponse _updateInfo;
        private TemporaryFolder _newPackageTempFolder;

        private bool _forcedUpdate;
        public bool ForcedUpdate
        {
            get { return _forcedUpdate; }
            set { _forcedUpdate = value; RaisePropertyChangedAuto(); }
        }

        private UpdateStatus _status;
        public UpdateStatus Status
        {
            get { return _status; }
            set { _status = value; RaisePropertyChangedAuto(); }
        }

        private String _latestVersion;
        public String LatestVersion
        {
            get { return _latestVersion; }
            set { _latestVersion = value; RaisePropertyChangedAuto(); }
        }

        private double _downloadProgress;

        public double DownloadProgress
        {
            get { return _downloadProgress; }
            set { _downloadProgress = value; RaisePropertyChangedAuto(); }
        }

        private double _updateProgress;

        public double UpdateProgress
        {
            get { return _updateProgress; }
            set { _updateProgress = value; RaisePropertyChangedAuto(); }
        }

        private String _currentUpdateFile;

        public String CurrentUpdateFile
        {
            get { return _currentUpdateFile; }
            set { _currentUpdateFile = value; RaisePropertyChanged(nameof(CurrentUpdateFile)); }
        }

        public RelayCommand UpdateCommand { get; set; }

        public RelayCommand BackCommand { get; set; }

        public RelayCommand RestartCommand { get; set; }

        public RelayCommand TryAgainCommand { get; set; }

        public UpdateViewVM(INotificationProvider notification, IAuthenticationProvider authentication, INavigationManager navigation, IStudioApplicationManager application)
        {
            _notification = notification;
            _navigation = navigation;
            _application = application;
            _authentication = authentication;

            LatestVersion = "1.0.0.2";
            Status = UpdateStatus.CheckingForUpdate;
            UpdateCommand = new RelayCommand(StartUpdate, () => Status == UpdateStatus.UpdateAvailable);
            BackCommand = new RelayCommand(BackToApplication, () => Status != UpdateStatus.Updating && !ForcedUpdate);
            RestartCommand = new RelayCommand(RestartApplication, () => Status == UpdateStatus.UpdateCompleted);
            TryAgainCommand = new RelayCommand(TryAgain, () => Status == UpdateStatus.Error);

            TangoMessenger.Default.Register<Messages.ForcedUpdateMessage>(HandleForcedUpdateMessage);
        }

        private void HandleForcedUpdateMessage(ForcedUpdateMessage msg)
        {
            ForcedUpdate = true;
            InvalidateRelayCommands();

            _updateInfo = msg.UpdateResponse;
            Status = UpdateStatus.UpdateAvailable;
            LatestVersion = _updateInfo.Version;
            StartUpdate();
        }

        public void OnNavigatedInto()
        {
            if (!ForcedUpdate)
            {
                CheckForUpdates();
            }
        }

        private void CheckForUpdates()
        {
            Status = UpdateStatus.CheckingForUpdate;

            ChannelFactory<IMachineStudioUpdateService> service = null;

            Task.Factory.StartNew(() =>
            {
                try
                {
                    Thread.Sleep(2000);

                    service = UpdateServiceHelper.GetUpdateServiceChannel();
                    var client = service.CreateChannel();

                    CheckForUpdatesResponse response = client.CheckForUpdates(new CheckForUpdatesRequest()
                    {
                        Email = _authentication.CurrentUser.Email,
                        Password = _authentication.CurrentUser.Password,
                        Version = _application.Version,
                    });

                    if (response.IsUpdateAvailable)
                    {
                        _updateInfo = response;
                        Status = UpdateStatus.UpdateAvailable;
                        LatestVersion = response.Version;
                    }
                    else
                    {
                        Status = UpdateStatus.UpToDate;
                    }
                }
                catch (Exception ex)
                {
                    logManager.Log(ex, "Error while checking for version update!");
                    Status = UpdateStatus.Error;
                }
                finally
                {
                    if (service != null)
                    {
                        service.Close();
                    }
                }
            });
        }

        private void BackToApplication()
        {
            if (Status == UpdateStatus.Downloading)
            {
                if (!_notification.ShowQuestion("This will abort all update operations. Are you sure?"))
                {
                    return;
                }
            }

            _navigation.NavigateTo(NavigationView.MainView);
            Status = UpdateStatus.None;
        }

        private void StartUpdate()
        {
            DownloadProgress = 0;
            UpdateProgress = 0;

            Status = UpdateStatus.Downloading;

            Task.Factory.StartNew(() =>
            {
                var tempFile = TemporaryManager.CreateFile(".zip");

                try
                {
                    logManager.Log("Creating temporary file " + tempFile);

                    int fileSize = 0;

                    using (FileStreamWrapper fs = new FileStreamWrapper(tempFile.Path, FileMode.Create, (current) =>
                    {
                        InvokeUINow(() =>
                        {
                            Thread.Sleep(10);
                            DownloadProgress = ((double)current / (double)fileSize) * 100d;
                        });
                    }))
                    {
                        using (FtpClient ftp = new FtpClient(_updateInfo.FtpHost, _updateInfo.UserName, _updateInfo.Password))
                        {
                            logManager.Log("Connecting to FTP site: " + _updateInfo.FtpHost);
                            ftp.ConnectAsync().Wait();
                            logManager.Log("Retrieving download size...");
                            fileSize = (int)ftp.GetFileSize(_updateInfo.FilePath);
                            logManager.Log("Download size: " + fileSize + " bytes.");
                            logManager.Log("Starting download...");
                            ftp.DownloadAsync(fs, _updateInfo.FilePath).Wait();
                        }
                    }


                    Status = UpdateStatus.Updating;

                    _newPackageTempFolder = TemporaryManager.CreateFolder();
                    _newPackageTempFolder.Persist = true;

                    using (ZipFile zip = ZipFile.Read(tempFile.Path))
                    {
                        int currentEntry = 0;

                        zip.ExtractProgress += (x, args) =>
                        {
                            if (args.EventType == ZipProgressEventType.Extracting_AfterExtractEntry)
                            {
                                logManager.Log("Extracting " + Path.GetFileName(args.CurrentEntry.FileName));
                                UpdateProgress = ((double)(currentEntry++) / (double)zip.Entries.Count) * 100d;
                            }
                        };

                        foreach (ZipEntry entry in zip)
                        {
                            Thread.Sleep(10);

                            string newPath = Path.Combine(_newPackageTempFolder.Path, entry.FileName);

                            try
                            {
                                if (entry.IsDirectory)
                                {
                                    Directory.CreateDirectory(newPath);
                                }
                                else
                                {
                                    CurrentUpdateFile = Path.GetFileName(entry.FileName);
                                    entry.Extract(_newPackageTempFolder.Path, ExtractExistingFileAction.OverwriteSilently);
                                }
                            }
                            catch
                            {
                                logManager.Log("Could not extract file " + entry.FileName);
                            }
                        }
                    }

                    TangoIOC.Default.GetInstance<MainViewVM>().DisableCheckForUpdates = true;
                    Status = UpdateStatus.UpdateCompleted;
                }
                catch (Exception ex)
                {
                    logManager.Log(ex, "Error while extracting update package.");
                    Status = UpdateStatus.Error;
                }
                finally
                {
                    tempFile.Delete();
                }
            });
        }

        private void TryAgain()
        {
            CheckForUpdates();
        }

        private void RestartApplication()
        {
            try
            {
                Process p = new Process();
                p.StartInfo.FileName = _appPath + "\\Tango.MachineStudio.Updater.exe";
                p.StartInfo.UseShellExecute = true;
                p.StartInfo.Arguments = _newPackageTempFolder;
                p.Start();
            }
            catch (Exception ex)
            {
                if (ex.Message == "The operation was canceled by the user")
                {
                    _notification.ShowWarning("It seems like you refused to invoke our update utility. This prevents Machine Studio from completing the update process!");
                    return;
                }
            }
            Environment.Exit(0);
        }

        protected override void RaisePropertyChangedAuto([CallerMemberName] string caller = null)
        {
            base.RaisePropertyChangedAuto(caller);
            InvalidateRelayCommands();
        }
    }
}