using System.IO;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;

namespace Noctalk.Shared.Logging
{
    public static class Noctalk_log
    {
        private static readonly Regex Onion_address_regex = new(@"\b([a-z2-7]{16,56})\.onion\b", RegexOptions.Compiled | RegexOptions.IgnoreCase);

        public static string Log(string The__text_to_log)
        {
            return string.IsNullOrEmpty(The__text_to_log)
                ? string.Empty
                : $"{DateTime.Now:yyyy.MM.dd HH:mm:ss} : {Log__sanitize(The__text_to_log)}";
        }

        private static string Log__sanitize(string The_text)
        {
            return Onion_address_regex.Replace(The_text, The_match => $"{new string('x', The_match.Groups[1].Value.Length)}.onion");
        }
    }
}

namespace Noctalk.Shared.Chat.Configuration
{
    public sealed class Main_client_config
    {
        public bool Flag__sound__on { get; set; } = true;

        public Guid? Current_conversation__guid { get; set; }

        public int Client__local_tor__port { get; set; } = 65191;
    }

    public sealed class Conversation_config
    {
        public Guid conversation__guid { get; set; }

        public Guid conversation__client__guid { get; set; }

        public string conversation__local_encryption__key { get; set; } = string.Empty;

        public string Peer__nickname { get; set; } = string.Empty;

        public string Server__onion_address { get; set; } = string.Empty;

        public Guid? Admin__guid { get; set; }
    }

    public sealed class Server_config
    {
        public Guid Admin__guid { get; set; }

        public string Server__name { get; set; } = "My private chat server";

        public int Server__local_relay_port { get; set; } = 65190;

        public string Onion_address { get; set; } = string.Empty;
    }

    public static class Base64_json_file
    {
        private static readonly JsonSerializerOptions Json_options = new()
        {
            WriteIndented = true
        };

        public static T Read__from__relative_path<T>(string The_base_directory, string The_relative_path) where T : new()
        {
            string path = Path.Combine(The_base_directory, The_relative_path);

            if (!File.Exists(path))
            {
                return new T();
            }

            string encodedJson = File.ReadAllText(path, Encoding.UTF8);
            string json = Encoding.UTF8.GetString(Convert.FromBase64String(encodedJson));
            return JsonSerializer.Deserialize<T>(json, Json_options) ?? new T();
        }

        public static void Write__to__relative_path<T>(string The_base_directory, string The_relative_path, T The_value)
        {
            string path = Path.Combine(The_base_directory, The_relative_path);
            string? directory = Path.GetDirectoryName(path);

            if (!string.IsNullOrWhiteSpace(directory))
            {
                Directory.CreateDirectory(directory);
            }

            string json = JsonSerializer.Serialize(The_value, Json_options);
            string encodedJson = Convert.ToBase64String(Encoding.UTF8.GetBytes(json));
            File.WriteAllText(path, encodedJson, Encoding.UTF8);
        }
    }
}

namespace Noctalk.Shared.Chat.Constants
{
    public static class Client_constants
    {
        public const int Max__image_message__bytes = 2097152;
    }

    public static class Network_constants
    {
        public const int Server__port = 65191;

        public const int Max__transport_chunk__bytes = 262144;

        public const int Max__transport_chunk__retry_count = 3;

        public const int Transport__session__timeout_minutes = 5;
    }

    public static class File_constants
    {
        public const string Conversation_config__extension = ".scon";
    }
}

namespace Noctalk.Shared.Chat.Encryption
{
    public enum enum__Message_delivery
    {
        None = 0,
        Delivered_to_server = 1,
        Delivered_to_peer = 2,
        Read_by_peer = 3,
        Failed_to_send = 4
    }

    public enum Message_type
    {
        Text = 1,
        Image = 2,
        Clear_history = 3
    }

    public sealed class Inner_message
    {
        public Message_type Message_type { get; set; }

        public string Message_content { get; set; } = string.Empty;

        public Guid Sender_client_guid { get; set; }

        public long Message_counter { get; set; }

        public DateTime Created_utc { get; set; }
    }
}

namespace Noctalk.Shared.Chat.Api.Json.Chat_client__to__server.Poll
{
    public sealed class Message
    {
        public string Nonce { get; set; } = string.Empty;

        public string Ciphertext { get; set; } = string.Empty;
    }

