<commit_before>﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using VndbSharp.Enums;
using VndbSharp.Interfaces;
using VndbSharp.Structs.Models;
using VndbSharp.Structs.Models.Character;
using VndbSharp.Structs.Models.DatabaseStats;
using VndbSharp.Structs.Models.Error;
using VndbSharp.Structs.Models.Producer;
using VndbSharp.Structs.Models.Release;
using VndbSharp.Structs.Models.User;
using VndbSharp.Structs.Models.VnList;
using VndbSharp.Structs.Models.Votelist;
using VndbSharp.Structs.Models.Wishlist;
using VisualNovel = VndbSharp.Structs.Models.VisualNovel.VisualNovel;

namespace VndbSharp
{
	public class VndbClient : IDisposable
	{
		private Boolean _useTls;

		private Int32 _receiveBufferSize = 1024 * 4;
		private Int32 _sendBufferSize = 1024 * 4;

		protected String LastErrorJson;
		protected IVndbError LastError;

		protected TcpClient Client;

		protected Stream Stream;

		protected Boolean LoggedIn;

		protected String Username;
		protected SecureString Password;

		public Int32 ReceiveBufferSize
		{
			get { return this.Client?.ReceiveBufferSize ?? this._receiveBufferSize; }
			set
			{
				if (this.Client != null)
					this.Client.ReceiveBufferSize = value;
				this._receiveBufferSize = value;
			}
		}

		public Int32 SendBufferSize
		{
			get { return this.Client?.SendBufferSize ?? this._sendBufferSize; }
			set
			{
				if (this.Client != null)
					this.Client.SendBufferSize = value;
				this._sendBufferSize = value;
			}
		}

		public Boolean UseTls
		{
			get { return this._useTls; }
			set
			{
				if (!String.IsNullOrWhiteSpace(this.Username) || this.Password != null)
					throw new InvalidOperationException($"Cannot change {nameof(this.UseTls)} state while using a username / password.");

				this._useTls = value;
				this.LoggedIn = false;
			}
		}

        // TODO: Use HasMono property on TLS to warn about lack of encryption support
	    internal static Boolean HasMono { get; } = Type.GetType("Mono.Runtime") != null;

		public VndbClient()
		{ }

		public VndbClient(Boolean useTls)
		{
			this.UseTls = useTls;
		}

		/// <summary>
		///		If using .Net Core or Mono, please read https://github.com/Nikey646/VndbSharp/wiki/Mono-and-.Net-Core#securestring--username--password-logins
		/// 
		/// 	This will also *force* a secure connection.
		/// </summary>
		public VndbClient(String username, SecureString password)
		{
			this.UseTls = true;
			this.Username = username;
			this.Password = password;
		}

		public async Task<DatabaseStats> GetDatabaseStatsAsync()
			=> await this.SendRequestInternalAsync<DatabaseStats>(Constants.DbStatsCommand).ConfigureAwait(false);

		public async Task<RootObject<VisualNovel>> GetVisualNovelAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
			=> await this.SendRequestInternalAsync<RootObject<VisualNovel>>(Constants.GetVotelistCommand, flags, filters, options)
				.ConfigureAwait(false);

		public async Task<RootObject<Release>> GetReleaseAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
			=> await this.SendRequestInternalAsync<RootObject<Release>>(Constants.GetReleaseCommand, flags, filters, options)
				.ConfigureAwait(false);

		public async Task<RootObject<Producer>> GetProducerAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
			=> await this.SendRequestInternalAsync<RootObject<Producer>>(Constants.GetProducerCommand, flags, filters, options)
				.ConfigureAwait(false);

		public async Task<RootObject<Character>> GetCharacterAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
			=> await this.SendRequestInternalAsync<RootObject<Character>>(Constants.GetCharacterCommand, flags, filters, options)
				.ConfigureAwait(false);

		public async Task<RootObject<User>> GetUserAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
			=> await this.SendRequestInternalAsync<RootObject<User>>(Constants.GetUserCommand, flags, filters, options)
				.ConfigureAwait(false);

		public async Task<RootObject<Votelist>> GetVotelistAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
			=> await this.SendRequestInternalAsync<RootObject<Votelist>>(Constants.GetVotelistCommand, flags, filters, options)
				.ConfigureAwait(false);

