public void FixSynchronizationMode (TestResult result)
    {
      const SynchronizationMode readOnlyDefaultMode = SynchronizationMode.ReplicateServerIntoOutlook;
      if (result.ResourceType.HasFlag (ResourceType.Calendar))
      {
        if (!result.AccessPrivileges.HasFlag (AccessPrivileges.Modify)
            && OptionTasks.DoesModeRequireWriteableServerResource(_syncSettingsControl.SynchronizationMode))
        {
          _syncSettingsControl.SynchronizationMode = readOnlyDefaultMode;
          MessageBox.Show (
              string.Format (
                  "The specified Url is a read-only calendar. Synchronization mode set to '{0}'.",
                  _syncSettingsControl.AvailableSynchronizationModes.Single (m => m.Value == readOnlyDefaultMode).Name),
              OptionTasks.ConnectionTestCaption);
        }
      }

      if (result.ResourceType.HasFlag (ResourceType.AddressBook))
      {
        if (!result.AccessPrivileges.HasFlag (AccessPrivileges.Modify)
            && OptionTasks.DoesModeRequireWriteableServerResource(_syncSettingsControl.SynchronizationMode))
        {
          _syncSettingsControl.SynchronizationMode = readOnlyDefaultMode;
          MessageBox.Show (
              string.Format (
                  "The specified Url is a read-only addressbook. Synchronization mode set to '{0}'.",
                  _syncSettingsControl.AvailableSynchronizationModes.Single (m => m.Value == readOnlyDefaultMode).Name),
              OptionTasks.ConnectionTestCaption);
        }
      }
    }
      public void FixSynchronizationMode (TestResult result)
      {
        const SynchronizationMode readOnlyDefaultMode = SynchronizationMode.ReplicateServerIntoOutlook;
        if (result.ResourceType.HasFlag (ResourceType.Calendar))
        {
          if (!result.CalendarProperties.HasFlag (CalendarProperties.IsWriteable)
              && _.SelectedModeRequiresWriteableServerResource)
          {
            _._synchronizationModeComboBox.SelectedValue = readOnlyDefaultMode;
            MessageBox.Show (
                string.Format (
                    "The specified Url is a read-only calendar. Synchronization mode set to '{0}'.",
                    _._availableSynchronizationModes.Single (m => m.Value == readOnlyDefaultMode).Name),
                c_connectionTestCaption);
          }
        }

        if (result.ResourceType.HasFlag (ResourceType.AddressBook))
        {
          if (!result.AddressBookProperties.HasFlag (AddressBookProperties.IsWriteable)
              && _.SelectedModeRequiresWriteableServerResource)
          {
            _._synchronizationModeComboBox.SelectedValue = readOnlyDefaultMode;
            MessageBox.Show (
                string.Format (
                    "The specified Url is a read-only addressbook. Synchronization mode set to '{0}'.",
                    _._availableSynchronizationModes.Single (m => m.Value == readOnlyDefaultMode).Name),
                c_connectionTestCaption);
          }
        }
      }
    public static async Task<TestResult> TestConnection (Uri url, IWebDavClient webDavClient, ResourceType supposedRessourceType)
    {
      var calDavDataAccess = new CalDavDataAccess (url, webDavClient);
      var cardDavDataAccess = new CardDavDataAccess (url, webDavClient);

      TestResult result;


      switch (supposedRessourceType)
      {
        case ResourceType.None:
          var ressourceType =
              (await calDavDataAccess.IsResourceCalender() ? ResourceType.Calendar : ResourceType.None) |
              (await cardDavDataAccess.IsResourceAddressBook() ? ResourceType.AddressBook : ResourceType.None);

          result = new TestResult (
              ressourceType,
              ressourceType.HasFlag (ResourceType.Calendar) ? await GetCalendarProperties (calDavDataAccess) : CalendarProperties.None,
              ressourceType.HasFlag (ResourceType.AddressBook) ? await GetAddressBookProperties (cardDavDataAccess) : AddressBookProperties.None);
              break;

        case ResourceType.Calendar:
          result = new TestResult (
              supposedRessourceType,
              CalendarProperties.CalendarAccessSupported |
              (await calDavDataAccess.IsWriteable() ? CalendarProperties.IsWriteable : CalendarProperties.None) |
              (await calDavDataAccess.DoesSupportCalendarQuery() ? CalendarProperties.SupportsCalendarQuery : CalendarProperties.None),
              AddressBookProperties.None);
          break;
        
        case ResourceType.AddressBook:
          result = new TestResult (
              supposedRessourceType,
              CalendarProperties.None,
              AddressBookProperties.AddressBookAccessSupported |
              (await cardDavDataAccess.IsWriteable() ? AddressBookProperties.IsWriteable : AddressBookProperties.None));
          break;
        
        default:
          throw new ArgumentOutOfRangeException ("supposedRessourceType");
      }

      return result;
    }
    public static async Task<TestResult> TestConnection (Uri url, IWebDavClient webDavClient, ResourceType autoRessourceType)
    {
      var calDavDataAccess = new CalDavDataAccess (url, webDavClient);
      var cardDavDataAccess = new CardDavDataAccess (url, webDavClient);

      TestResult result;

      if (autoRessourceType == ResourceType.None)
      {
        var ressourceType =
          (await calDavDataAccess.IsResourceCalender() ? ResourceType.Calendar : ResourceType.None) |
          (await cardDavDataAccess.IsResourceAddressBook() ? ResourceType.AddressBook : ResourceType.None);

        result = new TestResult(
          ressourceType,
          ressourceType.HasFlag(ResourceType.Calendar) ? await GetCalendarProperties(calDavDataAccess) : CalendarProperties.None,
          ressourceType.HasFlag(ResourceType.AddressBook) ? await GetAddressBookProperties(cardDavDataAccess) : AddressBookProperties.None);
      }
      else if (autoRessourceType == ResourceType.Calendar)
      {
        result = new TestResult(
          autoRessourceType,
          CalendarProperties.CalendarAccessSupported |
          (await calDavDataAccess.IsWriteable() ? CalendarProperties.IsWriteable : CalendarProperties.None) |
          (await calDavDataAccess.DoesSupportCalendarQuery() ? CalendarProperties.SupportsCalendarQuery : CalendarProperties.None),
          AddressBookProperties.None);
      }
      else
      {
        result = new TestResult(
          autoRessourceType,
          CalendarProperties.None,
          AddressBookProperties.AddressBookAccessSupported |
          (await cardDavDataAccess.IsWriteable() ? AddressBookProperties.IsWriteable : AddressBookProperties.None));
      }

      return result;
    }
 public void FixSynchronizationMode (TestResult result)
 {
 }
 public void FixSynchronizationMode (TestResult result)
   {
     _syncSettingsControl.FixSynchronizationMode (result);
   }
    private void DisplayTestReport (TestResult result)
    {
      bool hasError = false;
      var errorMessageBuilder = new StringBuilder();

      var isCalendar = result.ResourceType.HasFlag (ResourceType.Calendar);
      var isAddressBook = result.ResourceType.HasFlag (ResourceType.AddressBook);

      if (!isCalendar && !isAddressBook)
      {
        errorMessageBuilder.AppendLine ("- The specified Url is neither a calendar nor an addressbook!");
        hasError = true;
      }

      if (isCalendar && isAddressBook)
      {
        errorMessageBuilder.AppendLine ("- Ressources which are a calendar and an addressbook are not valid!");
        hasError = true;
      }

      if (isCalendar)
      {
        if (!result.CalendarProperties.HasFlag (CalendarProperties.CalendarAccessSupported))
        {
          errorMessageBuilder.AppendLine ("- The specified Url does not support calendar access.");
          hasError = true;
        }

        if (!result.CalendarProperties.HasFlag (CalendarProperties.SupportsCalendarQuery))
        {
          errorMessageBuilder.AppendLine ("- The specified Url does not support calendar queries. Some features like time range filter may not work!");
          hasError = true;
        }

        if (!result.CalendarProperties.HasFlag (CalendarProperties.IsWriteable))
        {
          var synchronizationMode = (SynchronizationMode) _synchronizationModeComboBox.SelectedValue;
          if (RequiresWriteableServerResource (synchronizationMode))
          {
            errorMessageBuilder.AppendFormat (
                "- The specified calendar is not writeable. Therefore it is not possible to use the synchronization mode '{0}'.",
                _availableSynchronizationModes.Single (m => m.Value == synchronizationMode).Name);
            errorMessageBuilder.AppendLine();
            hasError = true;
          }
        }

        if (_folderType != OlItemType.olAppointmentItem && _folderType != OlItemType.olTaskItem)
        {
          errorMessageBuilder.AppendLine ("- The outlook folder is not a calendar or task folder, or there is no folder selected.");
          hasError = true;
        }
      }

      if (isAddressBook)
      {
        if (!result.AddressBookProperties.HasFlag (AddressBookProperties.AddressBookAccessSupported))
        {
          errorMessageBuilder.AppendLine ("- The specified Url does not support address books.");
          hasError = true;
        }

        if (!result.AddressBookProperties.HasFlag (AddressBookProperties.IsWriteable))
        {
          var synchronizationMode = (SynchronizationMode) _synchronizationModeComboBox.SelectedValue;
          if (RequiresWriteableServerResource (synchronizationMode))
          {
            errorMessageBuilder.AppendFormat (
                "- The specified address book is not writeable. Therefore it is not possible to use the synchronization mode '{0}'.",
                _availableSynchronizationModes.Single (m => m.Value == synchronizationMode).Name);
            errorMessageBuilder.AppendLine();
            hasError = true;
          }
        }

        if (_folderType != OlItemType.olContactItem)
        {
          errorMessageBuilder.AppendLine ("- The outlook folder is not an address book, or there is no folder selected.");
          hasError = true;
        }
      }

      if (hasError)
        MessageBox.Show ("Connection test NOT successful:" + Environment.NewLine + errorMessageBuilder, c_connectionTestCaption);
      else
        MessageBox.Show ("Connection test successful.", c_connectionTestCaption);
    }
    public static void DisplayTestReport (
        TestResult result,
        bool selectedSynchronizationModeRequiresWriteableServerResource,
        string selectedSynchronizationModeDisplayName,
        OlItemType? outlookFolderType,
        ServerAdapterType serverAdapterType)
    {
      bool hasError = false;
      bool hasWarning = false;
      var errorMessageBuilder = new StringBuilder ();

      var isCalendar = result.ResourceType.HasFlag (ResourceType.Calendar);
      var isAddressBook = result.ResourceType.HasFlag (ResourceType.AddressBook);
      var isGoogleTask = result.ResourceType.HasFlag (ResourceType.TaskList);

      if (isGoogleTask)
      {
        if (outlookFolderType != OlItemType.olTaskItem)
        {
          errorMessageBuilder.AppendLine ("- The outlook folder is not a task folder, or there is no folder selected.");
          hasError = true;
        }
      }
      else if (!isCalendar && !isAddressBook)
      {
        errorMessageBuilder.AppendLine ("- The specified Url is neither a calendar nor an addressbook!");
        hasError = true;
      }

      if (isCalendar && isAddressBook)
      {
        errorMessageBuilder.AppendLine ("- Ressources which are a calendar and an addressbook are not valid!");
        hasError = true;
      }

      if (isCalendar)
      {
        if (!result.CalendarProperties.HasFlag (CalendarProperties.CalendarAccessSupported))
        {
          errorMessageBuilder.AppendLine ("- The specified Url does not support calendar access.");
          hasError = true;
        }

        if (!result.CalendarProperties.HasFlag (CalendarProperties.SupportsCalendarQuery))
        {
          errorMessageBuilder.AppendLine ("- The specified Url does not support calendar queries. Some features like time range filter may not work!");
          hasWarning = true;
        }

        if (!result.CalendarProperties.HasFlag (CalendarProperties.IsWriteable))
        {
          if (selectedSynchronizationModeRequiresWriteableServerResource)
          {
            errorMessageBuilder.AppendFormat (
                "- The specified calendar is not writeable. Therefore it is not possible to use the synchronization mode '{0}'.",
                selectedSynchronizationModeDisplayName);
            errorMessageBuilder.AppendLine ();
            hasError = true;
          }
        }

        if (serverAdapterType == ServerAdapterType.WebDavHttpClientBasedWithGoogleOAuth)
        {
          if (outlookFolderType != OlItemType.olAppointmentItem)
          {
            errorMessageBuilder.AppendLine ("- The outlook folder is not a calendar folder, or there is no folder selected.");
            hasError = true;
          }
        }
        else if (outlookFolderType != OlItemType.olAppointmentItem && outlookFolderType != OlItemType.olTaskItem)
        {
          errorMessageBuilder.AppendLine ("- The outlook folder is not a calendar or task folder, or there is no folder selected.");
          hasError = true;
        }
      }

      if (isAddressBook)
      {
        if (!result.AddressBookProperties.HasFlag (AddressBookProperties.AddressBookAccessSupported))
        {
          errorMessageBuilder.AppendLine ("- The specified Url does not support address books.");
          hasError = true;
        }

        if (!result.AddressBookProperties.HasFlag (AddressBookProperties.IsWriteable))
        {
          if (selectedSynchronizationModeRequiresWriteableServerResource)
          {
            errorMessageBuilder.AppendFormat (
                "- The specified address book is not writeable. Therefore it is not possible to use the synchronization mode '{0}'.",
                selectedSynchronizationModeDisplayName);
            errorMessageBuilder.AppendLine ();
            hasError = true;
          }
        }

        if (outlookFolderType != OlItemType.olContactItem)
        {
          errorMessageBuilder.AppendLine ("- The outlook folder is not an address book, or there is no folder selected.");
          hasError = true;
        }
      }

      if (hasError)
        MessageBox.Show ("Connection test NOT successful:" + Environment.NewLine + errorMessageBuilder, OptionTasks.ConnectionTestCaption);
      else if (hasWarning)
        MessageBox.Show ("Connection test successful BUT:" + Environment.NewLine + errorMessageBuilder, OptionTasks.ConnectionTestCaption, MessageBoxButtons.OK, MessageBoxIcon.Warning);
      else
        MessageBox.Show ("Connection test successful.", OptionTasks.ConnectionTestCaption);
    }
    private async Task TestGoogleConnection ()
    {
      StringBuilder errorMessageBuilder = new StringBuilder ();

      if (!OptionTasks.ValidateGoogleEmailAddress (errorMessageBuilder, _emailAddressTextBox.Text)) 
      {
        MessageBox.Show (errorMessageBuilder.ToString(), "The Email Address is invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
      }
      if (UsedServerAdapterType == ServerAdapterType.GoogleTaskApi &&
          !string.IsNullOrWhiteSpace (_calenderUrlTextBox.Text) &&
          _calenderUrlTextBox.Text != c_googleDavBaseUrl)
      {
        var service = await OAuth.Google.GoogleHttpClientFactory.LoginToGoogleTasksService (_emailAddressTextBox.Text);

        try
        {
          TaskList task = await service.Tasklists.Get (_calenderUrlTextBox.Text).ExecuteAsync();
        }
        catch (Exception)
        {
          errorMessageBuilder.AppendFormat ("The tasklist with id '{0}' is invalid.", _calenderUrlTextBox.Text);
          MessageBox.Show(errorMessageBuilder.ToString(), "The tasklist is invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
          return;
        }
        TestResult result = new TestResult (ResourceType.TaskList, CalendarProperties.None, AddressBookProperties.None);

        OptionTasks.DisplayTestReport (result, false, _dependencies.SelectedSynchronizationModeDisplayName, _dependencies.OutlookFolderType, UsedServerAdapterType);
        return;
      }

      if (!OptionTasks.ValidateWebDavUrl (_calenderUrlTextBox.Text, errorMessageBuilder, false))
      {
        MessageBox.Show (errorMessageBuilder.ToString(), "The CalDav/CardDav Url is invalid", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
      }

      var enteredUri = new Uri (_calenderUrlTextBox.Text);
      var webDavClient = CreateWebDavClient ();

      Uri autoDiscoveredUrl;
      ResourceType autoDiscoveredResourceType;

      if (ConnectionTester.RequiresAutoDiscovery (enteredUri))
      {
        var calDavDataAccess = new CalDavDataAccess(enteredUri, webDavClient);
        IReadOnlyList<Tuple<Uri, string, string>> foundCaldendars = await calDavDataAccess.GetUserCalendarsNoThrow(false);

        var cardDavDataAccess = new CardDavDataAccess(enteredUri, webDavClient);
        IReadOnlyList<Tuple<Uri, string>> foundAddressBooks = await cardDavDataAccess.GetUserAddressBooksNoThrow(true);

        var service = await OAuth.Google.GoogleHttpClientFactory.LoginToGoogleTasksService(_emailAddressTextBox.Text);

        TaskLists taskLists = await service.Tasklists.List().ExecuteAsync();

        if (foundCaldendars.Count > 0 || foundAddressBooks.Count > 0 || taskLists.Items.Any())
        {
          ResourceType initalResourceType;
          if (_dependencies.OutlookFolderType == OlItemType.olContactItem)
          {
            initalResourceType = ResourceType.AddressBook;
          }
          else if (_dependencies.OutlookFolderType == OlItemType.olTaskItem)
          {
            initalResourceType = ResourceType.TaskList;
          }
          else
          {
            initalResourceType = ResourceType.Calendar;
          }

          using (SelectResourceForm listCalendarsForm =
              new SelectResourceForm(
                  foundCaldendars,
                  foundAddressBooks,
                  taskLists.Items.Select(i => Tuple.Create(i.Id, i.Title)).ToArray(),
                  initalResourceType))
          {
            if (listCalendarsForm.ShowDialog() == DialogResult.OK)
            {
              if (listCalendarsForm.ResourceType == ResourceType.TaskList)
              {
                autoDiscoveredUrl = null;
                _calenderUrlTextBox.Text = listCalendarsForm.SelectedUrl;
                UsedServerAdapterType = ServerAdapterType.GoogleTaskApi;
              }
              else
              {
                autoDiscoveredUrl = new Uri(enteredUri.GetLeftPart(UriPartial.Authority) + listCalendarsForm.SelectedUrl);
                UsedServerAdapterType = ServerAdapterType.WebDavHttpClientBasedWithGoogleOAuth;
              }
              autoDiscoveredResourceType = listCalendarsForm.ResourceType;
            }
            else
            {
              autoDiscoveredUrl = null;
              autoDiscoveredResourceType = ResourceType.None;
            }
          }
        }
        else
        {
          MessageBox.Show("No resources were found via autodiscovery!", OptionTasks.ConnectionTestCaption);
          autoDiscoveredUrl = null;
          autoDiscoveredResourceType = ResourceType.None;
        }
      }
      else
      {
        var result = await ConnectionTester.TestConnection (enteredUri, webDavClient, ResourceType.None);
        if (result.ResourceType != ResourceType.None)
        {
          _settingsFaultFinder.FixSynchronizationMode (result);
        }
        OptionTasks.DisplayTestReport (
            result,
            _dependencies.SelectedSynchronizationModeRequiresWriteableServerResource,
            _dependencies.SelectedSynchronizationModeDisplayName,
            _dependencies.OutlookFolderType,
            UsedServerAdapterType);
        return;
      }

      if (autoDiscoveredUrl != null)
      {
        _calenderUrlTextBox.Text = autoDiscoveredUrl.ToString();
        var finalResult =
          await ConnectionTester.TestConnection(autoDiscoveredUrl, webDavClient, autoDiscoveredResourceType);
        _settingsFaultFinder.FixSynchronizationMode(finalResult);

        OptionTasks.DisplayTestReport(
          finalResult,
          _dependencies.SelectedSynchronizationModeRequiresWriteableServerResource,
          _dependencies.SelectedSynchronizationModeDisplayName,
          _dependencies.OutlookFolderType,
          UsedServerAdapterType);
      }
      else if (UsedServerAdapterType == ServerAdapterType.GoogleTaskApi)
      {
        TestResult result = new TestResult(ResourceType.TaskList, CalendarProperties.None, AddressBookProperties.None);

        OptionTasks.DisplayTestReport (result,false,_dependencies.SelectedSynchronizationModeDisplayName, _dependencies.OutlookFolderType, UsedServerAdapterType);
      }
    }