    public sealed class Send
    {
        public Guid Api_secret_guid { get; set; }

        public Guid Conversation_guid { get; set; }

        public Guid Client_guid { get; set; }

        public bool Flag__delete__history { get; set; }

        public bool Flag__conversation__has_been_opened { get; set; }

        public Message? Message { get; set; }
    }

    public sealed class Receive
    {
        public bool Flag__success { get; set; }

        public bool Flag__history__deleted { get; set; }

        public bool Flag__conversation_does_not_exists { get; set; }

        public bool Flag__send_locked { get; set; }

        public Noctalk.Shared.Chat.Encryption.enum__Message_delivery Message_delivery__from_this_client_to_peer { get; set; }

        public bool Flag__peer_online { get; set; }

        public Message? Message_to_client { get; set; }

        public List<Message> Messages { get; set; } = [];
    }

    public sealed class Send__and__receive__conversation
    {
        public Guid Conversation_guid { get; set; }

        public Guid Client_guid { get; set; }

        public bool Flag__delete__history { get; set; }

        public bool Flag__conversation__has_been_opened { get; set; }

        public List<Message> Messages_to_send { get; set; } = [];
    }

    public sealed class Send__and__receive__send
    {
        public Guid Api_secret_guid { get; set; }

        public List<Send__and__receive__conversation> Conversations { get; set; } = [];
    }

    public sealed class Send__and__receive__conversation_result
    {
        public Guid Conversation_guid { get; set; }

        public bool Flag__success { get; set; }

        public bool Flag__history__deleted { get; set; }

        public bool Flag__conversation_does_not_exists { get; set; }

        public bool Flag__send_locked { get; set; }

        public Noctalk.Shared.Chat.Encryption.enum__Message_delivery Message_delivery__from_this_client_to_peer { get; set; }

        public bool Flag__peer_online { get; set; }

        public List<Message> Messages { get; set; } = [];
    }

    public sealed class Send__and__receive__receive
    {
        public bool Flag__success { get; set; }

        public List<Send__and__receive__conversation_result> Conversations { get; set; } = [];
    }

    public sealed class Transport__chunk__send
    {
        public Guid Transport__session_guid { get; set; }

        public bool Flag__last_chunk { get; set; }

        public bool Flag__download_response_chunk { get; set; }

        public int Transport__chunk_index { get; set; }

        public Guid Transport__response_session_guid { get; set; }

        public string Transport__payload_base64 { get; set; } = string.Empty;
    }

    public sealed class Transport__chunk__receive
    {
        public bool Flag__success { get; set; }

        public bool Flag__transport_session_completed { get; set; }

        public bool Flag__transport_session_failed { get; set; }

        public bool Flag__response_requires_chunk_download { get; set; }

        public bool Flag__last_chunk { get; set; }

        public string Message_to_client { get; set; } = string.Empty;

        public Guid Transport__response_session_guid { get; set; }

        public int Transport__chunk_index { get; set; }

        public string Transport__response_payload_base64 { get; set; } = string.Empty;
    }
}

namespace Noctalk.Shared.Chat.Api.Json.Admin_client__to__server.Command
{
    public sealed class Send
    {
        public Guid Admin__guid { get; set; }

        public bool Flag__create__conversation_pair { get; set; }

        public bool Flag__get__conversation_list { get; set; }

        public bool Flag__delete__conversation { get; set; }

        public Guid Conversation_guid { get; set; }
    }

    public sealed class Receive
    {
        public bool Flag__success { get; set; }

        public bool Flag__conversation_created { get; set; }

        public bool Flag__conversation_deleted { get; set; }

        public bool Flag__invalid_admin_api_secret { get; set; }

        public string Message_to_admin { get; set; } = string.Empty;

        public string Server__name { get; set; } = string.Empty;

        public List<Conversation__metadata> Conversation__metadata { get; set; } = [];
    }

    public sealed class Conversation__metadata
    {
        public Guid Conversation_guid { get; set; }

        public DateTime Conversation__metadata__date__created { get; set; }

        public int Pending_messages__count { get; set; }

        public int Client_A__pending_message_count { get; set; }

        public DateTime? Client_A__last_sent__date { get; set; }

        public int Client_B__pending_message_count { get; set; }

        public DateTime? Client_B__last_sent__date { get; set; }
    }
}