		public async Task<RootObject<VnList>> GetVnListAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)<commit_msg>Fixed a tiny mistake I found<commit_after>﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using VndbSharp.Enums;
using VndbSharp.Interfaces;
using VndbSharp.Structs.Models;
using VndbSharp.Structs.Models.Character;
using VndbSharp.Structs.Models.DatabaseStats;
using VndbSharp.Structs.Models.Error;
using VndbSharp.Structs.Models.Producer;
using VndbSharp.Structs.Models.Release;
using VndbSharp.Structs.Models.User;
using VndbSharp.Structs.Models.VnList;
using VndbSharp.Structs.Models.Votelist;
using VndbSharp.Structs.Models.Wishlist;
using VisualNovel = VndbSharp.Structs.Models.VisualNovel.VisualNovel;

namespace VndbSharp
{
	public class VndbClient : IDisposable
	{
		private Boolean _useTls;

		private Int32 _receiveBufferSize = 1024 * 4;
		private Int32 _sendBufferSize = 1024 * 4;

		protected String LastErrorJson;
		protected IVndbError LastError;

		protected TcpClient Client;

		protected Stream Stream;

		protected Boolean LoggedIn;

		protected String Username;
		protected SecureString Password;

		public Int32 ReceiveBufferSize
		{
			get { return this.Client?.ReceiveBufferSize ?? this._receiveBufferSize; }
			set
			{
				if (this.Client != null)
					this.Client.ReceiveBufferSize = value;
				this._receiveBufferSize = value;
			}
		}

		public Int32 SendBufferSize
		{
			get { return this.Client?.SendBufferSize ?? this._sendBufferSize; }
			set
			{
				if (this.Client != null)
					this.Client.SendBufferSize = value;
				this._sendBufferSize = value;
			}
		}

		public Boolean UseTls
		{
			get { return this._useTls; }
			set
			{
				if (!String.IsNullOrWhiteSpace(this.Username) || this.Password != null)
					throw new InvalidOperationException($"Cannot change {nameof(this.UseTls)} state while using a username / password.");

				this._useTls = value;
				this.LoggedIn = false;
			}
		}

        // TODO: Use HasMono property on TLS to warn about lack of encryption support
	    internal static Boolean HasMono { get; } = Type.GetType("Mono.Runtime") != null;

		public VndbClient()
		{ }

		public VndbClient(Boolean useTls)
		{
			this.UseTls = useTls;
		}

		/// <summary>
		///		If using .Net Core or Mono, please read https://github.com/Nikey646/VndbSharp/wiki/Mono-and-.Net-Core#securestring--username--password-logins
		/// 
		/// 	This will also *force* a secure connection.
		/// </summary>
		public VndbClient(String username, SecureString password)
		{
			this.UseTls = true;
			this.Username = username;
			this.Password = password;
		}

		public async Task<DatabaseStats> GetDatabaseStatsAsync()
			=> await this.SendRequestInternalAsync<DatabaseStats>(Constants.DbStatsCommand).ConfigureAwait(false);

		public async Task<RootObject<VisualNovel>> GetVisualNovelAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
			=> await this.SendRequestInternalAsync<RootObject<VisualNovel>>(Constants.GetVisualNovelCommand, flags, filters, options)
				.ConfigureAwait(false);

		public async Task<RootObject<Release>> GetReleaseAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
			=> await this.SendRequestInternalAsync<RootObject<Release>>(Constants.GetReleaseCommand, flags, filters, options)
				.ConfigureAwait(false);

		public async Task<RootObject<Producer>> GetProducerAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
			=> await this.SendRequestInternalAsync<RootObject<Producer>>(Constants.GetProducerCommand, flags, filters, options)
				.ConfigureAwait(false);

		public async Task<RootObject<Character>> GetCharacterAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
			=> await this.SendRequestInternalAsync<RootObject<Character>>(Constants.GetCharacterCommand, flags, filters, options)
				.ConfigureAwait(false);

		public async Task<RootObject<User>> GetUserAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
			=> await this.SendRequestInternalAsync<RootObject<User>>(Constants.GetUserCommand, flags, filters, options)
				.ConfigureAwait(false);

		public async Task<RootObject<Votelist>> GetVotelistAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
			=> await this.SendRequestInternalAsync<RootObject<Votelist>>(Constants.GetVotelistCommand, flags, filters, options)
				.ConfigureAwait(false);

		public async Task<RootObject<VnList>> GetVnListAsync(VndbFlags flags, IFilter filters,
			IRequestOptions options = null)
{'fraction_non_alphanumeric': 0.09685751183814034, 'fraction_numerical': 0.004520017219113216, 'mean_word_length': 4.793640897755611, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 77, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, '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': '1966614', 'n_tokens_mistral': 3260, 'n_tokens_neox': 2808, 'n_words': 630}