<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Xml;
using System.Web;

using Maileon.Utils;

namespace Maileon.Contacts
{
    public class MaileonContactsService : AbstractMaileonService
    {
        /// <summary>
        /// The name of this service
        /// </summary>
        public static string SERVICE = "MAILEON CONTACTS";

        /// <summary>
        /// Instantiates a new maileon contacts service
        /// </summary>
        /// <param name="config">The Maileon configuration to use</param>
        public MaileonContactsService(MaileonConfiguration config): base(config, SERVICE) { }

        /// <summary>
        /// Gets the number of contacts
        /// </summary>
        /// <returns></returns>
        public int GetCountContacts()
        {
            ResponseWrapper response = Get("contacts/count");
            return SerializationUtils<int>.FromXmlString(response.Body);
        }

        /// <summary>
        /// Creates the contact
        /// </summary>
        /// <param name="contact">the contact</param>
        /// <param name="syncMode">the maileon synchronization mode</param>
        public void CreateContact(Contact contact, SynchronizationMode syncMode)
        {
            CreateContact(contact, syncMode, null, null, false, false, null);
        }

        /// <summary>
        /// Synchronizes (updates) the contacts in the account with the data from a list of contacts and returns a detailed report with stats and validation errors
        /// </summary>
        /// <param name="contacts">List of contacts to be synchronized</param>
        /// <param name="permission">Specifies the permission to be assigned to the contact</param>
        /// <param name="syncMode">Specifies the synchronization option in case a contact with the provided identifier (external id or email address)</param>
        /// <param name="useExternalId">If set to true, the external id is used as identifier for the contacts. Otherwise the email address is used as identifier.</param>
        /// <param name="ignoreInvalidContacts">If set to true, invalid contacts are ignored and the synchronization succeeds for valid contacts.</param>
        /// <param name="overridePermission">If set to true the permission of existing and non existing contacts will be set to the given permission. If the permission is not set, permission 'none' will be set for new contacts and the permission of existing contacts will not be changed. If set to false, the permission will be used for new contacts only and the permission of existing contacts will not be changed.</param>
        /// <param name="reimportUnsubscribedContacts">If set to true unsubscribed contacts will be reimported, else, they will be ignored.</param>
        /// <param name="updateOnly">If set to true only existing contacts will be updated. Not existing contacts will not be created.</param>
        /// <returns></returns>
        public SynchronizationReport SynchronizeContacts(List<Contact> contacts, Permission permission, SynchronizationMode syncMode, bool useExternalId, bool ignoreInvalidContacts, bool overridePermission, bool reimportUnsubscribedContacts, bool updateOnly)
        {
            if (contacts == null) 
            {
                throw new MaileonClientException("contacts cannot be null", null);
            }
            if (contacts.Count == 0)
            {
                return new SynchronizationReport();
            }

            QueryParameters parameters = new QueryParameters();
            parameters.Add("permission", (int)permission);
            parameters.Add("sync_mode", (int)syncMode);
            parameters.Add("ignore_invalid_contacts", true);
            parameters.Add("use_external_id", useExternalId);
            parameters.Add("override_permission", overridePermission);
            parameters.Add("reimport_unsubscribed_contacts", reimportUnsubscribedContacts);
            parameters.Add("update_only", updateOnly);

            ResponseWrapper response = Post("contacts", parameters, SerializationUtils<ContactCollection>.ToXmlString(contacts));
            return SerializationUtils<SynchronizationReport>.FromXmlString(response.Body);
        }

        /// <summary>
        /// Creates the contact
        /// </summary>
        /// <param name="contact">the contact</param>
        /// <param name="syncMode">the sync mode</param>
        /// <param name="src">the src</param>
        /// <param name="subscriptionPage">the subscription page</param>
        /// <param name="doi">the doi</param>
        /// <param name="doiPlus">the doi plus</param>
        /// <param name="doiMailingKey">the doi mailing key</param>
        public void CreateContact(Contact contact, SynchronizationMode syncMode, string src, string subscriptionPage, bool doi, bool doiPlus, string doiMailingKey) 
        {
            if (contact == null) 
            {
                throw new MaileonClientException("contact cannot be null", null);
            }
            if (contact.Email == null)
            {
                throw new MaileonClientException("email address cannot be null", null);
            }

            QueryParameters parameters = new QueryParameters();
            parameters.Add("permission", (int)contact.Permission);
            parameters.Add("sync_mode", (int)syncMode);
            parameters.Add("src", src);
            parameters.Add("subscription_page", subscriptionPage);
            parameters.Add("doi", doi);
            parameters.Add("doiplus", doiPlus);
            parameters.Add("doimailing", doiMailingKey);

            //this method doesn't accept permission in the contact body
            contact.PermissionSpecified = false;
            contact.SerializeAnonymousSpecified = false;

            string xml = SerializationUtils<Contact>.ToXmlString(contact);
            Post("contacts/" + HttpUtility.UrlEncode(contact.Email), parameters, xml);
        }

