Korero – Rev 1

Subversion Repositories:
Rev:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Korero.Communication;
using Korero.Properties;
using Korero.Serialization;
using Korero.Utilities;
using Serilog;

namespace Korero.Teleport
{
    public partial class TeleportForm : Form
    {
        #region Private Delegates, Events, Enums, Properties, Indexers and Fields

        private readonly CancellationToken _cancellationToken;

        private readonly CancellationTokenSource _cancellationTokenSource;

        private readonly Task _loadInventoryLandmarksTask;

        private readonly MainForm _mainForm;

        private readonly MqttCommunication _mqttCommunication;

        #endregion

        #region Constructors, Destructors and Finalizers

        public TeleportForm()
        {
            InitializeComponent();
            Utilities.WindowState.FormTracker.Track(this);

            _cancellationTokenSource = new CancellationTokenSource();
            _cancellationToken = _cancellationTokenSource.Token;
        }

        public TeleportForm(MainForm mainForm, MqttCommunication mqttCommunication) : this()
        {
            _mainForm = mainForm;
            _mqttCommunication = mqttCommunication;

            _loadInventoryLandmarksTask = LoadInventoryLandmarks(_cancellationToken);
            _mqttCommunication.NotificationReceived += MqttCommunication_NotificationReceived;
        }

        /// <summary>
        ///     Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && components != null)
            {
                components.Dispose();
            }

            _mqttCommunication.NotificationReceived -= MqttCommunication_NotificationReceived;
            base.Dispose(disposing);
        }

        #endregion

        #region Event Handlers

        private void MqttCommunication_NotificationReceived(object sender, MqttNotificationEventArgs e)
        {
            switch (e.Notification["notification"])
            {
                case "teleport":
                    toolStripStatusLabel1.Text = $"Teleport status: {e.Notification["status"]}";
                    break;
            }
        }

        private async void Button1_Click(object sender, EventArgs e)
        {
            if (!await CheckTeleportRegion(textBox1.Text))
            {
                return;
            }

            if (!int.TryParse(textBox2.Text, out var x))
            {
                x = 128;
            }

            if (!int.TryParse(textBox3.Text, out var y))
            {
                y = 128;
            }

            if (!int.TryParse(textBox4.Text, out var z))
            {
                z = 25;
            }

            await TeleportManual(textBox1.Text, x, y, z);
        }

