using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Input;
using RGBController2.Commands;
using RGBController2.ViewModels.Tabs;
using RGBController2.ViewModels.Dialogs;
using System.ComponentModel;
using System.Windows;
using System.Xml;
using System.IO;
using System.Linq;
namespace RGBController2.ViewModels
{
class MainViewModel
{
///
/// This is the directory of the exe
///
public static string BaseDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
private readonly ObservableCollection _tabs;
public ICommand NewTabCommand { get; }
public static ICollection Tabs { get; set; }
private string configLocation = "config.xml";
private bool _runOnStartUp;
public bool RunOnStartUp
{
get { return _runOnStartUp; }
set
{
if (value != _runOnStartUp)
{
_runOnStartUp = value;
RunAppOnStartup(value);
}
}
}
public MainViewModel()
{
configLocation = Path.Combine(BaseDir, "config.xml");
NewTabCommand = new ActionCommand(p => NewTab());
_tabs = new ObservableCollection();
_tabs.CollectionChanged += Tabs_CollectionChanged;
Tabs = _tabs;
_runOnStartUp = IsRunAppOnStartup();
// Check here that the config file exists
if (File.Exists(configLocation))
{
// Load the config file
using (XmlReader reader = XmlReader.Create(configLocation))
{
string name = "";
string type = "";
string device = "";
while (reader.Read())
{
if (reader.IsStartElement())
{
//return only when you have START tag
switch (reader.Name.ToString())
{
case "name":
name = reader.ReadString();
break;
case "type":
type = reader.ReadString();
break;
case "device":
device = reader.ReadString();
break;
}
}
// Create the tab here
if (name != "" && type != "" && device !="")
{
switch (type)
{
case "arduino":
{
var tab = new ArduinoTab(name);
tab.SelectedPort = device;
_tabs.Add(tab);
break;
}
case "cue":
{
var tab = new CueDeviceTab(name);
switch (device)
{
case "Headset":
tab.SelectedDevice = CUE.NET.Devices.Generic.Enums.CorsairDeviceType.Headset;
break;
case "HeadsetStand":
tab.SelectedDevice = CUE.NET.Devices.Generic.Enums.CorsairDeviceType.HeadsetStand;
break;
case "Keyboard":
tab.SelectedDevice = CUE.NET.Devices.Generic.Enums.CorsairDeviceType.Keyboard;
break;
case "Mouse":
tab.SelectedDevice = CUE.NET.Devices.Generic.Enums.CorsairDeviceType.Mouse;
break;
case "Mousemat":
tab.SelectedDevice = CUE.NET.Devices.Generic.Enums.CorsairDeviceType.Mousemat;
break;
}
_tabs.Add(tab);
break;
}
}
name = "";
type = "";
device = "";
}
}
}
}
}
private void Tabs_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
ITab tab;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
tab = (ITab) e.NewItems[0];
tab.CloseRequested += OnTabCloseRequested;
break;
case NotifyCollectionChangedAction.Remove:
tab = (ITab) e.OldItems[0];
tab.CloseRequested -= OnTabCloseRequested;
break;
}
}
private void OnTabCloseRequested(object sender, EventArgs e)
{
Tabs.Remove((Tab) sender);
}
private void NewTab()
{
// Open the add tab dialog
var dialog = new NewTabDialogViewModel();
dialog.ShowDialogWindow();
// Use the results from the dialog when creating the new tab
if (dialog.Success)
{
switch(dialog.SelectedDeviceType)
{
case 0: // Arduino
Tabs.Add(new ArduinoTab(dialog.DeviceName));
break;
case 1:
Tabs.Add(new CueDeviceTab(dialog.DeviceName));
break;
}
}
}
///
/// This function is called when the application is closed.
/// This allows the configuration to be saved to disk.
///
///
///
public void OnWindowClosing(object sender, CancelEventArgs e)
{
// Check if the config file currently exists
// if it does then we will need to delete it beofre we can save a new config
if (File.Exists(configLocation))
{
File.Delete(configLocation);
}
// This may need to be saved somwhere better, for now we will just save it
// with the executable
XmlWriter xmlWriter = XmlWriter.Create(configLocation);
xmlWriter.WriteStartDocument();
xmlWriter.WriteStartElement("tabs");
xmlWriter.WriteAttributeString("count", Tabs.Count.ToString());
foreach (var tab in Tabs)
{
xmlWriter.WriteStartElement("tab");
xmlWriter.WriteStartElement("name");
xmlWriter.WriteString(tab.Name);
xmlWriter.WriteEndElement();
switch (tab.TabType)
{
case Tab.tabType.Arduino:
xmlWriter.WriteStartElement("type");
xmlWriter.WriteString("arduino");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("device");
xmlWriter.WriteString(((ArduinoTab)tab).SelectedPort);
xmlWriter.WriteEndElement();
break;
case Tab.tabType.CUE:
xmlWriter.WriteStartElement("type");
xmlWriter.WriteString("cue");
xmlWriter.WriteEndElement();
xmlWriter.WriteStartElement("device");
xmlWriter.WriteString(((CueDeviceTab)tab).SelectedDevice.ToString());
xmlWriter.WriteEndElement();
break;
}
xmlWriter.WriteEndElement();
}
xmlWriter.WriteEndDocument();
xmlWriter.Close();
}
///
/// Checks if run on startup is enabled in the registry for the current user.
///
/// Truw if run on startup is enabled, false if not
private bool IsRunAppOnStartup()
{
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
return key.GetValueNames().Contains("RGB Application");
}
///
/// Helper function for modifying the registry to enable/disable run on startup.
/// This only enables run on startup for the current user, not the whole machine.
///
/// True if should be enabled, false if should be disabled.
private void RunAppOnStartup(bool enabled)
{
if (enabled)
{
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
key.SetValue("RGB Application", Path.Combine(BaseDir, System.AppDomain.CurrentDomain.FriendlyName) + ".exe");
}
else
{
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
key.DeleteValue("RGB Application", false);
}
}
}
}