        /// <summary>
        /// Gets a page of contacts
        /// </summary>
        /// <param name="standardFields">the standard fields to query</param>
        /// <param name="customFields">the custom fields to query</param>
        /// <param name="pageIndex">the idnex of the page</param>
        /// <param name="pageSize">the number of items on the page</param>
        /// <returns>a page of contacts</returns>
        public Page<Contact> GetContacts(List<StandardFieldName> standardFields, List<string> customFields, int pageIndex, int pageSize)
        {
            ValidatePaginationParameters(pageIndex, pageSize);

            QueryParameters parameters = new QueryParameters();
            parameters.Add("page_index", pageIndex);
            parameters.Add("page_size", pageSize);
            parameters.AddList("standard_field", standardFields);
            parameters.AddList("custom_field", customFields);

            ResponseWrapper response = Get("contacts", parameters);
            Page<Contact> page = new Page<Contact>(pageIndex, pageSize, response);<commit_msg>added the ability to create contact by external id<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Xml;
using System.Web;

using Maileon.Utils;

namespace Maileon.Contacts
{
    public class MaileonContactsService : AbstractMaileonService
    {
        /// <summary>
        /// The name of this service
        /// </summary>
        public static string SERVICE = "MAILEON CONTACTS";

        /// <summary>
        /// Instantiates a new maileon contacts service
        /// </summary>
        /// <param name="config">The Maileon configuration to use</param>
        public MaileonContactsService(MaileonConfiguration config): base(config, SERVICE) { }

        /// <summary>
        /// Gets the number of contacts
        /// </summary>
        /// <returns></returns>
        public int GetCountContacts()
        {
            ResponseWrapper response = Get("contacts/count");
            return SerializationUtils<int>.FromXmlString(response.Body);
        }

        /// <summary>
        /// Synchronizes (updates) the contacts in the account with the data from a list of contacts and returns a detailed report with stats and validation errors
        /// </summary>
        /// <param name="contacts">List of contacts to be synchronized</param>
        /// <param name="permission">Specifies the permission to be assigned to the contact</param>
        /// <param name="syncMode">Specifies the synchronization option in case a contact with the provided identifier (external id or email address)</param>
        /// <param name="useExternalId">If set to true, the external id is used as identifier for the contacts. Otherwise the email address is used as identifier.</param>
        /// <param name="ignoreInvalidContacts">If set to true, invalid contacts are ignored and the synchronization succeeds for valid contacts.</param>
        /// <param name="overridePermission">If set to true the permission of existing and non existing contacts will be set to the given permission. If the permission is not set, permission 'none' will be set for new contacts and the permission of existing contacts will not be changed. If set to false, the permission will be used for new contacts only and the permission of existing contacts will not be changed.</param>
        /// <param name="reimportUnsubscribedContacts">If set to true unsubscribed contacts will be reimported, else, they will be ignored.</param>
        /// <param name="updateOnly">If set to true only existing contacts will be updated. Not existing contacts will not be created.</param>
        /// <returns></returns>
        public SynchronizationReport SynchronizeContacts(List<Contact> contacts, Permission permission, SynchronizationMode syncMode, bool useExternalId, bool ignoreInvalidContacts, bool overridePermission, bool reimportUnsubscribedContacts, bool updateOnly)
        {
            if (contacts == null) 
            {
                throw new MaileonClientException("contacts cannot be null", null);
            }
            if (contacts.Count == 0)
            {
                return new SynchronizationReport();
            }

            QueryParameters parameters = new QueryParameters();
            parameters.Add("permission", (int)permission);
            parameters.Add("sync_mode", (int)syncMode);
            parameters.Add("ignore_invalid_contacts", true);
            parameters.Add("use_external_id", useExternalId);
            parameters.Add("override_permission", overridePermission);
            parameters.Add("reimport_unsubscribed_contacts", reimportUnsubscribedContacts);
            parameters.Add("update_only", updateOnly);

            ResponseWrapper response = Post("contacts", parameters, SerializationUtils<ContactCollection>.ToXmlString(contacts));
            return SerializationUtils<SynchronizationReport>.FromXmlString(response.Body);
        }

        /// <summary>
        /// Creates the contact by email address
        /// </summary>
        /// <param name="contact">the contact</param>
        /// <param name="syncMode">the sync mode</param>
        /// <param name="src">the src</param>
        /// <param name="subscriptionPage">the subscription page</param>
        /// <param name="doi">the doi</param>
        /// <param name="doiPlus">the doi plus</param>
        /// <param name="doiMailingKey">the doi mailing key</param>
        public void CreateContact(Contact contact, SynchronizationMode syncMode, string src = null, string subscriptionPage = null, bool doi = false, bool doiPlus = false, string doiMailingKey = null) 
        {
            if (contact == null) 
            {
                throw new MaileonClientException("contact cannot be null", null);
            }
            if (contact.Email == null)
            {
                throw new MaileonClientException("email address cannot be null", null);
            }
            if(contact.Email != null && contact.ExternalId != null)
            {
                throw new MaileonClientException("ExternalId cannot be set when using CreateContact", null);
            }

            QueryParameters parameters = new QueryParameters();
            parameters.Add("permission", (int)contact.Permission);
            parameters.Add("sync_mode", (int)syncMode);
            parameters.Add("src", src);
            parameters.Add("subscription_page", subscriptionPage);
            parameters.Add("doi", doi);
            parameters.Add("doiplus", doiPlus);
            parameters.Add("doimailing", doiMailingKey);

            //this method doesn't accept permission in the contact body
            contact.PermissionSpecified = false;
            contact.SerializeAnonymousSpecified = false;

            string xml = SerializationUtils<Contact>.ToXmlString(contact);
            Post("contacts/" + HttpUtility.UrlEncode(contact.Email), parameters, xml);
        }

        /// <summary>
        /// Creates the contact by external ID
        /// </summary>
        /// <param name="contact">the contact</param>
        /// <param name="syncMode">the sync mode</param>
        /// <param name="src">the src</param>
        /// <param name="subscriptionPage">the subscription page</param>
        /// <param name="doi">the doi</param>
        /// <param name="doiPlus">the doi plus</param>
        /// <param name="doiMailingKey">the doi mailing key</param>
        public void CreateContactByExternalId(Contact contact, SynchronizationMode syncMode, string src = null, string subscriptionPage = null, bool doi = false, bool doiPlus = false, string doiMailingKey = null)
        {
            if (contact == null)
            {
                throw new MaileonClientException("contact cannot be null", null);
            }
            if (contact.ExternalId == null)
            {
                throw new MaileonClientException("external id cannot be null", null);
            }

            QueryParameters parameters = new QueryParameters();
            parameters.Add("permission", (int)contact.Permission);
            parameters.Add("sync_mode", (int)syncMode);
            parameters.Add("src", src);
            parameters.Add("subscription_page", subscriptionPage);
            parameters.Add("doi", doi);
            parameters.Add("doiplus", doiPlus);
            parameters.Add("doimailing", doiMailingKey);

            //this method doesn't accept permission in the contact body
            contact.PermissionSpecified = false;
            contact.SerializeAnonymousSpecified = false;

            string externalId = contact.ExternalId;
            contact.ExternalId = null;

            string xml = SerializationUtils<Contact>.ToXmlString(contact);
            Post("contacts/externalid/" + HttpUtility.UrlEncode(externalId), parameters, xml);
        }

        /// <summary>
        /// Gets a page of contacts
        /// </summary>
        /// <param name="standardFields">the standard fields to query</param>
        /// <param name="customFields">the custom fields to query</param>
        /// <param name="pageIndex">the idnex of the page</param>
        /// <param name="pageSize">the number of items on the page</param>
        /// <returns>a page of contacts</returns>
        public Page<Contact> GetContacts(List<StandardFieldName> standardFields, List<string> customFields, int pageIndex, int pageSize)
        {
            ValidatePaginationParameters(pageIndex, pageSize);

            QueryParameters parameters = new QueryParameters();
            parameters.Add("page_index", pageIndex);
            parameters.Add("page_size", pageSize);
            parameters.AddList("standard_field", standardFields);
            parameters.AddList("custom_field", customFields);

            ResponseWrapper response = Get("contacts", parameters);
            Page<Contact> page = new Page<Contact>(pageIndex, pageSize, response);
{'fraction_non_alphanumeric': 0.10575669129975782, 'fraction_numerical': 0.0001242004595417003, 'mean_word_length': 2.5581087052585065, 'pattern_counts': {'":': 0, '<': 162, '<?xml version=': 0, '>': 162, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4727928', 'n_tokens_mistral': 3868, 'n_tokens_neox': 3777, 'n_words': 1199}