corrade-vassal – Rev 7

Subversion Repositories:
Rev:
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3      //
//  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  //
//  rights of fair usage, the disclaimer and warranty conditions.        //
///////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;
using OpenMetaverse;

namespace Vassal
{
    public partial class SettingsForm : Form
    {
        private static SettingsForm mainForm;
        
        ///////////////////////////////////////////////////////////////////////////
        //    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    //
        ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        ///     Get enumeration value from its description.
        /// </summary>
        /// <typeparam name="T">the enumeration type</typeparam>
        /// <param name="description">the description of a member</param>
        /// <returns>the value or the default of T if case no description found</returns>
        private static T wasGetEnumValueFromDescription<T>(string description)
        {
            var field = typeof(T).GetFields()
                .AsParallel().SelectMany(f => f.GetCustomAttributes(
                    typeof(DescriptionAttribute), false), (
                       f, a) => new { Field = f, Att = a }).SingleOrDefault(a => ((DescriptionAttribute)a.Att)
                             .Description.Equals(description));
            return field != null ? (T)field.Field.GetRawConstantValue() : default(T);
        }

        ///////////////////////////////////////////////////////////////////////////
        //    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    //
        ///////////////////////////////////////////////////////////////////////////
        /// <summary>
        ///     Get the description from an enumeration value.
        /// </summary>
        /// <param name="value">an enumeration value</param>
        /// <returns>the description or the empty string</returns>
        private static string wasGetDescriptionFromEnumValue(Enum value)
        {
            DescriptionAttribute attribute = value.GetType()
                .GetField(value.ToString())
                .GetCustomAttributes(typeof(DescriptionAttribute), false)
                .SingleOrDefault() as DescriptionAttribute;
            return attribute != null ? attribute.Description : string.Empty;
        }

        private readonly Action SetUserConfiguration = () =>
        {
            // general
            Vassal.vassalConfiguration.HTTPServerURL = mainForm.HTTPServerURL.Text;
            Vassal.vassalConfiguration.Group = mainForm.Group.Text;
            Vassal.vassalConfiguration.Password = mainForm.Password.Text;
            uint outUint;
            if (uint.TryParse(mainForm.TeleportTimeout.Text, out outUint))
            {
                Vassal.vassalConfiguration.TeleportTimeout = outUint;
            }
            if (uint.TryParse(mainForm.DataTimeout.Text, out outUint))
            {
                Vassal.vassalConfiguration.DataTimeout = outUint;
            }
            if (uint.TryParse(mainForm.RegionRestartDelay.Text, out outUint))
            {
                Vassal.vassalConfiguration.RegionRestartDelay = outUint;
            }

            // filters
            Vassal.vassalConfiguration.InputFilters =
                mainForm.ActiveInputFilters.Items.Cast<ListViewItem>().Select(o => (Filter)o.Tag).ToList();
            Vassal.vassalConfiguration.OutputFilters =
                mainForm.ActiveOutputFilters.Items.Cast<ListViewItem>().Select(o => (Filter)o.Tag).ToList();

            // cryptography
            Vassal.vassalConfiguration.ENIGMA = new ENIGMA
            {
                rotors = mainForm.ENIGMARotorSequence.Items.Cast<ListViewItem>().Select(o => (char)o.Tag).ToArray(),
                plugs = mainForm.ENIGMAPlugSequence.Items.Cast<ListViewItem>().Select(o => (char)o.Tag).ToArray(),
                reflector = mainForm.ENIGMAReflector.Text[0]
            };

            Vassal.vassalConfiguration.VIGENERESecret = mainForm.VIGENERESecret.Text;

        };

