}//end frmMain_Resize()

        /// <summary>
        /// Thread to fetch records, nothing else
        /// </summary>
        private void threadFetchOnly()
        {
            try
            {
                Program.cloudFlareAPI.getExternalAddress();
                this.Invoke(new updateAddressInvoker(updateAddress), Program.settingsManager.getSetting("ExternalAddressIPV4").ToString(), Program.settingsManager.getSetting("ExternalAddressIPV6").ToString());
                if (!string.IsNullOrEmpty(Program.settingsManager.getSetting("SelectedZones").ToString()))
                {
                    List<Result> resultList = new List<Result>();
                    foreach (string SelectedZones in Program.settingsManager.getSetting("SelectedZones").ToString().Split(';'))
                    {

                        GetDnsRecordsResponse records = Program.cloudFlareAPI.getCloudFlareRecords(SelectedZones);
                        records.result.All(x => { resultList.Add(x); return true; });
                    }
                    if (resultList != null)
                    {
                        this.Invoke(new updateHostsListInvoker(updateHostsList), resultList);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.log(ex.Message);
            }
        }//end threadFetchOnly()
        }//end threadFetchOnly()

        /// <summary>
        /// Thread to run updates every x minutes
        /// </summary>
        private void threadFetchUpdate()
        {
            Program.cloudFlareAPI.getExternalAddress();
            this.Invoke(new updateAddressInvoker(updateAddress), Program.settingsManager.getSetting("ExternalAddressIPV4").ToString(), Program.settingsManager.getSetting("ExternalAddressIPV6").ToString());
            if (!string.IsNullOrEmpty(Program.settingsManager.getSetting("SelectedZones").ToString()))
            {
                foreach (string SelectedZones in Program.settingsManager.getSetting("SelectedZones").ToString().Split(';'))
                {
                    GetDnsRecordsResponse records = Program.cloudFlareAPI.getCloudFlareRecords(SelectedZones);
                    if (records != null)
                    {
                        this.Invoke(new updateHostsListInvoker(updateHostsList), records);
                        List<Result> Ldns = Program.cloudFlareAPI.updateRecords(listViewRecords,records);
                    }
                }
                start_fetchThread();
            }
        }//end timerUpdateThread()
        }//end OnContinue()

        /// <summary>
        /// Auto update every x minutes, creates a new timerUpdateThread() thread
        /// NOTE: This already runs in its own thread!
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void autoUpdateTimer_Tick(object sender, EventArgs e)
        {
            Program.settingsManager.loadSettings(); //Do this to reload the config, GUI might have changed settings since last tick
            autoUpdateTimer.Interval = (Program.settingsManager.getSetting("FetchTime").ToInt() * 60000); //Minutes to milliseconds
            Program.cloudFlareAPI.getExternalAddress();
            if (!string.IsNullOrEmpty(Program.settingsManager.getSetting("SelectedZones").ToString()))
            {
                List<Result> resultList = new List<Result>();
                foreach (string SelectedZones in Program.settingsManager.getSetting("SelectedZones").ToString().Split(';'))
                {

                    GetDnsRecordsResponse records = Program.cloudFlareAPI.getCloudFlareRecords(SelectedZones);
                    records.result.All(x => { resultList.Add(x); return true; });
                }
                if (resultList != null)
                {
                    Program.cloudFlareAPI.updateRecords(null, resultList);
                }
            }
        }//end autoUpdateTimer_Tick()
        /// <summary>
        /// Called from another thread
        /// Populate the list hosts control with the new returned hosts
        /// </summary>
        /// <param name="fetchedRecords"></param>
        private void updateHostsList(GetDnsRecordsResponse fetchedRecords)
        {
                if (fetchedRecords == null)
                {
                    Debug.WriteLine("fetchrecords failed");
                    return; //bail if the fetch failed
                }
                string[] selectedHosts = Program.settingsManager.getSetting("SelectedHosts").ToString().Split(';');

                if (listViewRecords.Items.Count != selectedHosts.Length)
                {
                    if (listViewRecords.Items.Count != 0)
                    {
                        //listViewRecords.Clear(); -- Cant use Clear() it crashes the ListView i dont know why
                        foreach (ListViewItem item in listViewRecords.Items)
                        {
                            bool id_exist = false;
                            foreach (Result r in fetchedRecords.result)
                            {
                                if ((item.Tag as Result).id == r.id)
                                {
                                    id_exist = true;
                                    break;
                                }
                            }
                            if (!id_exist)
                                item.Remove();
                        }
                    }
                }

                foreach (Result r in fetchedRecords.result)
                {
                    bool exist = false;
                    ListViewItem listViewItem = null;
                    ListView.ListViewItemCollection items = null;
                    this.Invoke((MethodInvoker)delegate
                    {
                        items = listViewRecords.Items;
                    });
                    foreach (ListViewItem lvItem in items)
                    {
                        if ((lvItem.Tag as Result).id == r.id)
                        {
                            exist = true;
                            listViewItem = lvItem;
                            break;
                        }
                    }
                    if (exist)
                    {
                        this.Invoke((MethodInvoker)delegate
                        {
                            listViewItem.SubItems[1].Text = r.type.ToString();
                            listViewItem.SubItems[2].Text = r.name;
                            listViewItem.SubItems[3].Text = r.content;
                            listViewItem.SubItems[4].Text = r.modified_on.ToShortDateString() + " " + r.modified_on.ToShortTimeString();
                        });
                        continue;
                    }
                    ListViewItem row = new ListViewItem();
                    row.SubItems.Add(r.type);
                    row.SubItems.Add(r.name);
                    row.SubItems.Add(r.content);
                    row.SubItems.Add(r.modified_on.ToShortDateString() + " " + r.modified_on.ToShortTimeString());
                    row.Tag = r;
                    //Only check this if it's an A record. MX records may have the same name as the primary A record, but should never be updated with an IP.
                    bool NeedIp = false;
                    switch (r.type)
                    {
                        case "A":
                        case "AAAA":
                            NeedIp = true;
                            break;
                    }
                    if (NeedIp)
                    {
                        int pos = Array.IndexOf(selectedHosts, (row.Tag as Result).id);
                        if (pos > -1)
                        {
                            row.Checked = true;
                        }
                    }
                    try
                    {
                        if (string.IsNullOrEmpty(Program.settingsManager.getSetting("HideSRV").ToString()))
                        {
                            if (Program.settingsManager.getSetting("HideSRV").ToBool())
                            {
                                if (r.type != "SRV")
                                {
                                    listViewRecords.Items.Add(row);
                                    continue;
                                }
                            }
                        }
                        listViewRecords.Items.Add(row);
                        continue;
                    }
                    catch (Exception e)
                    {
                        Debug.WriteLine(e);
                        listViewRecords.Items.Add(row);
                    }
                }

                //Grey out anything that isn't an A record.
                for (int j = 0; j < listViewRecords.Items.Count; j++)
                {
                    bool NeedIp = false;
                    switch (listViewRecords.Items[j].SubItems[1].Text)
                    {
                        case "A":
                        case "AAAA":
                            NeedIp = true;
                            break;
                    }
                    if (NeedIp == false)
                    {
                        listViewRecords.Items[j].ForeColor = System.Drawing.Color.Gray;
                    }
                }
        }//end updateHostsList()
        /// <summary>
        /// Logic to update records
        /// And return changes
        /// </summary>
        public List<Result> updateRecords(ListView lv,GetDnsRecordsResponse fetchedRecords)
        {
            //List for the Updated IPs
            List<Result> return_updated_list = new List<Result>();

            if (fetchedRecords == null) //Dont attempt updates if the fetch failed
                return return_updated_list;

            int up_to_date = 0, skipped = 0, failed = 0, updated = 0, ignored = 0;
            string[] selectedHosts = Program.settingsManager.getSetting("SelectedHosts").ToString().Split(';');

            foreach (Result r in fetchedRecords.result)
            {
                //Skip over MX and CNAME records
                //TODO: Dont skip them :)
                switch (r.type)
                {
                    case "A":
                    case "AAAA":
                        break;
                    default:
                         skipped++;
                         continue;
                }

                //Ignore anything that is not checked
                if ((Array.IndexOf(selectedHosts, r.id) >= 0) != true)
                {
                    ignored++;
                    continue;
                }
                

                //Skip over anything that doesnt need an update
                if (r.content == Program.settingsManager.getSetting("ExternalAddressIPV4").ToString() || r.content == Program.settingsManager.getSetting("ExternalAddressIPV6").ToString())
                {
                    up_to_date++;
                    continue;
                }
                string strResponse = "";
                try
                {

                    if (lv != null)
                        UpdateLastChange(lv, r, Properties.Resources.Main_Change_IP);

                    strResponse = this.updateCloudflareRecords(r);

                    System.Threading.Thread.Sleep(1000); //DontNeedTooSpamCloudflareServer

                    if (lv != null)
                        UpdateLastChange(lv, r, DateTime.Now.ToShortDateString()+" "+ DateTime.Now.ToShortTimeString());
                }
                catch (Exception)
                {
                    if (lv != null)
                        UpdateLastChange(lv, r, Properties.Resources.Main_Change_IP_Failed);

                    Logger.log(Properties.Resources.Error_FailedRecordUpdate + r.name, Logger.Level.Error);
                }
            }

            Logger.log("Update at " + DateTime.Now + " - " + updated.ToString(Program.cultureInfo) + " updated, " + up_to_date.ToString(Program.cultureInfo) + " up to date, " + skipped.ToString(Program.cultureInfo) + " skipped, " + ignored.ToString(Program.cultureInfo) + " ignored, " + failed.ToString(Program.cultureInfo) + " failed", Logger.Level.Info);
            return return_updated_list;
        }//end updateRecords()