using System;
using System.IO;
using System.Net;
using System.Web;
using System.Text;
using System.Collections.Generic;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace 
MASample {

    public class 
Example {
        public static 
void Main(string[] args) {

            
#region submitContactImport example
            // The response from submitContactImport is generally just useful for letting you know if it was successful,
            //  but you may wish to use the returned info for some other purpose.
            
var contactimportResponse Request.Post("Contact""submitContactImport", new {
                
// The list of contacts you wish to import. No fields are required.
                // The keys used for each contact must mirror the keys used in the contact_import_mapping object.
                
contacts = new object[] {
                    new {
                        
email_address "johndoe@johndoe.com",
                        
first "John",
                        
last "Doe",
                    },
                    new {
                        
email_address "bob@barkers.com",
                        
first "Bob",
                        
last "Barker",
                        
occupation "Game Show Host",
                        
status "Retired"
                    
}
                },

                
// The keys here must mirror all the different keys used for contacts.
                // The values here map to the attribute names in our system. They must match those names exactly.
                // You can find lists of these attributes when you segment by Contact Attributes, be it Custom or Standard.
                
contact_import_mapping = new {
                    
email_address "Email Address",
                    
first "First Name",
                    
last "Last Name",
                    
occupation "Occupation",
                    
status "Status"
                
},

                
// If the contact exists, update them with this info. if they don't, create the contact.
                
overwrite true,

                
// The name of your import. You should try to keep fairly distinct and unique,
                //  so you can keep track what's changing your data and when.
                
contact_import_name string.Format("Customer Import: Contact Form Submission - {0}"DateTime.Today.ToString("o")),
                
// If C# 6 is available, this and other formatted strings can also be expressed as such:
                // contact_import_name = $"Customer Import: Contact Form Submission - {DateTime.Today.ToString("o")}",

                // Leave as an empty array to skip notifications. Recommended to leave on while testing.
                
notification_recipients = new string[] {
                    
"youraddress@yourdomain.com"
                
},

                
// The list ids to add these contacts to. Leave this blank to do nothing.
                // You can get list ids from the EmailList API controller, or via the interface by hovering the link to edit a list.
                
add_to_lists = new int[] {
                    
123456,
                    
123457
                
},

                
// The list ids to remove contacts from. Leave this blank to do nothing.
                
remove_from_lists = new int[] { }
            });
            
#endregion

            #region getByContact example
            // The getByContact method returns an object containing custom attribute ids instead of the names themselves,
            //  so let's iterate through them and get the names using the getOne call.
            
var attrResp Request.Post("CustomAttribute""getByContact", new {
                
contact_id 442007742
            
});

            
JObject results null;
            
// Note that the "result" index may not be present if this or any other API call results in an error.
            
if (attrResp["result"] != null && attrResp["result"]["results"] != null) {
                
// If the results array is empty, casting to JObject will be null, so check for that.
                
results attrResp["result"]["results"] as JObject ?? new JObject();
            }

            
// There's also a getMultiple method if you wish to retrieve them all at once.
            
foreach (var result in results) {
                var 
attrNameResp Request.Post("CustomAttribute""getOne", new {
                    
custom_attribute_id result.Key
                
});

                
// If C# 6 is available, this can also be written as follows:
                // var attrName = (string)attrNameResp["result"]?["custom_attribute"];
                
string attrName null;
                var 
attrRes attrNameResp["result"];
                if (
attrRes != null) {
                    
attrName = (string)attrRes["custom_attribute"];
                }
                
// And now do something with the attrbute data.
            
}
            
#endregion
        
}
    }

    public static class 
Request {

        private static 
readonly Uri EndpointUrl = new Uri("https://apps.net-results.com/api/v2/rpc/server.php");
        private static 
readonly string BasicUserAuth Convert.ToBase64String("apiuser@yourdomain.com:thepassword".ToByteArray());

        public static 
JToken Post(string controllerstring methodobject requestData) {
            try {
                var 
fullUrl EndpointUrl.AddQueryString(new Dictionary<stringstring> {
                    
// C# 6 also lets you initialize dictionaries like so:
                    // ["Controller"] = controller.ToString()
                    
"Controller"controller.ToString() }
                });
                
// Making post request.
                
return CallHttpCommand(fullUrl"POST"BuildPostData(methodrequestData));
            } catch (
Exception e) {
                
// Unable to complete POST request. Do something with the exception returned.
                
return JsonConvert.SerializeObject(new {
                    
message e.Message,
                    
stackTrace e.StackTrace
                
});
            }
        }

        
/// <summary>
        /// Build the POST data object for making calls to the API.
        /// </summary>
        /// <param name="apiMethod">The API method to call (submitContactImport, getByContact, etc.)</param>
        /// <param name="requestData">The data you wish to send for this method call.</param>
        /// <returns>A JSON object ready to be sent to the API endpoint.</returns>
        
private static JToken BuildPostData(string apiMethodobject requestData) {
            return 
JsonConvert.SerializeObject(new {
                
// A value is required for the id, but it may be any value you choose to identify unique calls.
                // When submitting support requests, please include the value you used here, so we can find it.
                
id Guid.NewGuid(),
                
method apiMethod,
                
jsonrpc "2.0",
                @
params requestData
            
});
        }

        
// The following two methods are more general-purpose.
        // This method calls the NewRequest method and reads out the response into a JToken object.
        
private static JToken CallHttpCommand(Uri requestUrlstring methodJToken requestData null) {
            
using (var response NewRequest(requestUrlmethod, (requestData ?? string.Empty).ToString())) {
                if (
response != null && response.StatusCode == HttpStatusCode.OK) {
                    
using (var stream response.GetResponseStream()) {
                        
using (var reader = new StreamReader(stream)) {
                            return 
JToken.Parse(reader.ReadToEnd());
                        }
                    }
                } else {
                    throw new 
Exception(string.Format("The HTTP command has returned status code {0}"response.StatusCode));
                }
            }
        }

        private static 
HttpWebResponse NewRequest(Uri requestUrlstring methodstring content "") {
            var 
request WebRequest.CreateHttp(requestUrl);
            
// You can use the default credentials and add the encoded username/password as a header,
            //  or instantiate a new NetworkCredential and provide them that way.
            //request.Credentials = new NetworkCredential("apiuser@yourdomain.com", "thepassword");
            
request.Credentials CredentialCache.DefaultNetworkCredentials;
            
request.Timeout 30000;
            
request.UserAgent ".NET Example - 12/8/16";
            
request.Accept request.ContentType "application/json";
            
request.Method method;
            
request.Headers.Add(string.Format("Authorization: Basic {0}"BasicUserAuth));
            if (!
string.IsNullOrEmpty(content)) {
                var 
data content.ToByteArray();
                
request.ContentLength data.Length;
                
using (var stream request.GetRequestStream()) {
                    
stream.Write(data0data.Length);
                }
            }
            try {
                var 
response = (HttpWebResponse)request.GetResponse();
                if (
response.StatusCode != HttpStatusCode.OK) {
                    throw new 
WebException(string.Format("Bad response from server: {0}"response.StatusCode), WebExceptionStatus.ProtocolError);
                }
                return 
response;
            } catch (
WebException e) {
                
Console.WriteLine(string.Format("Unable to perform request. {0} Response returned: {1}"e.Messagee.Response));
                throw;
            } catch (
Exception e) {
                
Console.WriteLine(string.Format("Something completely unexpected happened: {0}."e.Message));
                throw;
            }
        }

        
#region Extension methods.
        /// <summary>
        /// Adds the given query string parameters to the end of this Uri. Any existing parameters will be preserved.
        /// </summary>
        /// <param name="queryParameters">A key-value collection of parameters to be added.</param>
        /// <returns>The Uri object with the new query string included.</returns>
        
public static Uri AddQueryString(this Uri selfIDictionary<stringstringqueryParameters) {
            var 
builder = new UriBuilder(self);
            
// The HttpUtility class is in the System.Web assembly.
            
var currentQuery HttpUtility.ParseQueryString(builder.Query);
            foreach (var 
kvp in queryParameters) {
                
currentQuery[kvp.Key] = kvp.Value;
            }
            
builder.Query currentQuery.ToString();
            return 
builder.Uri;
        }

        
/// <summary>
        /// Converts the characters in this string into bytes. UTF-8 encoding used by default.
        /// </summary>
        /// <returns>An array of the converted bytes from this string.</returns>
        
public static byte[] ToByteArray(this string selfEncoding encoding null) {
            return (
encoding ?? Encoding.UTF8).GetBytes(self);
        }
        
#endregion
    
}
}