        private readonly Action GetUserConfiguration = () =>
        {
            // general
            mainForm.HTTPServerURL.Text = Vassal.vassalConfiguration.HTTPServerURL;
            mainForm.Group.Text = Vassal.vassalConfiguration.Group;
            mainForm.Password.Text = Vassal.vassalConfiguration.Password;
            mainForm.TeleportTimeout.Text = Vassal.vassalConfiguration.TeleportTimeout.ToString(Utils.EnUsCulture);
            mainForm.DataTimeout.Text = Vassal.vassalConfiguration.DataTimeout.ToString(Utils.EnUsCulture);
            mainForm.RegionRestartDelay.Text = Vassal.vassalConfiguration.RegionRestartDelay.ToString(Utils.EnUsCulture);

            // filters
            mainForm.ActiveInputFilters.Items.Clear();
            foreach (Filter filter in Vassal.vassalConfiguration.InputFilters)
            {
                mainForm.ActiveInputFilters.Items.Add(new ListViewItem
                {
                    Text = wasGetDescriptionFromEnumValue(filter),
                    Tag = filter
                });
            }
            mainForm.ActiveOutputFilters.Items.Clear();
            mainForm.ActiveInputFilters.DisplayMember = "Text";
            foreach (Filter filter in Vassal.vassalConfiguration.OutputFilters)
            {
                mainForm.ActiveOutputFilters.Items.Add(new ListViewItem
                {
                    Text = wasGetDescriptionFromEnumValue(filter),
                    Tag = filter
                });
            }
            mainForm.ActiveOutputFilters.DisplayMember = "Text";

            // cryptography
            mainForm.ENIGMARotorSequence.Items.Clear();
            foreach (char rotor in Vassal.vassalConfiguration.ENIGMA.rotors)
            {
                mainForm.ENIGMARotorSequence.Items.Add(new ListViewItem
                {
                    Text = rotor.ToString(),
                    Tag = rotor
                });
            }
            mainForm.ENIGMARotorSequence.DisplayMember = "Text";
            mainForm.ENIGMAPlugSequence.Items.Clear();
            foreach (char plug in Vassal.vassalConfiguration.ENIGMA.plugs)
            {
                mainForm.ENIGMAPlugSequence.Items.Add(new ListViewItem
                {
                    Text = plug.ToString(),
                    Tag = plug
                });
            }
            mainForm.ENIGMAPlugSequence.DisplayMember = "Text";
            mainForm.ENIGMAReflector.Text = Vassal.vassalConfiguration.ENIGMA.reflector.ToString();
            mainForm.VIGENERESecret.Text = Vassal.vassalConfiguration.VIGENERESecret;
        };

        public SettingsForm()
        {
            InitializeComponent();
            mainForm = this;
        }

        private void LoadSettingsRequested(object sender, EventArgs e)
        {
            mainForm.BeginInvoke((MethodInvoker)(() =>
            {
                switch (mainForm.LoadSettingsDialog.ShowDialog())
                {
                    case DialogResult.OK:
                        string file = mainForm.LoadSettingsDialog.FileName;
                        new Thread(() =>
                        {
                            mainForm.BeginInvoke((MethodInvoker)(() =>
                            {
                                try
                                {
                                    mainForm.StatusText.Text = @"loading settings...";
                                    mainForm.StatusProgress.Value = 0;

                                    // load settings
                                    VassalConfiguration.Load(file, ref Vassal.vassalConfiguration);
                                    mainForm.StatusProgress.Value = 50;
                                    GetUserConfiguration.Invoke();

                                    mainForm.StatusText.Text = @"settings loaded";
                                    mainForm.StatusProgress.Value = 100;
                                }
                                catch (Exception ex)
                                {
                                    mainForm.StatusText.Text = ex.Message;
                                }
                            }));
                        })
                        { IsBackground = true, Priority = ThreadPriority.Normal }.Start();
                        break;
                }
            }));
        }

        private void SaveSettingsRequested(object sender, EventArgs e)
        {
            mainForm.BeginInvoke((MethodInvoker)(() =>
            {
                switch (mainForm.SaveSettingsDialog.ShowDialog())
                {
                    case DialogResult.OK:
                        string file = mainForm.SaveSettingsDialog.FileName;
                        new Thread(() =>
                        {
                            mainForm.BeginInvoke((MethodInvoker)(() =>
                            {
                                try
                                {
                                    mainForm.StatusText.Text = @"saving settings...";
                                    mainForm.StatusProgress.Value = 0;

                                    // apply configuration
                                    SetUserConfiguration.Invoke();
                                    mainForm.StatusProgress.Value = 50;

                                    // save settings
                                    VassalConfiguration.Save(file, ref Vassal.vassalConfiguration);

                                    mainForm.StatusText.Text = @"settings saved";
                                    mainForm.StatusProgress.Value = 100;
                                }
                                catch (Exception ex)
                                {
                                    mainForm.StatusText.Text = ex.Message;
                                }
                            }));
                        })
                        { IsBackground = true, Priority = ThreadPriority.Normal }.Start();
                        break;
                }
            }));
        }

