/// <summary>
        /// Constructor.
        /// </summary>
        public Processor()
        {
            this.ftp = new Ftp();
            this.connections = new Connections();

            last_updated = DateTime.Now;
            data_extension = ".data";
            time_extension = ".time";
            screenshot_extension = ".png";
            upload_extension = ".upload";
            image_cache_directory = "image_processing";
            retina_marker = "@2x";
        }
        /// <summary>
        /// Main program loop.
        /// </summary>
        public void run()
        {
            // Pace reconnections (minutes)
            int observation_delay = Properties.Settings.Default.ObservationDelay * 60;

            while (true)
            {
                try
                {
                    // Reload connections if anything has changed
                    if (Connections.Changed)
                    {
                        connections = connections.read();
                    }

                    foreach (Connection connection in connections)
                    {
                        if(connection.IsValid)
                        {
                            // Load connection context into the ftp object
                            ftp.Connection(connection);

                            // Collect data ready for processing
                            Items items_to_update = dataCollection();

                            // Capture screenshots and upload to server 
                            captureAndUpload(items_to_update);

                            // If uploads were successful, move into place. Otherwise revert.
                            validateAndFinalize();
                        }
                    }
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e.ToString());
                }
                Trace.WriteLine("Cycle done");
                Thread.Sleep(observation_delay * 1000);
            }
        }
        /// <summary>
        /// Shown event. Fires when the UI appears.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event arguments.</param>
        private void configuration_Shown(Object sender, EventArgs e)
        {
            // Read connections from disk
            connections = connections.read();

            // Bind connections to the interface
            listBox_installations.DataSource = connections.Conns;
            listBox_installations.DisplayMember = "Name";
            listBox_installations.ValueMember = "Name";
            listBox_installations.DataBindings.Add("Text", connections.Conns, "Name");

            // No connections? Freeze the interface.
            if (connections.Conns.Count == 0)
            {
                clearServerGroup();
                disableServerGroup();
            }

            // Read in saved expiry value
            comboBox_expiry.SelectedValue = Properties.Settings.Default.Expiry;
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        public Configuration()
        {
            InitializeComponent();

            // Connections object
            connections = new Connections();

            // Screenshot expiry data
            delay_list = new List<Hour>();
            delay_list.Add(new Hour(1));
            delay_list.Add(new Hour(6));
            delay_list.Add(new Hour(12));
            delay_list.Add(new Hour(24));

            // Screenshot expiry binding
            comboBox_expiry.DataSource = delay_list;
            comboBox_expiry.DisplayMember = "Name";
            comboBox_expiry.ValueMember = "Value";

            // Bind events
            events();
        }
 /// <summary>
 /// Read the connection pool from disk.
 /// </summary>
 /// <returns>Connections.</returns>
 public Connections read()
 {
     Connections connections = new Connections();
     try
     {
         using (Stream stream = new FileStream("Connections.bin", FileMode.Open, FileAccess.Read, FileShare.Read))
         {
             IFormatter formatter = new BinaryFormatter();
             connections = (Connections)formatter.Deserialize(stream);
             stream.Close();
         }
     }
     catch (Exception e)
     {
         Debug.WriteLine(e.ToString());
     }
     Connections.Changed = false;
     return connections;
 }