using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Tango.Core.Commands;
using Tango.MachineStudio.Common.Notifications;
using Tango.MachineStudio.Common.StudioApplication;
using Tango.Scripting;
using Tango.Settings;
using Tango.SharedUI;
using Tango.Stubs;
using Tango.Transport;
using Tango.Transport.Adapters;
namespace Tango.MachineStudio.Stubs.ViewModels
{
///
/// Represents the script execution utility main view model.
///
///
public class MainViewVM : ViewModel
{
private UsbTransportAdapter _adapter; //Holds the USB transport adapter.
private StubManager _stubManager;
private INotificationProvider _notification;
#region Properties
public IStudioApplicationManager ApplicationManager { get; set; }
private bool _useConnectedMachine;
///
/// Gets or sets a value indicating whether [use connected machine].
///
public bool UseConnectedMachine
{
get { return _useConnectedMachine; }
set { _useConnectedMachine = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
}
///
/// Gets or sets the code tabs.
///
public ObservableCollection CodeTabs { get; set; }
///
/// Gets or sets the additional highlight C# types.
///
public ObservableCollection> HighlightTypes { get; set; }
///
/// Gets or sets the collection of stub snippets.
///
public ObservableCollection StubSnippets { get; set; }
private StubSnippetVM _selectedStubSnippet;
///
/// Gets or sets the selected stub snippet.
///
public StubSnippetVM SelectedStubSnippet
{
get { return _selectedStubSnippet; }
set { _selectedStubSnippet = value; RaisePropertyChanged(nameof(SelectedStubSnippet)); }
}
private String _log;
///
/// Gets or sets the current response log.
///
public String Log
{
get { return _log; }
set { _log = value; RaisePropertyChanged(nameof(Log)); }
}
private CodeTabVM _selectedCodeTab;
///
/// Gets or sets the selected code tab.
///
public CodeTabVM SelectedCodeTab
{
get { return _selectedCodeTab; }
set { _selectedCodeTab = value; RaisePropertyChanged(nameof(SelectedCodeTab)); InvalidateRelayCommands(); }
}
private bool _isConnected;
///
/// Gets or sets a value indicating whether the USB adapter is connected.
///
public bool IsConnected
{
get { return _isConnected; }
set { _isConnected = value; RaisePropertyChanged(nameof(IsConnected)); InvalidateRelayCommands(); }
}
private List _ports;
///
/// Gets or sets the available USB ports.
///
public List Ports
{
get { return _ports; }
set { _ports = value; RaisePropertyChanged(nameof(Ports)); }
}
private String _selectedPort;
///
/// Gets or sets the selected USB port.
///
public String SelectedPort
{
get { return _selectedPort; }
set { _selectedPort = value; RaisePropertyChanged(nameof(SelectedPort)); InvalidateRelayCommands(); }
}
private String _status;
///
/// Gets or sets the current status bar text.
///
public String Status
{
get { return _status; }
set { _status = value; RaisePropertyChanged(nameof(Status)); }
}
private bool _isRunning;
///
/// Gets or sets a value indicating whether a stub is currently running.
///
public bool IsRunning
{
get { return _isRunning; }
set { _isRunning = value; RaisePropertyChanged(nameof(IsRunning)); InvalidateRelayCommands(); }
}
#endregion
#region Commands
///
/// Gets or sets the new command.
///
public RelayCommand NewCommand { get; set; }
///
/// Gets or sets the close tab command.
///
public RelayCommand CloseTabCommand { get; set; }
///
/// Gets or sets the run command.
///
public RelayCommand RunCommand { get; set; }
///
/// Gets or sets the stop command.
///
public RelayCommand StopCommand { get; set; }
///
/// Gets or sets the toggle connection command.
///
public RelayCommand ToggleConnectionCommand { get; set; }
///
/// Gets or sets the open command.
///
public RelayCommand OpenCommand { get; set; }
///
/// Gets or sets the save command.
///
public RelayCommand SaveCommand { get; set; }
///
/// Gets or sets the save as command.
///
public RelayCommand SaveAsCommand { get; set; }
///
/// Gets or sets the stub snippet selected command.
///
public RelayCommand StubSnippetSelectedCommand { get; set; }
///
/// Gets or sets the insert snippet command.
///
public RelayCommand InsertSnippetCommand { get; set; }
///
/// Gets or sets the exit command.
///
public RelayCommand ExitCommand { get; set; }
#endregion
#region Constructors
///
/// Initializes a new instance of the class.
///
public MainViewVM(IStudioApplicationManager applicationManager, INotificationProvider notification)
{
ApplicationManager = applicationManager;
_notification = notification;
CodeTabs = new ObservableCollection();
NewCommand = new RelayCommand(CreateNewTab);
CloseTabCommand = new RelayCommand(OnTabClosing);
RunCommand = new RelayCommand(RunTab, (x) => (IsConnected || UseConnectedMachine) && !IsRunning && SelectedCodeTab != null);
StopCommand = new RelayCommand(StopTab, (x) => (IsConnected || UseConnectedMachine) && IsRunning && SelectedCodeTab != null);
InsertSnippetCommand = new RelayCommand((x) => { });
HighlightTypes = new ObservableCollection>();
HighlightTypes.Add(new KeyValuePair("stubManager", typeof(StubManager)));
StubSnippets = new ObservableCollection();
foreach (var stubType in StubBase.GetAvailableRequestStubs())
{
StubSnippetVM snippet = new StubSnippetVM();
snippet.Name = stubType.Name.Replace("Stub_", "");
snippet.Code = String.Format("stubManager.Run(\"{0}\" ,{1});", stubType.Name, String.Join(", ", stubType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(x => x.PropertyType.Name == "string" ? "\"string\"" : x.PropertyType.Name)));
StubSnippets.Add(snippet);
}
ToggleConnectionCommand = new RelayCommand(ToggleConnection, (x) => !IsRunning);
OpenCommand = new RelayCommand(OpenFile);
SaveCommand = new RelayCommand(SaveFile);
SaveAsCommand = new RelayCommand(SaveAsFile);
StubSnippetSelectedCommand = new RelayCommand(OnStubSnippetSelected);
ExitCommand = new RelayCommand(() => Application.Current.Shutdown());
Ports = new List()
{
"COM1",
"COM2",
"COM3",
"COM4",
"COM5",
"COM6",
"COM7",
"COM8",
"COM9",
};
SelectedPort = SettingsManager.Default.StubsUI.SelectedPort != null ? SettingsManager.Default.StubsUI.SelectedPort : Ports.First();
Status = "Ready";
if (SettingsManager.Default.StubsUI.LastTabs.Count > 0)
{
foreach (var file in SettingsManager.Default.StubsUI.LastTabs)
{
if (File.Exists(file))
{
OpenFile(file);
}
}
}
else
{
CreateNewTab();
}
Application.Current.Exit += Current_Exit;
}
#endregion
#region Virtual Methods
///
/// Called when a stub snippet is double clicked.
///
protected virtual void OnStubSnippetSelected()
{
if (SelectedStubSnippet != null)
{
if (InsertSnippetCommand != null)
{
InsertSnippetCommand.Execute(SelectedStubSnippet.Code);
}
}
}
///
/// Called when user closes a script tab.
///
/// The code tab.
protected virtual void OnTabClosing(CodeTabVM codeTab)
{
CodeTabs.Remove(codeTab);
}
#endregion
#region Private Methods
///
/// Saves the selected script file.
///
private void SaveFile()
{
if (SelectedCodeTab != null)
{
if (SelectedCodeTab.File == null)
{
SaveAsFile();
}
else
{
File.WriteAllText(SelectedCodeTab.File, SelectedCodeTab.Code);
}
}
}
///
/// Saves the selected script file.
///
private void SaveAsFile()
{
if (SelectedCodeTab != null)
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.Filter = "C# Script Files|*.cs";
dlg.DefaultExt = ".cs";
if (dlg.ShowDialog().Value)
{
File.WriteAllText(dlg.FileName, SelectedCodeTab.Code);
SelectedCodeTab.File = dlg.FileName;
}
}
}
///
/// Opens a script from HD.
///
private void OpenFile()
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = "C# Script Files|*.cs";
dlg.Multiselect = true;
if (dlg.ShowDialog().Value)
{
foreach (var file in dlg.FileNames)
{
OpenFile(file);
}
}
}
///
/// Opens the file.
///
/// The file.
private void OpenFile(String file)
{
var newTab = new CodeTabVM();
newTab.File = file;
newTab.Code = File.ReadAllText(file);
CodeTabs.Add(newTab);
SelectedCodeTab = newTab;
}
///
/// Toggles the USB adapter connection.
///
private void ToggleConnection()
{
try
{
if (!IsConnected)
{
_adapter = new UsbTransportAdapter(SelectedPort);
_adapter.Connect().Wait();
IsConnected = true;
}
else
{
_adapter.Disconnect().Wait();
IsConnected = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Tango");
}
}
///
/// Creates a new script tab.
///
private void CreateNewTab()
{
var newTab = new CodeTabVM();
CodeTabs.Add(newTab);
SelectedCodeTab = newTab;
}
///
/// Runs the selected script tab.
///
private async void RunTab()
{
if (UseConnectedMachine && !ApplicationManager.IsMachineConnected)
{
_notification.ShowError("Cannot execute stub while 'Connected Machine' is set but not machine connected.");
return;
}
IsRunning = true;
SelectedCodeTab.IsRunning = true;
Log = (DateTime.Now.ToTimeString() + ": ") + "Executing script '" + SelectedCodeTab.Title + "'..." + Environment.NewLine;
await Task.Factory.StartNew(async () =>
{
try
{
ITransportAdapter adapter = _adapter;
if (ApplicationManager.IsMachineConnected && UseConnectedMachine)
{
adapter = ApplicationManager.ConnectedMachine.Adapters.First();
}
_stubManager = new StubManager(adapter);
var thisStubManager = _stubManager;
_stubManager.Completed += Manager_Completed;
_stubManager.Failed += Manager_Failed;
_stubManager.Executed += Manager_Executed;
ScriptEngine engine = new ScriptEngine(new StubOnExecuteParameters(_stubManager));
engine.ReferencedAssemblies.Add(this.GetType());
await engine.Run(SelectedCodeTab.Code);
if (!thisStubManager.Aborted)
{
IsRunning = false;
SelectedCodeTab.IsRunning = false;
}
}
catch (Exception ex)
{
IsRunning = false;
SelectedCodeTab.IsRunning = false;
MessageBox.Show(ex.Message, "Tango");
}
});
}
///
/// Stops the currently current script.
///
private void StopTab()
{
if (_stubManager != null)
{
_stubManager.Abort();
IsRunning = false;
SelectedCodeTab.IsRunning = false;
Status = "Stopped!";
Log += (DateTime.Now.ToTimeString() + ": ") + "Stopped!" + Environment.NewLine;
}
}
#endregion
#region Event Handlers
///
/// Handled the Executed event.
///
/// The sender.
/// Name of the stub.
private void Manager_Executed(object sender, string stubName)
{
Log += (DateTime.Now.ToTimeString() + ": ") + "Executing '" + stubName + "'..." + Environment.NewLine;
Status = "Executing " + stubName + "...";
}
///
/// Handled the Failed event.
///
/// The sender.
/// The exception.
private void Manager_Failed(object sender, Exception ex)
{
if (IsRunning)
{
Log += (DateTime.Now.ToTimeString() + ": ") + ex.Message + Environment.NewLine;
Status = "Failed!";
}
}
///
/// Handled the Completed event.
///
/// The sender.
/// The response.
private void Manager_Completed(object sender, string response)
{
Log += (DateTime.Now.ToTimeString() + ": ") + "Response Received:" + Environment.NewLine;
Log += (DateTime.Now.ToTimeString() + ": ") + response + Environment.NewLine;
Status = "Completed";
}
private void Current_Exit(object sender, ExitEventArgs e)
{
SettingsManager.Default.MachineStudio.StubsModule.SelectedPort = SelectedPort;
SettingsManager.Default.MachineStudio.StubsModule.LastTabs = CodeTabs.Select(x => x.File).ToList();
SettingsManager.SaveDefaultSettings();
}
#endregion
}
}