        private void AddInputDecoderRequested(object sender, EventArgs e)
        {
            mainForm.BeginInvoke((MethodInvoker)(() =>
            {
                if (string.IsNullOrEmpty(InputDecode.Text))
                {
                    InputDecode.BackColor = Color.MistyRose;
                    return;
                }
                InputDecode.BackColor = Color.Empty;
                ActiveInputFilters.Items.Add(new ListViewItem
                {
                    Text = InputDecode.Text,
                    Tag = wasGetEnumValueFromDescription<Filter>(InputDecode.Text)
                });
            }));
        }

        private void AddInputDecryptionRequested(object sender, EventArgs e)
        {
            mainForm.BeginInvoke((MethodInvoker)(() =>
            {
                if (string.IsNullOrEmpty(InputDecryption.Text))
                {
                    InputDecryption.BackColor = Color.MistyRose;
                    return;
                }
                InputDecryption.BackColor = Color.Empty;
                ActiveInputFilters.Items.Add(new ListViewItem
                {
                    Text = InputDecryption.Text,
                    Tag = wasGetEnumValueFromDescription<Filter>(InputDecryption.Text)
                });
            }));
        }

        private void AddOutputEncryptionRequested(object sender, EventArgs e)
        {
            mainForm.BeginInvoke((MethodInvoker)(() =>
            {
                if (string.IsNullOrEmpty(OutputEncrypt.Text))
                {
                    OutputEncrypt.BackColor = Color.MistyRose;
                    return;
                }
                OutputEncrypt.BackColor = Color.Empty;
                ActiveOutputFilters.Items.Add(new ListViewItem
                {
                    Text = OutputEncrypt.Text,
                    Tag = wasGetEnumValueFromDescription<Filter>(OutputEncrypt.Text)
                });
            }));
        }

        private void AddOutputEncoderRequested(object sender, EventArgs e)
        {
            mainForm.BeginInvoke((MethodInvoker)(() =>
            {
                if (string.IsNullOrEmpty(OutputEncode.Text))
                {
                    OutputEncode.BackColor = Color.MistyRose;
                    return;
                }
                OutputEncode.BackColor = Color.Empty;
                ActiveOutputFilters.Items.Add(new ListViewItem
                {
                    Text = OutputEncode.Text,
                    Tag = wasGetEnumValueFromDescription<Filter>(OutputEncode.Text)
                });
            }));
        }

        private void DeleteSelectedOutputFilterRequested(object sender, EventArgs e)
        {
            mainForm.BeginInvoke((MethodInvoker)(() =>
            {
                ListViewItem listViewItem = ActiveOutputFilters.SelectedItem as ListViewItem;
                if (listViewItem == null)
                {
                    ActiveOutputFilters.BackColor = Color.MistyRose;
                    return;
                }
                ActiveOutputFilters.BackColor = Color.Empty;
                ActiveOutputFilters.Items.RemoveAt(ActiveOutputFilters.SelectedIndex);
            }));
        }

        private void DeleteSelectedInputFilterRequested(object sender, EventArgs e)
        {
            mainForm.BeginInvoke((MethodInvoker)(() =>
            {
                ListViewItem listViewItem = ActiveInputFilters.SelectedItem as ListViewItem;
                if (listViewItem == null)
                {
                    ActiveInputFilters.BackColor = Color.MistyRose;
                    return;
                }
                ActiveInputFilters.BackColor = Color.Empty;
                ActiveInputFilters.Items.RemoveAt(ActiveInputFilters.SelectedIndex);
            }));
        }

        private void AddENIGMARotorRequested(object sender, EventArgs e)
        {
            mainForm.BeginInvoke((MethodInvoker)(() =>
            {
                if (string.IsNullOrEmpty(ENIGMARotor.Text))
                {
                    ENIGMARotor.BackColor = Color.MistyRose;
                    return;
                }
                ENIGMARotor.BackColor = Color.Empty;
                ENIGMARotorSequence.Items.Add(new ListViewItem
                {
                    Text = ENIGMARotor.Text,
                    Tag = ENIGMARotor.Text[0]
                });
            }));
        }

