/// <summary>
        /// Output error to console as well as log file
        /// </summary>
        /// <param name="s">String to output</param>
        /// <param name="e">Exception to output</param>
        public static void Output(string s, Exception e)
        {
            s = "\n" + s + ": \n" + e.ToString() + "\n\n";

            try
            {
                // write to log
                ArbiterOutput.WriteToLog(DateTime.Now.ToString() + ": " + s);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error writing to log: \n" + ex.ToString());
            }

            // write to console
            Console.WriteLine(s);

            try
            {
                if (CoreCommon.Communications != null)
                {
                    // output
                    CoreCommon.Communications.SendOutput(s);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error outputting to arbiter message channel: \n" + ex.ToString());
            }
        }
        /// <summary>
        /// Operational competes a behavior
        /// </summary>
        /// <param name="report"></param>
        public override void OnCompletionReport(CompletionReport report)
        {
            try
            {
                if (report.Result == CompletionResult.Success)
                {
                    ArbiterOutput.OutputNoLog("Received Completion Report: " + report.BehaviorType.ToString() + ", Result: " + report.Result.ToString());
                }
                else if (this.ArbiterBlockageHandler != null && report is TrajectoryBlockedReport)
                {
                    this.ArbiterBlockageHandler.OnBlockageReport((TrajectoryBlockedReport)report);
                }

                lock (this.recentReports)
                {
                    this.recentReports = new List <KeyValuePair <CompletionReport, DateTime> >(this.recentReports.ToArray());
                    this.recentReports.Add(new KeyValuePair <CompletionReport, DateTime>(report, DateTime.Now));
                }
            }
            catch (Exception e)
            {
                try
                {
                    ArbiterOutput.OutputNoLog("Error in completion report");
                    ArbiterOutput.WriteToLog(e.ToString());
                }
                catch (Exception)
                {
                }
            }
        }
        public void UpdateInformation(ArbiterInformation arbiterInformation)
        {
            if (arbiterInformation != null)
            {
                //Stopwatch stopwatch3 = new Stopwatch();

                //stopwatch3.Reset();
                //stopwatch3.Start();
                ArbiterOutput.WriteToLog(arbiterInformation.LogString());
                //stopwatch3.Stop();
                //Console.WriteLine("SW 3: " + stopwatch3.ElapsedMilliseconds.ToString());

                //stopwatch3.Reset();
                //stopwatch3.Start();
                this.currentInformation = arbiterInformation;
                //stopwatch3.Stop();
                //Console.WriteLine("SW 4: " + stopwatch3.ElapsedMilliseconds.ToString());
            }
        }
        /// <summary>
        /// Shuts down the communicator and unsubscribes from channels, whatnot
        /// </summary>
        public void Shutdown()
        {
            try
            {
                if (vehicleStateChannel != null)
                {
                    // unsubscribe from channels
                    vehicleStateChannel.Unsubscribe(vehicleStateChannelToken);
                    observedObstacleChannel.Unsubscribe(observedObstacleChannelToken);
                    observedVehicleChannel.Unsubscribe(observedVehicleChannelToken);
                    vehicleSpeedChannel.Unsubscribe(vehicleSpeedChannelToken);
                    sideObstacleChannel.Unsubscribe(sideObstacleChannelToken);
                }

                // notify
                ArbiterOutput.Output("Unsubscribed from channels");
            }
            catch (Exception e)
            {
                // notify
                ArbiterOutput.Output("Error in shutting down registered channels");
                ArbiterOutput.WriteToLog(e.ToString());
            }
        }
        /// <summary>
        /// Keeps watch over communications components and determines if any need to be restarted
        /// </summary>
        public void Watchdog()
        {
            // always loop
            while (true)
            {
                try
                {
                    if (Arbiter.Core.ArbiterSettings.Default.IgnoreVehicles)
                    {
                        ArbiterOutput.Output("Ignoring Tracked Clusters");
                    }

                    #region Update Completion reports with 3 Sec Timeout

                    lock (this.recentReports)
                    {
                        List <KeyValuePair <CompletionReport, DateTime> > crs = new List <KeyValuePair <CompletionReport, DateTime> >();
                        foreach (KeyValuePair <CompletionReport, DateTime> cr in this.recentReports)
                        {
                            TimeSpan diff = DateTime.Now.Subtract(cr.Value);
                            ArbiterOutput.WriteToLog("Comm line 263 test diff.ToString: " + diff.ToString());

                            if (diff.Seconds < 2 && cr.Value.Date.Equals(DateTime.Now.Date))
                            {
                                crs.Add(cr);
                            }
                            else
                            {
                                ArbiterOutput.WriteToLog("Removed Completion Report: " + cr.Key.BehaviorType.ToString() + ", " + cr.Key.Result.ToString());
                            }
                        }
                        this.recentReports = crs;
                    }

                    #endregion

                    #region Check for communications readiness

                    if (!this.CommunicationsReady)
                    {
                        try
                        {
                            // configure
                            this.Configure();
                        }
                        catch (Exception e)
                        {
                            // notify
                            ArbiterOutput.Output("Error in communications watchdog, configuration");
                            ArbiterOutput.WriteToLog(e.ToString());
                        }
                    }

                    if (!this.CommunicationsReady)
                    {
                        try
                        {
                            // make sure nothing else registered
                            this.Shutdown();

                            // register services
                            this.Register();
                        }
                        catch (Exception e)
                        {
                            // notify
                            ArbiterOutput.Output("Error in communications watchdog, registration");
                            ArbiterOutput.WriteToLog(e.ToString());
                        }
                    }

                    #endregion

                    #region Get Car Mode (Acts as Operational Ping and know then Comms Ready)

                    try
                    {
                        if (this.operationalFacade != null)
                        {
                            // update the car mode
                            this.carMode = this.operationalFacade.GetCarMode();

                            // set comms ready as true given success
                            if (!this.CommunicationsReady)
                            {
                                this.CommunicationsReady = true;
                            }
                        }
                        else
                        {
                            this.CommunicationsReady = false;
                        }
                    }
                    catch (Exception e)
                    {
                        // notify
                        ArbiterOutput.Output("Error retreiving car mode from operational in watchdog, attempting to reconnect");

                        // log
                        ArbiterOutput.WriteToLog(e.ToString());

                        // set comms ready as false
                        this.CommunicationsReady = false;
                    }

                    #endregion
                }
                catch (Exception e)
                {
                    ArbiterOutput.Output("Error in communications watchdog", e);
                }

                // wait for cycle time
                Thread.Sleep(1000);
            }
        }