/// <summary>
        /// Gets the picture.
        /// </summary>
        /// <param name="request">The request.</param>
        /// <param name="contact">The contact.</param>
        /// <returns>The Picture stream.</returns>
        public static Stream GetPicture(this ContactsRequest request, Contact contact)
        {
            var stream = new MemoryStream();
            Stream retStream = null;

            try
            {
                if (contact.PhotoUri != null)
                {
                    retStream = request.Service.Query(contact.PhotoUri);
                }
            }
            catch (GDataRequestException ex)
            {
                var response = ex.Response as HttpWebResponse;
                if (response != null && response.StatusCode != HttpStatusCode.NotFound)
                {
                    throw;
                }
            }

            if (retStream != null)
            {
                retStream.CopyTo(stream);
            }

            return stream;
        }
        /// <summary>
        /// Syncs the outlook contact.
        /// </summary>
        /// <param name="outlookContact">The outlook contact.</param>
        /// <param name="googleContacts">The google contacts.</param>
        private void SyncOutlookContact(ContactItem outlookContact, IEnumerable<Contact> googleContacts)
        {
            var mergeables = googleContacts.Mergeable(outlookContact).ToList();

            // continue with next, if modificationdate is older then other side.
            if (ApplicationData.ContactBehavior == ContactBehavior.Automatic && mergeables.Any() &&
                outlookContact.LastModificationTime < mergeables.First().ContactEntry.Edited.DateValue)
                return;

            // Get or Create Contact and merge informations
            Contact googleContact;
            var googleGroups = Repository.GoogleData.GetGroups();
            if (mergeables.Any())
            {
                googleContact = mergeables.First();
                var changed = googleContact.MergeWith(outlookContact, googleGroups);
                if (changed)
                    this.Repository.GoogleData.ContactsRequest.Update(googleContact);
            }
            else
            {
                googleContact = new Contact();
                googleContact.MergeWith(outlookContact, googleGroups);
                this.Repository.GoogleData.ContactsRequest.Insert(ApplicationData.GoogleContactsUri, googleContact);
            }

            // Set GoogleId and Picture
            var outlookChanged = outlookContact.UserProperties.SetProperty("GoogleId", googleContact.Id);
            if (ApplicationData.ContactBehavior != ContactBehavior.GoogleOverOutlook && outlookContact.HasNewPicture())
            {
                try
                {
                    this.Repository.GoogleData.ContactsRequest.SetPhoto(googleContact, outlookContact.GetPicture(), "image/jpg");
                    googleContact = this.Repository.GoogleData.ContactsRequest.Retrieve(googleContact);
                    outlookChanged |= outlookContact.UserProperties.SetProperty("GooglePicture", googleContact.PhotoEtag);
                }
                catch (IOException ex)
                {
                    Debug.Write(ex.Message);
                    new EventLogPermission(EventLogPermissionAccess.Administer, ".").PermitOnly();
                    EventLog.WriteEntry("GoogleSync Addin", ex.ToString(), EventLogEntryType.Warning);
                }
                catch (UnauthorizedAccessException ex)
                {
                    Debug.Write(ex.Message);
                    new EventLogPermission(EventLogPermissionAccess.Administer, ".").PermitOnly();
                    EventLog.WriteEntry("GoogleSync Addin", ex.ToString(), EventLogEntryType.Warning);
                }
            }

            if (outlookChanged) outlookContact.Save();
        }
 /// <summary>
 /// Добавляет контакт в список
 /// </summary>
 public void AddContact(Contact contact)
 {
     this.ContactsList.Add(contact);
 }
        /// <summary>
        /// Merges the with.
        /// </summary>
        /// <param name="outlookContact">The outlook contact.</param>
        /// <param name="googleContact">The google contact.</param>
        /// <param name="outlookGroups">The outlook groups.</param>
        /// <returns>
        /// True if Changed.
        /// </returns>
        public static bool MergeWith(this ContactItem outlookContact, Contact googleContact, IEnumerable<Group> outlookGroups)
        {
            var result = false;

            result |= outlookContact.ApplyProperty(c => c.FullName, googleContact.Name.FullName);
            result |= outlookContact.ApplyProperty(c => c.FirstName, googleContact.Name.GivenName);
            result |= outlookContact.ApplyProperty(c => c.LastName, googleContact.Name.FamilyName);

            result |= outlookContact.ApplyProperty(c => c.Email1Address, googleContact.Emails.FirstOrInstance(e => e.Primary).Address);
            result |= outlookContact.ApplyProperty(c => c.Email2Address, googleContact.Emails.FirstOrInstance(e => !e.Primary).Address);
            result |= outlookContact.ApplyProperty(c => c.Email3Address, googleContact.Emails.FirstOrInstance(e => !e.Primary && e.Address != outlookContact.Email2Address).Address);

            result |= outlookContact.ApplyProperty(c => c.PrimaryTelephoneNumber, (googleContact.Phonenumbers.FirstOrDefault(p => p.Primary) ?? googleContact.Phonenumbers.FirstOrInstance()).Value.FormatPhone());
            result |= outlookContact.ApplyProperty(c => c.HomeTelephoneNumber, googleContact.Phonenumbers.FirstOrInstance(p => p.Rel == ContactsRelationships.IsHome).Value.FormatPhone());
            result |= outlookContact.ApplyProperty(c => c.HomeFaxNumber, googleContact.Phonenumbers.FirstOrInstance(p => p.Rel == ContactsRelationships.IsHomeFax).Value.FormatPhone());
            result |= outlookContact.ApplyProperty(c => c.BusinessTelephoneNumber, googleContact.Phonenumbers.FirstOrInstance(p => p.Rel == ContactsRelationships.IsWork).Value.FormatPhone());
            result |= outlookContact.ApplyProperty(c => c.BusinessFaxNumber, googleContact.Phonenumbers.FirstOrInstance(p => p.Rel == ContactsRelationships.IsWorkFax).Value.FormatPhone());
            result |= outlookContact.ApplyProperty(c => c.OtherFaxNumber, googleContact.Phonenumbers.FirstOrInstance(p => p.Rel == ContactsRelationships.IsOther).Value.FormatPhone());
            result |= outlookContact.ApplyProperty(c => c.OtherTelephoneNumber, googleContact.Phonenumbers.FirstOrInstance(p => p.Rel == ContactsRelationships.IsFax).Value.FormatPhone());
            result |= outlookContact.ApplyProperty(c => c.MobileTelephoneNumber, googleContact.Phonenumbers.FirstOrInstance(p => p.Rel == ContactsRelationships.IsMobile).Value.FormatPhone());

            var primaryMailAddress = googleContact.PostalAddresses.FirstOrDefault(p => p.Primary) ?? googleContact.PostalAddresses.FirstOrInstance();
            result |= outlookContact.ApplyProperty(c => c.MailingAddressStreet, string.Format("{0} {1}", primaryMailAddress.Street, primaryMailAddress.Housename));
            result |= outlookContact.ApplyProperty(c => c.MailingAddressCity, primaryMailAddress.City);
            result |= outlookContact.ApplyProperty(c => c.MailingAddressCountry, primaryMailAddress.Country);
            result |= outlookContact.ApplyProperty(c => c.MailingAddressPostalCode, primaryMailAddress.Postcode);
            result |= outlookContact.ApplyProperty(c => c.MailingAddressPostOfficeBox, primaryMailAddress.Pobox);
            result |= outlookContact.ApplyProperty(c => c.MailingAddressState, primaryMailAddress.Region);

            DateTime birth;
            if (!string.IsNullOrEmpty(googleContact.ContactEntry.Birthday) && DateTime.TryParseExact(googleContact.ContactEntry.Birthday, DateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out birth) && birth.Year > 1000 && birth.Year < 2500)
            {
                result |= outlookContact.ApplyProperty(c => c.Birthday, birth);
            }

            result |= outlookContact.ApplyProperty(c => c.BillingInformation, googleContact.ContactEntry.BillingInformation);
            result |= outlookContact.ApplyProperty(c => c.IMAddress, (googleContact.IMs.FirstOrDefault(i => i.Primary) ?? googleContact.IMs.FirstOrInstance()).Address);
            result |= outlookContact.ApplyProperty(c => c.Initials, googleContact.ContactEntry.Initials);
            result |= outlookContact.ApplyProperty(c => c.Language, googleContact.ContactEntry.Language);
            result |= outlookContact.ApplyProperty(c => c.Mileage, googleContact.ContactEntry.Mileage);
            result |= outlookContact.ApplyProperty(c => c.NickName, googleContact.ContactEntry.Nickname);
            result |= outlookContact.ApplyProperty(c => c.WebPage, (googleContact.ContactEntry.Websites.FirstOrDefault(w => w.Primary) ?? googleContact.ContactEntry.Websites.FirstOrInstance()).Href);
            result |= outlookContact.ApplyProperty(c => c.PersonalHomePage, googleContact.ContactEntry.Websites.FirstOrInstance(w => w.Rel == "home-page").Href);
            result |= outlookContact.ApplyProperty(c => c.BusinessHomePage, googleContact.ContactEntry.Websites.FirstOrInstance(w => w.Rel == "work").Href);

            var organization = googleContact.ContactEntry.Organizations.FirstOrDefault(o => o.Primary) ?? googleContact.ContactEntry.Organizations.FirstOrInstance();
            result |= outlookContact.ApplyProperty(c => c.CompanyName, organization.Name);
            result |= outlookContact.ApplyProperty(c => c.Department, organization.Department);
            result |= outlookContact.ApplyProperty(c => c.Profession, organization.Title);

            // Syncing Groups/Categories
            var contactGroups = googleContact.GroupMembership.Select(g => outlookGroups.FirstOrInstance(m => m.Id == g.HRef));
            result |= outlookContact.ApplyProperty(c => c.Categories, string.Join("; ", contactGroups.Select(g => (string.IsNullOrEmpty(g.SystemGroup) ? g.Title : g.SystemGroup))));

            return result;
        }
 /// <summary>
 /// Determines wether the contacts are mergable.
 /// </summary>
 /// <param name="outlookContacts">The outlook contacts.</param>
 /// <param name="googleContact">The google contact.</param>
 /// <returns>
 /// The mergeable Contacts.
 /// </returns>
 public static IEnumerable<ContactItem> Mergeable(this IEnumerable<ContactItem> outlookContacts, Contact googleContact)
 {
     return outlookContacts.Where(c => Mergeable(c, googleContact));
 }
 /// <summary>
 /// Determines wether the contacts are mergable.
 /// </summary>
 /// <param name="outlookContact">The outlook contact.</param>
 /// <param name="googleContact">The google contact.</param>
 /// <returns></returns>
 public static bool Mergeable(ContactItem outlookContact, Contact googleContact)
 {
     return outlookContact.UserProperties.GetProperty("GoogleId") == googleContact.Id ||
            googleContact.Emails.Any(g => g.Address == outlookContact.Email1Address) ||
            googleContact.Emails.Any(g => g.Address == outlookContact.Email2Address) ||
            googleContact.Emails.Any(g => g.Address == outlookContact.Email3Address) ||
            (googleContact.Name.FullName == outlookContact.FullName && googleContact.Phonenumbers.Any(g => g.Value.FormatPhoneClean() == outlookContact.BusinessTelephoneNumber.FormatPhoneClean())) ||
            (googleContact.Name.FullName == outlookContact.FullName && googleContact.Phonenumbers.Any(g => g.Value.FormatPhoneClean() == outlookContact.Business2TelephoneNumber.FormatPhoneClean())) ||
            (googleContact.Name.FullName == outlookContact.FullName && googleContact.Phonenumbers.Any(g => g.Value.FormatPhoneClean() == outlookContact.HomeTelephoneNumber.FormatPhoneClean())) ||
            (googleContact.Name.FullName == outlookContact.FullName && googleContact.Phonenumbers.Any(g => g.Value.FormatPhoneClean() == outlookContact.Home2TelephoneNumber.FormatPhoneClean())) ||
            (googleContact.Name.FullName == outlookContact.FullName && googleContact.Phonenumbers.Any(g => g.Value.FormatPhoneClean() == outlookContact.OtherTelephoneNumber.FormatPhoneClean()));
 }