public ConflictResolution Resolve(ContactMatch match, bool isNewMatch)
        {
            string name = match.ToString();

            if (isNewMatch)
            {
                _form.messageLabel.Text =
                    "This is the first time these Outlook and Google Contacts \"" + name +
                    "\" are synced. Choose which you would like to keep.";
                _form.skip.Text = "Keep both";
            }
            else
            {
                _form.messageLabel.Text =
                    "Both the Outlook Contact and the Google Contact \"" + name +
                    "\" have been changed. Choose which you would like to keep.";
            }

            _form.OutlookItemTextBox.Text = string.Empty;
            _form.GoogleItemTextBox.Text = string.Empty;
            if (match.OutlookContact != null)
            {
                Microsoft.Office.Interop.Outlook.ContactItem item = match.OutlookContact.GetOriginalItemFromOutlook();
                try
                {
                    _form.OutlookItemTextBox.Text = ContactMatch.GetSummary(item);
                }
                finally
                {
                    if (item != null)
                    {
                        System.Runtime.InteropServices.Marshal.ReleaseComObject(item);
                        item = null;
                    }
                }

            }

            if (match.GoogleContact != null)
                _form.GoogleItemTextBox.Text = ContactMatch.GetSummary(match.GoogleContact);

            return Resolve();
        }
        public static void SyncContact(ContactMatch match, Synchronizer sync)
        {
            Outlook.ContactItem outlookContactItem = match.OutlookContact != null ? match.OutlookContact.GetOriginalItemFromOutlook() : null;

            try
            {
                if (match.GoogleContact == null && match.OutlookContact != null)
                {
                    //no google contact
                    string googleContactId = match.OutlookContact.UserProperties.GoogleContactId;
                    if (!string.IsNullOrEmpty(googleContactId))
                    {
                        //Redundant check if exist, but in case an error occurred in MatchContacts
                        Contact matchingGoogleContact = sync.GetGoogleContactById(googleContactId);
                        if (matchingGoogleContact == null)
                        {
                            if (sync.SyncOption == SyncOption.OutlookToGoogleOnly || !sync.SyncDelete)
                                return;
                            else if (!sync.PromptDelete)
                                 sync.DeleteOutlookResolution = DeleteResolution.DeleteOutlookAlways;
                            else if (sync.DeleteOutlookResolution != DeleteResolution.DeleteOutlookAlways &&
                                     sync.DeleteOutlookResolution != DeleteResolution.KeepOutlookAlways)
                            {
                                var r = new ConflictResolver();
                                sync.DeleteOutlookResolution = r.ResolveDelete(match.OutlookContact);
                            }
                            switch (sync.DeleteOutlookResolution)
                            {
                                case DeleteResolution.KeepOutlook:
                                case DeleteResolution.KeepOutlookAlways:
                                    ContactPropertiesUtils.ResetOutlookGoogleContactId(sync, outlookContactItem);
                                    break;
                                case DeleteResolution.DeleteOutlook:
                                case DeleteResolution.DeleteOutlookAlways:
                                    //Avoid recreating a GoogleContact already existing
                                    //==> Delete this outlookContact instead if previous match existed but no match exists anymore
                                    return;
                                default:
                                    throw new ApplicationException("Cancelled");
                            }
                        }
                    }

                    if (sync.SyncOption == SyncOption.GoogleToOutlookOnly)
                    {
                        sync.SkippedCount++;
                        Logger.Log(string.Format("Outlook Contact not added to Google, because of SyncOption " + sync.SyncOption.ToString() + ": {0}", match.OutlookContact.FileAs), EventType.Information);
                        return;
                    }

                    //create a Google contact from Outlook contact
                    match.GoogleContact = new Contact();

                    sync.UpdateContact(outlookContactItem, match.GoogleContact);

                }
                else if (match.OutlookContact == null && match.GoogleContact != null)
                {

                    // no outlook contact
                    string outlookId = ContactPropertiesUtils.GetGoogleOutlookContactId(sync.SyncProfile, match.GoogleContact);
                    if (outlookId != null)
                    {
                        if (sync.SyncOption == SyncOption.GoogleToOutlookOnly || !sync.SyncDelete)
                            return;
                        else if (!sync.PromptDelete)
                            sync.DeleteGoogleResolution = DeleteResolution.DeleteGoogleAlways;
                        else if (sync.DeleteGoogleResolution != DeleteResolution.DeleteGoogleAlways &&
                                 sync.DeleteGoogleResolution != DeleteResolution.KeepGoogleAlways)
                        {
                            var r = new ConflictResolver();
                            sync.DeleteGoogleResolution = r.ResolveDelete(match.GoogleContact);
                        }
                        switch (sync.DeleteGoogleResolution)
                        {
                            case DeleteResolution.KeepGoogle:
                            case DeleteResolution.KeepGoogleAlways:
                                ContactPropertiesUtils.ResetGoogleOutlookContactId(sync.SyncProfile, match.GoogleContact);
                                break;
                            case DeleteResolution.DeleteGoogle:
                            case DeleteResolution.DeleteGoogleAlways:
                                //Avoid recreating a OutlookContact already existing
                                //==> Delete this googleContact instead if previous match existed but no match exists anymore
                                return;
                            default:
                                throw new ApplicationException("Cancelled");
                        }

                    }

                    if (sync.SyncOption == SyncOption.OutlookToGoogleOnly)
                    {
                        sync.SkippedCount++;
                        Logger.Log(string.Format("Google Contact not added to Outlook, because of SyncOption " + sync.SyncOption.ToString() + ": {0}", match.GoogleContact.Title), EventType.Information);
                        return;
                    }

                    //create a Outlook contact from Google contact
                    outlookContactItem = Synchronizer.CreateOutlookContactItem(Synchronizer.SyncContactsFolder);

                    sync.UpdateContact(match.GoogleContact, outlookContactItem);
                    match.OutlookContact = new OutlookContactInfo(outlookContactItem, sync);
                }
                else if (match.OutlookContact != null && match.GoogleContact != null)
                {
                    //merge contact details

                    //determine if this contact pair were synchronized
                    //DateTime? lastUpdated = GetOutlookPropertyValueDateTime(match.OutlookContact, sync.OutlookPropertyNameUpdated);
                    DateTime? lastSynced = match.OutlookContact.UserProperties.LastSync;
                    if (lastSynced.HasValue)
                    {
                        //contact pair was syncronysed before.

                        //determine if google contact was updated since last sync

                        //lastSynced is stored without seconds. take that into account.
                        DateTime lastUpdatedOutlook = match.OutlookContact.LastModificationTime.AddSeconds(-match.OutlookContact.LastModificationTime.Second);
                        DateTime lastUpdatedGoogle = match.GoogleContact.Updated.AddSeconds(-match.GoogleContact.Updated.Second);

                        //check if both outlok and google contacts where updated sync last sync
                        if (lastUpdatedOutlook.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance
                            && lastUpdatedGoogle.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance)
                        {
                            //both contacts were updated.
                            //options: 1) ignore 2) loose one based on SyncOption
                            //throw new Exception("Both contacts were updated!");

                            switch (sync.SyncOption)
                            {
                                case SyncOption.MergeOutlookWins:
                                case SyncOption.OutlookToGoogleOnly:
                                    //overwrite google contact
                                    Logger.Log("Outlook and Google contact have been updated, Outlook contact is overwriting Google because of SyncOption " + sync.SyncOption + ": " + match.OutlookContact.FileAs + ".", EventType.Information);
                                    sync.UpdateContact(outlookContactItem, match.GoogleContact);
                                    break;
                                case SyncOption.MergeGoogleWins:
                                case SyncOption.GoogleToOutlookOnly:
                                    //overwrite outlook contact
                                    Logger.Log("Outlook and Google contact have been updated, Google contact is overwriting Outlook because of SyncOption " + sync.SyncOption + ": " + match.OutlookContact.FileAs + ".", EventType.Information);
                                    sync.UpdateContact(match.GoogleContact, outlookContactItem);
                                    break;
                                case SyncOption.MergePrompt:
                                    //promp for sync option
                                    if (sync.ConflictResolution != ConflictResolution.GoogleWinsAlways &&
                                        sync.ConflictResolution != ConflictResolution.OutlookWinsAlways &&
                                        sync.ConflictResolution != ConflictResolution.SkipAlways)
                                    {
                                        var r = new ConflictResolver();
                                        sync.ConflictResolution = r.Resolve(match, false);
                                    }
                                    switch (sync.ConflictResolution)
                                    {
                                        case ConflictResolution.Skip:
                                        case ConflictResolution.SkipAlways:
                                            Logger.Log(string.Format("User skipped contact ({0}).", match.ToString()), EventType.Information);
                                            sync.SkippedCount++;
                                            break;
                                        case ConflictResolution.OutlookWins:
                                        case ConflictResolution.OutlookWinsAlways:
                                            sync.UpdateContact(outlookContactItem, match.GoogleContact);
                                            break;
                                        case ConflictResolution.GoogleWins:
                                        case ConflictResolution.GoogleWinsAlways:
                                            sync.UpdateContact(match.GoogleContact, outlookContactItem);
                                            break;
                                        default:
                                            throw new ApplicationException("Cancelled");
                                    }
                                    break;
                            }
                            return;
                        }

                        //check if outlook contact was updated (with X second tolerance)
                        if (sync.SyncOption != SyncOption.GoogleToOutlookOnly &&
                            (lastUpdatedOutlook.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance ||
                             lastUpdatedGoogle.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance &&
                             sync.SyncOption == SyncOption.OutlookToGoogleOnly
                            )
                           )
                        {
                            //outlook contact was changed or changed Google contact will be overwritten

                            if (lastUpdatedGoogle.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance &&
                                sync.SyncOption == SyncOption.OutlookToGoogleOnly)
                                Logger.Log("Google contact has been updated since last sync, but Outlook contact is overwriting Google because of SyncOption " + sync.SyncOption + ": " + match.OutlookContact.FileAs + ".", EventType.Information);

                            sync.UpdateContact(outlookContactItem, match.GoogleContact);

                            //at the moment use outlook as "master" source of contacts - in the event of a conflict google contact will be overwritten.
                            //TODO: control conflict resolution by SyncOption
                            return;
                        }

                        //check if google contact was updated (with X second tolerance)
                        if (sync.SyncOption != SyncOption.OutlookToGoogleOnly &&
                            (lastUpdatedGoogle.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance ||
                             lastUpdatedOutlook.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance &&
                             sync.SyncOption == SyncOption.GoogleToOutlookOnly
                            )
                           )
                        {
                            //google contact was changed or changed Outlook contact will be overwritten

                            if (lastUpdatedOutlook.Subtract(lastSynced.Value).TotalSeconds > TimeTolerance &&
                                sync.SyncOption == SyncOption.GoogleToOutlookOnly)
                                Logger.Log("Outlook contact has been updated since last sync, but Google contact is overwriting Outlook because of SyncOption " + sync.SyncOption + ": " + match.OutlookContact.FileAs + ".", EventType.Information);

                            sync.UpdateContact(match.GoogleContact, outlookContactItem);
                        }
                    }
                    else
                    {
                        //contacts were never synced.
                        //merge contacts.
                        switch (sync.SyncOption)
                        {
                            case SyncOption.MergeOutlookWins:
                            case SyncOption.OutlookToGoogleOnly:
                                //overwrite google contact
                                sync.UpdateContact(outlookContactItem, match.GoogleContact);
                                break;
                            case SyncOption.MergeGoogleWins:
                            case SyncOption.GoogleToOutlookOnly:
                                //overwrite outlook contact
                                sync.UpdateContact(match.GoogleContact, outlookContactItem);
                                break;
                            case SyncOption.MergePrompt:
                                //promp for sync option
                                if (sync.ConflictResolution != ConflictResolution.GoogleWinsAlways &&
                                    sync.ConflictResolution != ConflictResolution.OutlookWinsAlways &&
                                    sync.ConflictResolution != ConflictResolution.SkipAlways)
                                {
                                    var r = new ConflictResolver();
                                    sync.ConflictResolution = r.Resolve(match, true);
                                }
                                switch (sync.ConflictResolution)
                                {
                                    case ConflictResolution.Skip:
                                    case ConflictResolution.SkipAlways: //Keep both, Google AND Outlook
                                        sync.Contacts.Add(new ContactMatch(match.OutlookContact, null));
                                        sync.Contacts.Add(new ContactMatch(null, match.GoogleContact));
                                        break;
                                    case ConflictResolution.OutlookWins:
                                    case ConflictResolution.OutlookWinsAlways:
                                        sync.UpdateContact(outlookContactItem, match.GoogleContact);
                                        break;
                                    case ConflictResolution.GoogleWins:
                                    case ConflictResolution.GoogleWinsAlways:
                                        sync.UpdateContact(match.GoogleContact, outlookContactItem);
                                        break;
                                    default:
                                        throw new ApplicationException("Cancelled");
                                }
                                break;
                        }
                    }

                }
                else
                    throw new ArgumentNullException("ContactMatch has all peers null.");
            }
            catch (ArgumentNullException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new Exception("Error syncing contact " + (match.OutlookContact != null ? match.OutlookContact.FileAs : match.GoogleContact.Title) + ": " + e.Message, e);
            }
            finally
            {
                if (outlookContactItem != null &&
                    match.OutlookContact != null)
                {
                    match.OutlookContact.Update(outlookContactItem, sync);
                    Marshal.ReleaseComObject(outlookContactItem);
                    outlookContactItem = null;
                }
            }
        }