public GarminFitnessCommunicatorDeviceController()
        {
            m_CommunicatorBridge = new GarminFitnessCommunicatorBridge();

            m_CommunicatorBridge.ControllerReady += new EventHandler(OnCommunicatorBridgeControllerReady);
            m_CommunicatorBridge.InitializeCompleted += new EventHandler<GarminFitnessCommunicatorBridge.InitializeCompletedEventArgs>(OnCommunicatorBridgeInitializeCompleted);
            m_CommunicatorBridge.ExceptionTriggered += new EventHandler<GarminFitnessCommunicatorBridge.ExceptionEventArgs>(OnCommunicatorBridgeExceptionTriggered);
            m_CommunicatorBridge.FinishFindDevices += new EventHandler<GarminFitnessCommunicatorBridge.FinishFindDevicesEventArgs>(OnCommunicatorBridgeFinishFindDevices);

            m_CommunicatorBridge.Start();
        }
        void OnControllerExceptionTriggered(object sender, GarminFitnessCommunicatorBridge.ExceptionEventArgs e)
        {
            if (CurrentTask != null &&
                (CurrentTask.Type == BasicTask.TaskTypes.Initialize ||
                 CurrentTask.Type == BasicTask.TaskTypes.RefreshDevices ||
                 CurrentTask.Type == BasicTask.TaskTypes.SetOperatingDevice))
            {
                try
                {
                    throw new Exception(e.ExceptionText);
                }
                catch (Exception exception)
                {
                    Logger.Instance.LogText(String.Format("Controller exception caught in manager : {0}\nStack:{1}", exception.Message, exception.StackTrace));
                }

                m_TimeoutTimer.Stop();
                CancelPendingTasks();
                CompleteCurrentTask(false, e.ExceptionText);
            }
        }
        private void OnCommunicatorBridgeInitializeCompleted(object sender, GarminFitnessCommunicatorBridge.InitializeCompletedEventArgs e)
        {
            Logger.Instance.LogText("Bridge initialization complete");

            m_Initialized = e.Success;

            if (InitializationCompleted != null)
            {
                InitializationCompleted(this, IsInitialized, e.ErrorText);
            }
        }
 private void OnCommunicatorBridgeExceptionTriggered(object sender, GarminFitnessCommunicatorBridge.ExceptionEventArgs e)
 {
     if (ExceptionTriggered != null)
     {
         ExceptionTriggered(sender, e);
     }
 }
        private void OnCommunicatorBridgeFinishFindDevices(object sender, GarminFitnessCommunicatorBridge.FinishFindDevicesEventArgs e)
        {
            XmlDocument devicesDocument = new XmlDocument();

            foreach (IGarminDevice device in m_Devices)
            {
                device.Dispose();
            }
            m_Devices.Clear();

            try
            {
                devicesDocument.LoadXml(e.DevicesString);

                foreach (XmlNode currentDeviceNode in devicesDocument.FirstChild.ChildNodes)
                {
                    GarminFitnessCommunicatorDevice newDevice = new GarminFitnessCommunicatorDevice(this, currentDeviceNode);

                    // Ignore & dispose invalid devices
                    if (newDevice.SoftwareVersion.Equals("0") ||
                        newDevice.DeviceId.Equals("4294967295"))    // 0xFFFFFFF
                    {
                        newDevice.Dispose();
                    }
                    else
                    {
                        m_Devices.Add(newDevice);
                    }
                }
            }
            catch
            {
                if (FindDevicesCompleted != null)
                {
                    FindDevicesCompleted(this, false, String.Empty);
                }
            }

            if (FindDevicesCompleted != null)
            {
                FindDevicesCompleted(this, true, String.Empty);
            }
        }
        private void OnBridgeWriteToDeviceCompleted(object sender, GarminFitnessCommunicatorBridge.TransferCompletedEventArgs e)
        {
            bool success = e.Success;
            DeviceOperations lastOperation = m_CurrentOperation;

            TriggerOperationWillCompleteEvent();

            switch (m_CurrentOperation)
            {
                case DeviceOperations.WriteProfile:
                    {
                        Logger.Instance.LogText("Comm. : Profile written");
                        break;
                    }
                case DeviceOperations.WriteWorkout:
                    {
                        Logger.Instance.LogText("Comm. : Workouts written");
                        break;
                    }
                default:
                    {
                        Debug.Assert(false);
                        success = false;
                        break;
                    }
            }

            m_CurrentOperation = DeviceOperations.Idle;

            if (WriteToDeviceCompleted != null)
            {
                WriteToDeviceCompleted(this, lastOperation, success, m_CancellationError);
            }
        }
        private void OnBridgeReadFromDeviceCompleted(object sender, GarminFitnessCommunicatorBridge.TransferCompletedEventArgs e)
        {
            bool success = e.Success;
            bool operationCompleted = true;
            DeviceOperations lastOperation = m_CurrentOperation;

            switch(m_CurrentOperation)
            {
                case DeviceOperations.ReadProfile:
                {
                    Logger.Instance.LogText("Comm. : Profile read");

                    TriggerOperationWillCompleteEvent();

                    if (success)
                    {
                        MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(e.DataString));

                        success = ProfileImporter.ImportProfile(stream);
                        stream.Close();
                    }

                    break;
                }
                case DeviceOperations.ReadMassStorageWorkouts:
                case DeviceOperations.ReadFITWorkouts:
                case DeviceOperations.ReadFITProfile:
                {
                    if (success)
                    {
                        if (m_CurrentOperation == DeviceOperations.ReadFITProfile)
                        {
                            Logger.Instance.LogText("Comm. : Mass storage profile read");
                        }
                        else
                        {
                            Logger.Instance.LogText("Comm. : Mass storage workout read");
                        }

                        ++m_MassStorageFileReadCount;
                        if (OperationProgressed != null)
                        {
                            OperationProgressed(this, m_CurrentOperation, m_MassStorageFileReadCount);
                        }

                        if (m_MassStorageFilesToDownload != null)
                        {
                            Debug.Assert(m_MassStorageFilesToDownload.Count > 0);
                            Logger.Instance.LogText(String.Format("Mass storage files remaining = {0}", m_MassStorageFilesToDownload.Count));

                            if (m_MassStorageFilesToDownload.Count > 0)
                            {
                                String currentFilename = m_TempDirectoryLocation + m_MassStorageFilesToDownload[0].Replace('/', '\\');
                                String fileDirectory = currentFilename.Substring(0, currentFilename.LastIndexOf('\\'));
                                Directory.CreateDirectory(fileDirectory);
                                FileStream newFile = File.Create(currentFilename);
                                Byte[] decodedData = UUDecode(e.DataString);

                                newFile.Write(decodedData, 0, decodedData.Length);
                                newFile.Close();
                                m_MassStorageFilesToDownload.RemoveAt(0);
                                operationCompleted = false;

                                Logger.Instance.LogText(String.Format("Mass storage files remaining after delete = {0}", m_MassStorageFilesToDownload.Count));

                                if (m_MassStorageFilesToDownload.Count > 0)
                                {
                                    m_Controller.CommunicatorBridge.GetBinaryFile(m_MassStorageFilesToDownload[0]);
                                }
                                else
                                {
                                    TriggerOperationWillCompleteEvent();

                                    if (m_CurrentOperation == DeviceOperations.ReadFITProfile)
                                    {
                                        success = ProfileImporter.AsyncImportDirectory(m_TempDirectoryLocation, this);
                                    }
                                    else
                                    {
                                        success = WorkoutImporter.AsyncImportDirectory(m_TempDirectoryLocation, this);
                                    }
                                }
                            }
                            else
                            {
                                try
                                {
                                    throw new Exception();
                                }
                                catch (Exception exception)
                                {
                                    Logger.Instance.LogText("Caught empty mass storage list\n" + exception.StackTrace);
                                }
                            }
                        }
                    }
                    else
                    {
                        TriggerOperationWillCompleteEvent();
                        m_MassStorageFilesToDownload.Clear();
                    }

                    break;
                }
                case DeviceOperations.ReadWorkout:
                {
                    Logger.Instance.LogText("Comm. : Workouts read");

                    TriggerOperationWillCompleteEvent();

                    if (success)
                    {
                        ImportWorkoutFileResult(e.DataString);
                    }

                    break;
                }
                default:
                {
                    Debug.Assert(false);
                    success = false;
                    break;
                }
            }

            if (operationCompleted)
            {
                m_CurrentOperation = DeviceOperations.Idle;

                if (ReadFromDeviceCompleted != null)
                {
                    ReadFromDeviceCompleted(this, lastOperation, success, m_CancellationError);
                }
            }
        }
        void OnBridgeReadDirectoryCompleted(object sender, GarminFitnessCommunicatorBridge.TransferCompletedEventArgs e)
        {
            bool operationComplete = true;

            m_IsReadingDirectory = false;

            if (e.Success)
            {
                if (OperationProgressed != null)
                {
                    OperationProgressed(this, m_CurrentOperation, 0);
                }

                if (m_CurrentOperation == DeviceOperations.ReadMassStorageWorkouts)
                {
                    m_MassStorageFilesToDownload = GetFilePaths(e.DataString);

                    Logger.Instance.LogText(String.Format("Comm. : Mass storage workout file count = {0}", m_MassStorageFilesToDownload.Count));
                }
                else if (m_CurrentOperation == DeviceOperations.ReadFITWorkouts)
                {
                    List<String> fitFilesOnDevice = GetFilePaths(e.DataString);

                    m_MassStorageFilesToDownload = new List<String>();

                    foreach (string fitFile in fitFilesOnDevice)
                    {
                        if (fitFile.StartsWith(m_FITWorkoutFileReadPath) ||
                            fitFile.StartsWith(m_FITWorkoutSchedulesFileReadPath))
                        {
                            m_MassStorageFilesToDownload.Add(fitFile);
                        }
                    }

                    Logger.Instance.LogText(String.Format("Comm. : Workout file count = {0}", m_MassStorageFilesToDownload.Count));
                }
                else if (m_CurrentOperation == DeviceOperations.ReadFITProfile)
                {
                    Logger.Instance.LogText("Comm. : Profile directory read");

                    List<String> fitFilesOnDevice = GetFilePaths(e.DataString);

                    m_MassStorageFilesToDownload = new List<String>();

                    foreach (string fitFile in fitFilesOnDevice)
                    {
                        if (fitFile.StartsWith(m_FITSettingsFileReadPath) ||
                            fitFile.StartsWith(m_FITSportFileReadPath))
                        {
                            m_MassStorageFilesToDownload.Add(fitFile);
                        }
                    }

                    Logger.Instance.LogText(String.Format("Comm. : Profile file count = {0}", m_MassStorageFilesToDownload.Count));
                }

                if (m_MassStorageFilesToDownload.Count > 0)
                {
                    operationComplete = false;

                    m_Controller.CommunicatorBridge.GetBinaryFile(m_MassStorageFilesToDownload[0]);
                }
            }

            if (operationComplete)
            {
                DeviceOperations lastOperation = m_CurrentOperation;
                m_CurrentOperation = DeviceOperations.Idle;

                if (ReadFromDeviceCompleted != null)
                {
                    ReadFromDeviceCompleted(this, lastOperation, e.Success, m_CancellationError);
                }
            }
        }
        void OnBridgeProgressChanged(object sender, GarminFitnessCommunicatorBridge.TransferProgressedEventArgs e)
        {
            Logger.Instance.LogText(String.Format("Comm. : Operation progress : {0}", e.Progress));

            if (OperationProgressed != null)
            {
                OperationProgressed(this, m_CurrentOperation, e.Progress);
            }
        }
        void OnBridgeExceptionTriggered(object sender, GarminFitnessCommunicatorBridge.ExceptionEventArgs e)
        {
            DeviceOperations lastOperation = m_CurrentOperation;

            m_CancellationError = e.ExceptionText;
            m_CurrentOperation = DeviceOperations.Idle;

            Logger.Instance.LogText(String.Format("Bridge exception caught in device : {0}\nStack:{1}", m_CancellationError, new StackTrace(true).ToString()));

            switch (lastOperation)
            {
                case DeviceOperations.ReadProfile:
                case DeviceOperations.ReadWorkout:
                {
                    if (ReadFromDeviceCompleted != null)
                    {
                        ReadFromDeviceCompleted(this, lastOperation, false, m_CancellationError);
                    }
                    break;
                }
                case DeviceOperations.WriteProfile:
                case DeviceOperations.WriteWorkout:
                {
                    if (WriteToDeviceCompleted != null)
                    {
                        WriteToDeviceCompleted(this, lastOperation, false, m_CancellationError);
                    }
                    break;
                }
            }
        }