/*
 *****************************************************************************
 *                                                                           *
 *              IMPINJ CONFIDENTIAL AND PROPRIETARY                          *
 *                                                                           *
 * This source code is the sole property of Impinj, Inc. Reproduction or     *
 * utilization of this source code in whole or in part is forbidden without  *
 * the prior written consent of Impinj, Inc.                                 *
 *                                                                           *
 * (c) Copyright Impinj, Inc. 2015. All rights reserved.                     *
 *                                                                           *
 *****************************************************************************/
using System;
using System.Windows;
using Microsoft.Win32;

using OxyPlot.Pdf;

namespace Impinj
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // Constants
        const string ReaderHostnameDefault = @"SpeedwayR-10-XX-XX";

        // Data members
        private string _SpeedwayRHostname = ReaderHostnameDefault;
        private bool ReaderHostnameChanged = false;
        private DeviceController ItemEncodeDeviceController;

        private bool isConnected = false;
        private bool isOperating = false;

        // Define a mutable hostname type
        public string SpeedwayRHostname
        {
            get { return _SpeedwayRHostname; }
            set
            {
                if (value != ReaderHostnameDefault)
                {
                    _SpeedwayRHostname = value;
                    ReaderHostnameChanged = true;
                }
            }
        }

        // Main Window constructor
        public MainWindow()
        {
            InitializeComponent();
            ReaderHostnameTextBox.Text = ReaderHostnameDefault;
        }

        // Connect button click operation
        private void connectButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // First, extract the current reader hostname from the GUI
                SpeedwayRHostname = ReaderHostnameTextBox.Text;

                // Manage the Connect/Disconnect operation of the connectButton 
                if (isConnected == false)
                {                // If the SpeedwayR hostname has not been changed, let
                // the user know that it has to be updated.
                    if (false == ReaderHostnameChanged)
                    {
                        MessageBox.Show(
                            "You must enter a valid hostname",
                            "Invalid hostname",
                            MessageBoxButton.OK,
                            MessageBoxImage.Exclamation
                            );

                        return;
                    }
                    else
                    {
                        string firmwareVersion = string.Empty;

                        // Create a new DeviceController object and establish
                        // a connection
                        ItemEncodeDeviceController = new DeviceController();
                        firmwareVersion = ItemEncodeDeviceController.Connect(SpeedwayRHostname);

                        // If we have reached here, then we are connected to
                        // the ItemEncode device, so update the GUI accordingly
                        DataContext = ItemEncodeDeviceController;
                        connectionStatusBarItem.Content = string.Format(
                            "Connected to device {0} running ItemEncodeVerify Version {1}",
                            SpeedwayRHostname,
                            firmwareVersion
                            );
                        connectButton.Content = "Disconnect";
                        startProfilerButton.IsEnabled = true;
                        txPowerTextBox.IsEnabled = true;
                        rxSensitivityTextBox.IsEnabled = true;
                        fixedFrequencyTextBox.IsEnabled = true;
                        isConnected = true;
                    }
                }
                else
                {
                    // Disconnect from the ItemEncode device
                    ItemEncodeDeviceController.Disconnect();
                    ItemEncodeDeviceController = null;

                    // Update GUI to reflect disconnected state
                    connectionStatusBarItem.Content = "Not Connected";
                    connectButton.Content = "Connect";
                    startProfilerButton.IsEnabled = false;
                    txPowerTextBox.IsEnabled = false;
                    rxSensitivityTextBox.IsEnabled = false;
                    fixedFrequencyTextBox.IsEnabled = false;
                    isConnected = false;
                }
            }
            catch (Exception ex)
            {
                // An exception has occurred, so inform the user
                string ex_msg = string.Format(
                    "Exception: {0}{1}{2}",
                    Environment.NewLine,
                    ex.Message,
                    (null == ex.InnerException) ? string.Empty : Environment.NewLine + ex.InnerException.Message
                    );

                MessageBox.Show(
                    ex_msg,
                    "Error Connecting/Disconnecting",
                    MessageBoxButton.OK,
                    MessageBoxImage.Exclamation
                    );

                // Disconnect from the ItemEncodeVerify device
                ItemEncodeDeviceController.Disconnect();
            }
        }

        // Start Trigger Profiler button click operation
        private void startTriggerProfilerButton_Click(object sender, RoutedEventArgs e)
        {
            // Continue only if the application is connected to an ItemEncode
            // device
            if ((true == ItemEncodeDeviceController.IsConnected) &&
                (false == isOperating))
            {
                try
                {
                    // Determine whether a fixedFrequency has been defined
                    double fixedFrequency = 0;
                    
                    if (false == string.IsNullOrEmpty(fixedFrequencyTextBox.Text))
                    {
                        fixedFrequency = double.Parse(fixedFrequencyTextBox.Text);
                    }

                    // Start the ItemEncode device with the power and receive
                    // settings specified in the GUI
                    ItemEncodeDeviceController.Start(
                        (int)(double.Parse(txPowerTextBox.Text) * 1e2),
                        (int)(double.Parse(rxSensitivityTextBox.Text) * 1e2),
                        (int)(fixedFrequency * 1e3));

                    // ItemEncode device is operating to update GUI accordingly
                    startProfilerButton.Content = "Stop";
                    connectButton.IsEnabled = false;
                    isOperating = true;
                }
                // Exception handler
                catch (Exception ex)
                {
                    string exMsg = ex.Message;
                    exMsg += (null == ex.InnerException) ? string.Empty : Environment.NewLine + ex.InnerException.Message;

                    MessageBox.Show(exMsg, "Exception!", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                }
            }
            else if(true == isOperating)
            {
                try
                {
                    // Stop the ItemEncode device
                    ItemEncodeDeviceController.Stop();

                    // Operation has stopped, so opdate the GUI accordingly
                    startProfilerButton.Content = "Start";
                    connectButton.IsEnabled = true;
                    isOperating = false;
                }
                // Exception handler
                catch (Exception ex)
                {
                    string exMsg = ex.Message;
                    exMsg += (null == ex.InnerException) ? string.Empty : Environment.NewLine + ex.InnerException.Message;

                    MessageBox.Show(exMsg, "Exception!", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                }
            }
        }

        // Window closing event operation.
        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // Ensure that a graceful disconnect from the ItemEncode device is
            // performed prior to closing the application
            if ((ItemEncodeDeviceController != null) && (isConnected))
            {
                ItemEncodeDeviceController.Stop();
                ItemEncodeDeviceController.Disconnect();
                ItemEncodeDeviceController = null;
            }
        }

        // File->Save menu item operation
        private void FileSavePlot(object sender, RoutedEventArgs e)
        {
            // Provide user option to save plot display to file
            var dlg = new SaveFileDialog();
            dlg.Filter = ".png files|*.png|.pdf files|*.pdf";
            dlg.DefaultExt = ".png";
            if (dlg.ShowDialog(this).Value)
            {
                var ext = System.IO.Path.GetExtension(dlg.FileName).ToLower();
                switch (ext)
                {
                    case ".png":
                        fovPlot.SaveBitmap(dlg.FileName, (int)fovPlot.ActualWidth, (int)fovPlot.ActualHeight, OxyPlot.OxyColors.Automatic);
                        break;
                    case ".pdf":
                        PdfExporter.Export(fovPlot.Model, dlg.FileName, fovPlot.ActualWidth, fovPlot.ActualHeight);
                        break;
                }
            }

        }

        // File->Exit menu item operation
        private void FileExit(object sender, RoutedEventArgs e)
        {
            Close();
        }

    }
}