        private async void TextBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar != (char) Keys.Enter)
            {
                return;
            }

            if (!await CheckTeleportRegion(textBox1.Text))
            {
                return;
            }

            if (!int.TryParse(textBox2.Text, out var x))
            {
                x = 128;
            }

            if (!int.TryParse(textBox3.Text, out var y))
            {
                y = 128;
            }

            if (!int.TryParse(textBox4.Text, out var z))
            {
                z = 25;
            }

            await TeleportManual(textBox1.Text, x, y, z);
        }

        private async void Button2_Click(object sender, EventArgs e)
        {
            var index = comboBox1.SelectedIndex;
            if (index == -1)
            {
                return;
            }

            var item = (LandmarkComboBoxItem) comboBox1.SelectedItem;

            toolStripStatusLabel1.Text = string.Empty;

            await TeleportLandmark(item.Id);
        }

        private async void Button3_Click(object sender, EventArgs e)
        {
            var data = new Dictionary<string, string>
            {
                {"command", "gohome"},
                {"group", Settings.Default.Group},
                {"password", Settings.Default.Password}
            };

            var callback = await _mqttCommunication.SendCommand(new Command(data), _cancellationToken);

            if (callback == null || !callback.Success)
            {
                if (callback != null)
                {
                    Log.Warning("Command {Command} has failed with {Error}.",
                        callback.Command, callback.Error);
                }

                toolStripStatusLabel1.Text = "Could not teleport home.";

                return;
            }

            toolStripStatusLabel1.Text = "Teleported home.";
        }

        private void TeleportForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            _cancellationTokenSource.Cancel();
        }

        #endregion

        #region Private Methods

        private async Task LoadInventoryLandmarks(CancellationToken cancellationToken)
        {
            var data = new Dictionary<string, string>
            {
                {"command", "inventory"},
                {"group", Settings.Default.Group},
                {"password", Settings.Default.Password},
                {"action", "ls"},
                {"path", "/My Inventory/Landmarks"}
            };

            var callback = await _mqttCommunication.SendCommand(new Command(data), cancellationToken);

            if (callback == null || !callback.Success)
            {
                if (callback != null)
                {
                    Log.Warning("Command {Command} has failed with {Error}.",
                        callback.Command, callback.Error);
                }

                return;
            }

            comboBox1.InvokeIfRequired(comboBox => { comboBox.Items.Clear(); });

            foreach (var landmark in CsvStride(callback.Data, 10))
            {
                var index = Array.IndexOf(landmark, "name");
                var name = landmark[index + 1];
                index = Array.IndexOf(landmark, "type");
                var type = landmark[index + 1];

                if (type != "Landmark")
                {
                    continue;
                }

                index = Array.IndexOf(landmark, "item");

                var item = landmark[index + 1];

                if (!Guid.TryParse(item, out var id))
                {
                    continue;
                }

                var landmarkComboBoxItem = new LandmarkComboBoxItem(name, id);

                comboBox1.InvokeIfRequired(comboBox => { comboBox.Items.Add(landmarkComboBoxItem); });
            }
        }

        private async Task TeleportManual(string region, int x, int y, int z)
        {
            var data = new Dictionary<string, string>
            {
                {"command", "teleport"},
                {"group", Settings.Default.Group},
                {"password", Settings.Default.Password},
                {"entity", "region"},
                {"region", region},
                {"position", $"<{x}, {y}, {z}>"}
            };

            var callback = await _mqttCommunication.SendCommand(new Command(data), _cancellationToken);

            if (callback == null || !callback.Success)
            {
                if (callback != null)
                {
                    Log.Warning("Command {Command} has failed with {Error}.",
                        callback.Command, callback.Error);
                }
            }
        }

        private async Task<bool> CheckTeleportRegion(string name)
        {
            // Check for region name roundtrip.
            var data = new Dictionary<string, string>
            {
                {"command", "getgridregiondata"},
                {"group", Settings.Default.Group},
                {"password", Settings.Default.Password},
                {"entity", "region"},
                {"region", textBox1.Text},
                {"data", "Name"}
            };

            var callback = await _mqttCommunication.SendCommand(new Command(data), _cancellationToken);

            if (callback == null || !callback.Success)
            {
                if (callback != null)
                {
                    Log.Warning("Command {Command} has failed with {Error}.",
                        callback.Command, callback.Error);
                }

                return false;
            }

            if (!string.Equals(name, callback["Name"].FirstOrDefault(), StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }

            return true;
        }

        private static IEnumerable<string[]> CsvStride(string input, int stride)
        {
            var i = 0;
            return new CSV(input).Select(s => new {s, num = i++})
                .GroupBy(t => t.num / stride, t => t.s)
                .Select(g => g.ToArray());
        }

        private async Task TeleportLandmark(Guid id)
        {
            var data = new Dictionary<string, string>
            {
                {"command", "teleport"},
                {"group", Settings.Default.Group},
                {"password", Settings.Default.Password},
                {"entity", "landmark"},
                {"item", $"{id.ToString()}"}
            };

            var callback = await _mqttCommunication.SendCommand(new Command(data), _cancellationToken);

            if (callback == null || !callback.Success)
            {
                if (callback != null)
                {
                    Log.Warning("Command {Command} has failed with {Error}.",
                        callback.Command, callback.Error);
                }
            }
        }

        #endregion
    }
}

Generated by GNU Enscript 1.6.5.90.