        private void DeleteENIGMARotorRequested(object sender, EventArgs e)
        {
            mainForm.BeginInvoke((MethodInvoker)(() =>
            {
                ListViewItem listViewItem = ENIGMARotorSequence.SelectedItem as ListViewItem;
                if (listViewItem == null)
                {
                    ENIGMARotorSequence.BackColor = Color.MistyRose;
                    return;
                }
                ENIGMARotorSequence.BackColor = Color.Empty;
                ENIGMARotorSequence.Items.RemoveAt(ENIGMARotorSequence.SelectedIndex);
            }));
        }

        private void AddENIGMAPlugRequested(object sender, EventArgs e)
        {
            mainForm.BeginInvoke((MethodInvoker)(() =>
            {
                if (string.IsNullOrEmpty(ENIGMARing.Text))
                {
                    ENIGMARing.BackColor = Color.MistyRose;
                    return;
                }
                ENIGMARing.BackColor = Color.Empty;
                ENIGMAPlugSequence.Items.Add(new ListViewItem
                {
                    Text = ENIGMARing.Text,
                    Tag = ENIGMARing.Text[0]
                });
            }));
        }

        private void DeleteENIGMAPlugRequested(object sender, EventArgs e)
        {
            mainForm.BeginInvoke((MethodInvoker)(() =>
            {
                ListViewItem listViewItem = ENIGMAPlugSequence.SelectedItem as ListViewItem;
                if (listViewItem == null)
                {
                    ENIGMAPlugSequence.BackColor = Color.MistyRose;
                    return;
                }
                ENIGMAPlugSequence.BackColor = Color.Empty;
                ENIGMAPlugSequence.Items.RemoveAt(ENIGMAPlugSequence.SelectedIndex);
            }));
        }

        private void SettingsFormShown(object sender, EventArgs e)
        {
            GetUserConfiguration.Invoke();
        }

        private void SettingsFormClosing(object sender, FormClosingEventArgs e)
        {
            // apply configuration
            SetUserConfiguration.Invoke();
            // save settings
            VassalConfiguration.Save(Vassal.VASSAL_CONSTANTS.VASSAL_CONFIGURATION_FILE, ref Vassal.vassalConfiguration);
            // set parameters for Vassal
            mainForm.Invoke((MethodInvoker) (() =>
            {
                Vassal.vassalForm.Invoke((MethodInvoker) (() =>
                {
                    if (string.IsNullOrEmpty(Vassal.vassalForm.RegionRestartDelayBox.Text))
                    {
                        Vassal.vassalForm.RegionRestartDelayBox.Text = mainForm.RegionRestartDelay.Text;
                    }
                }));
            }));
            // Spawn a thread to check Corrade's connection status.
            new Thread(() =>
            {
                TcpClient tcpClient = new TcpClient();
                try
                {
                    System.Uri uri = new System.Uri(Vassal.vassalConfiguration.HTTPServerURL);
                    tcpClient.Connect(uri.Host, uri.Port);
                    // port open
                    Vassal.vassalForm.BeginInvoke((MethodInvoker)(() => { Vassal.vassalForm.Tabs.Enabled = true; }));
                    // set the loading spinner
                    Assembly thisAssembly = System.Reflection.Assembly.GetExecutingAssembly();
                    System.IO.Stream file =
                        thisAssembly.GetManifestResourceStream("Vassal.img.loading.gif");
                    switch (file != null)
                    {
                        case true:
                            Vassal.vassalForm.BeginInvoke((MethodInvoker)(() =>
                            {
                                Vassal.vassalForm.RegionAvatarsMap.SizeMode = PictureBoxSizeMode.CenterImage;
                                Vassal.vassalForm.RegionAvatarsMap.Image = Image.FromStream(file);
                                Vassal.vassalForm.RegionAvatarsMap.Refresh();
                            }));
                            break;
                    }
                }
                catch (Exception)
                {
                    // port closed
                    Vassal.vassalForm.BeginInvoke((MethodInvoker)(() => { Vassal.vassalForm.Tabs.Enabled = false; }));
                }
            })
            { IsBackground = true }.Start();
        }
    }
}