<commit_before>﻿using KryptPadCSApp.API.Models;
using KryptPadCSApp.API.Responses;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace KryptPadCSApp.API
{

    /// <summary>
    /// Accesses the KryptPad API
    /// </summary>
    class KryptPadApi
    {
#if LOCAL
        /// <summary>
        /// Gets the host address of the API service.
        /// </summary>
        private static string ServiceHost { get; } = "http://localhost:50821/"; //
#elif DEBUG
        /// <summary>
        /// Gets the host address of the API service.
        /// </summary>
        private static string ServiceHost { get; } = "http://test.kryptpad.com/";
#else
        /// <summary>
        /// Gets the host address of the API service.
        /// </summary>
        private static string ServiceHost { get; } = "https://www.kryptpad.com/";
#endif


        #region Properties

        /// <summary>
        /// Gets or sets the API OAuth access token to authorize API calls
        /// </summary>
        private static OAuthTokenResponse TokenResponse { get; set; }
        
        /// <summary>
        /// Gets or sets the username of the user logged in
        /// </summary>
        private static string Username { get; set; }

        /// <summary>
        /// Gets or sets the password of the user logged in
        /// </summary>
        private static string Password { get; set; }

        /// <summary>
        /// Gets or sets the passphrase for the profile
        /// </summary>
        private static string Passphrase { get; set; }

        /// <summary>
        /// Gets or sets the current profile Id
        /// </summary>
        public static ApiProfile CurrentProfile { get; private set; }

        /// <summary>
        /// Gets whether the user is signed in
        /// </summary>
        public static bool IsSignedIn
        {
            get { return !string.IsNullOrWhiteSpace(TokenResponse?.AccessToken); }
        }
        #endregion


        /// <summary>
        /// Creates an authorization request
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public static async Task AuthenticateAsync(string username, string password)
        {
            // Clear token response
            TokenResponse = null;

            using (var client = new HttpClient())
            {
                // Prepare form values
                var values = new Dictionary<string, string>
                {
                    { "grant_type", "password" },
                    { "username", username },
                    { "password", password }
                };

                // Create the content to send
                var content = new FormUrlEncodedContent(values);
                // Send the post request
                var response = await client.PostAsync(GetUrl("token"), content);
                
                // Get the data if the response is what we want
                if (response.IsSuccessStatusCode)
                {
                    // Get the response as a string
                    var data = await response.Content.ReadAsStringAsync();

                    // Deserialize the data and get the access token
                    TokenResponse = JsonConvert.DeserializeObject<OAuthTokenResponse>(data);
                    
                    // Store the username and password for future use
                    Username = username;
                    Password = password;
                }
                else
                {
                    throw await CreateException(response);
                }
            }
            
        }

        /// <summary>
        /// Creates an account in the system
        /// </summary>
        /// <param name="username"></param>
        /// <param name="email"></param>
        /// <returns></returns>
        public static async Task<SuccessResponse> CreateAccountAsync(string username, string password)
        {<commit_msg>Update to authenticate method<commit_after>﻿using KryptPadCSApp.API.Models;
using KryptPadCSApp.API.Responses;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace KryptPadCSApp.API
{

    /// <summary>
    /// Accesses the KryptPad API
    /// </summary>
    class KryptPadApi
    {
#if LOCAL
        /// <summary>
        /// Gets the host address of the API service.
        /// </summary>
        private static string ServiceHost { get; } = "http://localhost:50821/"; //
#elif DEBUG
        /// <summary>
        /// Gets the host address of the API service.
        /// </summary>
        private static string ServiceHost { get; } = "http://test.kryptpad.com/";
#else
        /// <summary>
        /// Gets the host address of the API service.
        /// </summary>
        private static string ServiceHost { get; } = "https://www.kryptpad.com/";
#endif

        #region Events
        public static event EventHandler AccessTokenExpired;
        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the API OAuth access token to authorize API calls
        /// </summary>
        private static OAuthTokenResponse TokenResponse { get; set; }
        
        /// <summary>
        /// Gets or sets the username of the user logged in
        /// </summary>
        private static string Username { get; set; }

        /// <summary>
        /// Gets or sets the password of the user logged in
        /// </summary>
        private static string Password { get; set; }

        /// <summary>
        /// Gets or sets the passphrase for the profile
        /// </summary>
        private static string Passphrase { get; set; }

        /// <summary>
        /// Gets or sets the current profile Id
        /// </summary>
        public static ApiProfile CurrentProfile { get; private set; }

        /// <summary>
        /// Gets whether the user is signed in
        /// </summary>
        public static bool IsSignedIn
        {
            get { return !string.IsNullOrWhiteSpace(TokenResponse?.AccessToken); }
        }

        /// <summary>
        /// Gets or sets the CancellationToken for the task
        /// </summary>
        private static CancellationTokenSource ExpirationTaskCancelTokenSource { get; set; }

        /// <summary>
        /// Gets or sets the task used to check if the expiration date has passed
        /// </summary>
        private static Task ExpirationTask { get; set; }
        #endregion


        /// <summary>
        /// Creates an authorization request
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public static async Task AuthenticateAsync(string username, string password)
        {
            // Clear token response
            TokenResponse = null;

            using (var client = new HttpClient())
            {
                // Prepare form values
                var values = new Dictionary<string, string>
                {
                    { "grant_type", "password" },
                    { "username", username },
                    { "password", password }
                };

                // Create the content to send
                var content = new FormUrlEncodedContent(values);
                // Send the post request
                var response = await client.PostAsync(GetUrl("token"), content);
                
                // Get the data if the response is what we want
                if (response.IsSuccessStatusCode)
                {
                    // Get the response as a string
                    var data = await response.Content.ReadAsStringAsync();

                    // Before updating the token, kill the current task
                    if (ExpirationTaskCancelTokenSource != null)
                    {
                        // Cancel task
                        ExpirationTaskCancelTokenSource.Cancel();
                        // Wait for the task to complete
                        await ExpirationTask;
                    }

                    // Deserialize the data and get the access token
                    TokenResponse = JsonConvert.DeserializeObject<OAuthTokenResponse>(data);
                    
                    // Store the username and password for future use
                    Username = username;
                    Password = password;

                    // Initialize new cancellation token
                    ExpirationTaskCancelTokenSource = new CancellationTokenSource();

                    // Start a task that will check the expiration date of the access token, when
                    // the current time has passed token expiration, an event will be raised.
                    ExpirationTask = Task.Factory.StartNew(async () => {
                        // Get local date from expiration
                        var expiration = TimeZoneInfo.ConvertTime(TokenResponse.Expiration, TimeZoneInfo.Local);

                        // Enter a while loop and check that the expiration date hasn't passed
                        while (DateTime.Now < expiration)
                        {
                            // Wait a bit, then check again
                            ExpirationTaskCancelTokenSource.Token.ThrowIfCancellationRequested();

                            // Wait a bit, then check again
                            await Task.Delay(1000);
                        }
                    }, ExpirationTaskCancelTokenSource.Token);
                }
                else
                {
                    throw await CreateException(response);
                }
            }
            
        }

        /// <summary>
        /// Creates an account in the system
        /// </summary>
        /// <param name="username"></param>
        /// <param name="email"></param>
        /// <returns></returns>
        public static async Task<SuccessResponse> CreateAccountAsync(string username, string password)
        {
{'fraction_non_alphanumeric': 0.09617029364249739, 'fraction_numerical': 0.0013304190820108335, 'mean_word_length': 1.4497206703910615, 'pattern_counts': {'":': 0, '<': 82, '<?xml version=': 0, '>': 82, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, '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': '3375099', 'n_tokens_mistral': 2486, 'n_tokens_neox': 2370, 'n_words': 804}