HamBook – Rev 15

Subversion Repositories:
Rev:
using Configuration;
using HamBook.Properties;
using HamBook.Radios;
using HamBook.Radios.Generic;
using Serilog;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HamBook
{
    public partial class MemoryOrganizerForm : Form
    {
        private Configuration.Configuration Configuration { get; set; }

        private CatAssemblies _catAssemblies;
        private CancellationToken _cancellationToken;

        public MemoryOrganizerForm()
        {
            InitializeComponent();
        }

        public MemoryOrganizerForm(Configuration.Configuration configuration, CatAssemblies catAssemblies, CancellationToken cancellationToken) : this()
        {
            Configuration = configuration;
            _catAssemblies = catAssemblies;
            _cancellationToken = cancellationToken;
        }

        /// <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();
            }
            base.Dispose(disposing);
        }

        private async void button1_Click(object sender, EventArgs e)
        {
            var rows = GetSelectedDataGridViewRows(dataGridView1);
            await ReadMemoryBanks(rows);
        }

        private async void button2_Click(object sender, EventArgs e)
        {
            var rows = GetSelectedDataGridViewRows(dataGridView1);
            await WriteMemoryBanks(rows);
        }

        private void MemoryOrganizerForm_Load(object sender, EventArgs e)
        {
            toolStripProgressBar1.Minimum = 0;
            toolStripProgressBar1.Maximum = 98;

            var memoryBankQueue = new ConcurrentQueue<int>();
            var snapshotsQueuedTaskCompletionSource = new TaskCompletionSource<object>();

            async void IdleHandler(object idleHandlerSender, EventArgs idleHandlerArgs)
            {
                await snapshotsQueuedTaskCompletionSource.Task;

                try
                {
                    if (!memoryBankQueue.TryDequeue(out var memoryBank))
                    {
                        Application.Idle -= IdleHandler;

                        dataGridView1.Sort(dataGridView1.Columns["LocationColumn"], ListSortDirection.Ascending);
                        toolStripStatusLabel1.Text = "Done.";

                        return;
                    }

                    var index = dataGridView1.Rows.Add();

                    dataGridView1.Rows[index].Cells["LocationColumn"].Value = $"{memoryBank:000}";
                    dataGridView1.Rows[index].Cells["FrequencyColumn"].Value = default;
                    dataGridView1.Rows[index].Cells["ClarifierDirectionColumn"].Value = default;
                    dataGridView1.Rows[index].Cells["ClarifierOffsetColumn"].Value = default;
                    dataGridView1.Rows[index].Cells["ClarColumn"].Value = default;
                    dataGridView1.Rows[index].Cells["ModeColumn"].Value = default;
                    dataGridView1.Rows[index].Cells["CtcssColumn"].Value = default;
                    dataGridView1.Rows[index].Cells["PhaseColumn"].Value = default;
                    dataGridView1.Rows[index].Cells["TagColumn"].Value = default;
                    dataGridView1.Rows[index].Cells["TextColumn"].Value = default;

                    toolStripStatusLabel1.Text = $"{Resources.Read_memory_bank} {memoryBank}";

                    toolStripProgressBar1.Increment(1);

                    statusStrip1.Update();
                }
                catch (Exception exception)
                {
                    Log.Error(exception, Resources.Could_not_update_data_grid_view);
                }
            }

            Application.Idle += IdleHandler;
            try
            {
                foreach (var memoryBank in Enumerable.Range(1, 99))
                {
                    memoryBankQueue.Enqueue(memoryBank);
                }

                snapshotsQueuedTaskCompletionSource.TrySetResult(new { });
            }
            catch (Exception exception)
            {
                Application.Idle -= IdleHandler;

                Log.Error(exception, Resources.Unable_to_create_memory_banks);
            }
        }

        private void DataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
        {
            var dataGridView = (DataGridView)sender;

            if (dataGridView.CurrentCell is DataGridViewCheckBoxCell)
            {
                dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
            }
        }

        private void DataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            var dataGridView = (DataGridView)sender;

            dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }

        private void DataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            var dataGridView = (DataGridView)sender;

            if (dataGridView.CurrentCell is DataGridViewCheckBoxCell)
            {
                if (dataGridView.CurrentCell.IsInEditMode)
                {
                    if (dataGridView.IsCurrentCellDirty)
                    {
                        dataGridView.EndEdit();
                    }
                }
            }
        }

        private void DataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            var dataGridView = (DataGridView)sender;

            if (e.RowIndex == -1 || e.ColumnIndex == -1)
            {
                return;
            }

            switch (dataGridView.Columns[e.ColumnIndex].Name)
            {
                case "EnableColumn":
                    //ProcessEnable(dataGridView.Rows[e.RowIndex]);
                    break;
            }
        }

        private void DataGridView1_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
        {
            var dataGridView = (DataGridView)sender;

            if (e.RowIndex == -1 || e.ColumnIndex == -1 ||
                !(dataGridView.Columns[e.ColumnIndex] is DataGridViewCheckBoxColumn))
            {
                return;
            }

            dataGridView.EndEdit();
        }

        private void DataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            var dataGridView = (DataGridView)sender;

            if (e.RowIndex == -1 || e.ColumnIndex == -1 ||
                !(dataGridView.Columns[e.ColumnIndex] is DataGridViewCheckBoxColumn))
            {
                return;
            }

            dataGridView.EndEdit();
        }

        private void DataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            // @(-.-)@ -(o.o)- @(o_o)@
        }

        private static List<DataGridViewRow> GetSelectedDataGridViewRows(DataGridView dataGridView)
        {
            return dataGridView.SelectedRows.OfType<DataGridViewRow>().OrderBy(row => row.Index).ToList();
        }

        private async Task WriteMemoryBanks(List<DataGridViewRow> rows)
        {
            var count = rows.Count;

            toolStripProgressBar1.Minimum = 0;
            toolStripProgressBar1.Maximum = count;

            var progress = new Progress<DataGridViewRowProgress>(rowProgress =>
            {
                switch (rowProgress)
                {
                    case DataGridViewRowProgressSuccess<bool> rowProgressSuccess:
                        var success = rowProgressSuccess.Data;

                        if (!success)
                        {
                            Log.Error($"{Resources.Could_not_write_memory_bank}");

                            toolStripStatusLabel1.Text =
                                $"{Resources.Could_not_write_memory_bank} {rowProgress.Index + 1}";
                            toolStripProgressBar1.Value = rowProgress.Index + 1;
                            statusStrip1.Update();

                            return;
                        }

                        toolStripStatusLabel1.Text =
                            $"{Resources.Wrote_memory_bank} {rowProgress.Index + 1}";
                        toolStripProgressBar1.Value = rowProgress.Index + 1;
                        statusStrip1.Update();
                        break;
                    case DataGridViewRowProgressFailure rowProgressFailure:
                        Log.Error(rowProgressFailure.Exception, $"{Resources.Could_not_write_memory_bank}");

                        toolStripStatusLabel1.Text =
                            $"{Resources.Could_not_write_memory_bank} {rowProgress.Index + 1}";
                        toolStripProgressBar1.Value = rowProgress.Index + 1;
                        statusStrip1.Update();
                        break;
                }
            });

            await Task.Run(() => WriteMemoryBanks(rows, progress, _cancellationToken), _cancellationToken);

            if (!_cancellationToken.IsCancellationRequested)
            {
                toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
                toolStripStatusLabel1.Text = "Done.";
            }
        }

        private async Task ReadMemoryBanks(IReadOnlyList<DataGridViewRow> rows)
        {
            var count = rows.Count;

            toolStripProgressBar1.Minimum = 0;
            toolStripProgressBar1.Maximum = count;

            var progress = new Progress<DataGridViewRowProgress>(rowProgress =>
            {
                switch(rowProgress)
                {
                    case DataGridViewRowProgressSuccess<MemoryChannel> rowProgressSuccess:
                        var result = rowProgressSuccess.Data;

                        //rowProgress.Row.Cells["LocationColumn"].Value = $"{rowProgressSuccess.Index + 1:000}";
                        rowProgress.Row.Cells["FrequencyColumn"].Value = result.Frequency;
                        rowProgress.Row.Cells["ClarifierDirectionColumn"].Value = (char)result.ClarifierDirection;
                        rowProgress.Row.Cells["ClarifierOffsetColumn"].Value = result.ClarifierOffset;
                        rowProgress.Row.Cells["ClarColumn"].Value = result.Clar;
                        rowProgress.Row.Cells["ModeColumn"].Value = (string)result.MemoryRadioMode;
                        rowProgress.Row.Cells["CtcssColumn"].Value = (string)result.CtcssMode;
                        rowProgress.Row.Cells["PhaseColumn"].Value = (string)result.Phase;
                        rowProgress.Row.Cells["TagColumn"].Value = result.Tag;
                        rowProgress.Row.Cells["TextColumn"].Value = result.Text.Trim();

                        break;
                    case DataGridViewRowProgressFailure rowProgressFailure:
                        Log.Error(rowProgressFailure.Exception, $"{Resources.Could_not_read_memory_bank}");

                        break;
                }

                toolStripStatusLabel1.Text =
                    $"{Resources.Read_memory_bank} {rowProgress.Index + 1}";
                toolStripProgressBar1.Value = rowProgress.Index + 1;

                statusStrip1.Update();
            });

            await Task.Run(() => ReadMemoryBanks(rows, progress, _cancellationToken), _cancellationToken);

            if (!_cancellationToken.IsCancellationRequested)
            {
                toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
                toolStripStatusLabel1.Text = "Done.";
            }
        }

        private async Task ReadMemoryBanks(IReadOnlyList<DataGridViewRow> rows, IProgress<DataGridViewRowProgress> progress,
                                 CancellationToken cancellationToken)
        {
            var count = rows.Count;

            for (var i = 0; i < count && !cancellationToken.IsCancellationRequested; ++i)
            {
                try
                {
                    var location = int.Parse($"{rows[i].Cells["LocationColumn"].Value}");

                    var memoryBank = $"{location:000}";

                    var result = await _catAssemblies.CatReadAsync<MemoryChannel>("MT", new object[] { memoryBank }, _cancellationToken);

                    progress.Report(new DataGridViewRowProgressSuccess<MemoryChannel>(rows[i], i, result));
                }
                catch (UnexpectedRadioResponseException exception)
                {
                    progress.Report(new DataGridViewRowProgressFailure(rows[i], i, exception));
                }
                catch (Exception exception)
                {
                    progress.Report(new DataGridViewRowProgressFailure(rows[i], i, exception));
                }
            }
        }

        private async Task WriteMemoryBanks(IReadOnlyList<DataGridViewRow> rows, IProgress<DataGridViewRowProgress> progress,
                         CancellationToken cancellationToken)
        {
            var count = rows.Count;

            for (var i = 0; i < count && !cancellationToken.IsCancellationRequested; ++i)
            {
                try
                {
                    var location = int.Parse($"{rows[i].Cells["LocationColumn"].Value}");

                    var currentLocation = $"{location:000}";
                    var frequency = int.Parse($"{rows[i].Cells["FrequencyColumn"].Value}");
                    var clarifierDirection = char.Parse($"{rows[i].Cells["ClarifierDirectionColumn"].Value}");
                    var clarifierOffset = int.Parse($"{rows[i].Cells["ClarifierOffsetColumn"].Value}");
                    var clar = bool.Parse($"{rows[i].Cells["ClarColumn"].Value}");
                    var radioMode = new MemoryRadioMode($"{rows[i].Cells["ModeColumn"].Value}");
                    var ctcssMode = new CtcssMode($"{rows[i].Cells["CtcssColumn"].Value}");
                    var phase = new RadioPhase($"{rows[i].Cells["PhaseColumn"].Value}");
                    var tag = bool.Parse($"{rows[i].Cells["TagColumn"].Value}");
                    var text = $"{rows[i].Cells["TextColumn"].Value}";

                    var memoryChannel = new MemoryChannel
                    {
                        CurrentLocation = currentLocation,
                        Frequency = frequency,
                        ClarifierDirection = clarifierDirection,
                        ClarifierOffset = clarifierOffset,
                        Clar = clar,
                        MemoryRadioMode = radioMode,
                        CtcssMode = ctcssMode,
                        Phase = phase,
                        Tag = tag,
                        Text = text
                    };

                    var result = await _catAssemblies.CatSetAsync<MemoryChannel, bool>("MT", new object[] { memoryChannel }, _cancellationToken);

                    progress.Report(new DataGridViewRowProgressSuccess<bool>(rows[i], i, result));
                }
                catch (UnexpectedRadioResponseException exception)
                {
                    progress.Report(new DataGridViewRowProgressFailure(rows[i], i, exception));
                }
                catch (Exception exception)
                {
                    progress.Report(new DataGridViewRowProgressFailure(rows[i], i, exception));
                }
            }
        }
    }
}