using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using GEUTEBRUECK.GeViScope.Wrapper.DBI;

namespace GeViScopeConfigReader
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("=======================================================");
            Console.WriteLine("GeViScope Configuration Reader");
            Console.WriteLine("Reads server configuration and exports to JSON");
            Console.WriteLine("=======================================================");
            Console.WriteLine();

            // Configuration
            string hostname = "localhost";
            string username = "sysadmin";
            string password = "masterkey";
            string outputFile = "geviScope_config.json";

            // Parse command line arguments
            if (args.Length >= 1) hostname = args[0];
            if (args.Length >= 2) username = args[1];
            if (args.Length >= 3) password = args[2];
            if (args.Length >= 4) outputFile = args[3];

            Console.WriteLine($"Server: {hostname}");
            Console.WriteLine($"Username: {username}");
            Console.WriteLine($"Output: {outputFile}");
            Console.WriteLine();

            try
            {
                // Step 1: Connect to server
                Console.WriteLine("Connecting to GeViScope server...");

                GscServerConnectParams connectParams = new GscServerConnectParams(
                    hostname,
                    username,
                    DBIHelperFunctions.EncodePassword(password)
                );

                GscServer server = new GscServer(connectParams);
                GscServerConnectResult connectResult = server.Connect();

                if (connectResult != GscServerConnectResult.connectOk)
                {
                    Console.WriteLine($"ERROR: Failed to connect to server. Result: {connectResult}");
                    return;
                }

                Console.WriteLine("Connected successfully!");
                Console.WriteLine();

                // Step 2: Create registry accessor
                Console.WriteLine("Creating registry accessor...");
                GscRegistry registry = server.CreateRegistry();

                if (registry == null)
                {
                    Console.WriteLine("ERROR: Failed to create registry accessor");
                    return;
                }

                Console.WriteLine("Registry accessor created!");
                Console.WriteLine();

                // Step 3: Read entire configuration from server
                Console.WriteLine("Reading configuration from server (this may take a moment)...");

                GscRegistryReadRequest[] readRequests = new GscRegistryReadRequest[1];
                readRequests[0] = new GscRegistryReadRequest("/", 0);  // Read from root, depth=0 means all levels

                registry.ReadNodes(readRequests);

                Console.WriteLine("Configuration read successfully!");
                Console.WriteLine();

                // Step 4: Convert registry to JSON
                Console.WriteLine("Converting configuration to JSON...");
                JObject configJson = ConvertRegistryToJson(registry);

                // Step 5: Save to file
                Console.WriteLine($"Saving configuration to {outputFile}...");
                File.WriteAllText(outputFile, configJson.ToString(Formatting.Indented));

                Console.WriteLine("Configuration exported successfully!");
                Console.WriteLine();

                // Step 6: Display summary
                Console.WriteLine("Configuration Summary:");
                Console.WriteLine("=====================");
                DisplayConfigurationSummary(registry);

                Console.WriteLine();
                Console.WriteLine($"Complete! Configuration saved to: {Path.GetFullPath(outputFile)}");
                Console.WriteLine();
                Console.WriteLine("You can now:");
                Console.WriteLine("  1. View the JSON file in any text editor");
                Console.WriteLine("  2. Modify values programmatically");
                Console.WriteLine("  3. Use the SDK to write changes back to the server");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"ERROR: {ex.Message}");
                Console.WriteLine($"Stack trace: {ex.StackTrace}");
                Environment.ExitCode = 1;
            }

            Console.WriteLine();
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }

        /// <summary>
        /// Converts the GscRegistry tree to a JSON object
        /// </summary>
        static JObject ConvertRegistryToJson(GscRegistry registry)
        {
            JObject root = new JObject();

            // Get the root node
            GscRegNode rootNode = registry.FindNode("/");
            if (rootNode != null)
            {
                ConvertNodeToJson(rootNode, root);
            }

            return root;
        }

        /// <summary>
        /// Recursively converts a registry node and its children to JSON
        /// </summary>
        static void ConvertNodeToJson(GscRegNode node, JObject jsonParent)
        {
            try
            {
                // Iterate through all child nodes
                for (int i = 0; i < node.SubNodeCount; i++)
                {
                    GscRegNode childNode = node.SubNodeByIndex(i);
                    string childName = childNode.Name;

                    // Create child object
                    JObject childJson = new JObject();

                    // Try to get Name value if it exists
                    GscRegVariant nameVariant = new GscRegVariant();
                    childNode.GetValueInfoByName("Name", ref nameVariant);
                    if (nameVariant != null && nameVariant.ValueType == GscNodeType.ntWideString)
                    {
                        childJson["Name"] = nameVariant.Value.WideStringValue;
                    }

                    // Get all other values
                    // Note: We need to iterate through known value names or use a different approach
                    // For now, recursively process children
                    ConvertNodeToJson(childNode, childJson);

                    jsonParent[childName] = childJson;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Warning: Error processing node {node.Name}: {ex.Message}");
            }
        }

        /// <summary>
        /// Displays a summary of the configuration
        /// </summary>
        static void DisplayConfigurationSummary(GscRegistry registry)
        {
            try
            {
                // Display media channels
                GscRegNode channelsNode = registry.FindNode("/System/MediaChannels");
                if (channelsNode != null)
                {
                    Console.WriteLine($"  Media Channels: {channelsNode.SubNodeCount}");

                    // List first 5 channels
                    for (int i = 0; i < Math.Min(5, channelsNode.SubNodeCount); i++)
                    {
                        GscRegNode channelNode = channelsNode.SubNodeByIndex(i);

                        GscRegVariant nameVariant = new GscRegVariant();
                        GscRegVariant globalNumVariant = new GscRegVariant();

                        string name = "Unknown";
                        int globalNumber = -1;

                        channelNode.GetValueInfoByName("Name", ref nameVariant);
                        if (nameVariant != null && nameVariant.ValueType == GscNodeType.ntWideString)
                            name = nameVariant.Value.WideStringValue;

                        channelNode.GetValueInfoByName("GlobalNumber", ref globalNumVariant);
                        if (globalNumVariant != null && globalNumVariant.ValueType == GscNodeType.ntInt32)
                            globalNumber = globalNumVariant.Value.Int32Value;

                        Console.WriteLine($"    [{globalNumber}] {name}");
                    }

                    if (channelsNode.SubNodeCount > 5)
                    {
                        Console.WriteLine($"    ... and {channelsNode.SubNodeCount - 5} more");
                    }
                }

                Console.WriteLine();

                // Display users
                GscRegNode usersNode = registry.FindNode("/System/Users");
                if (usersNode != null)
                {
                    Console.WriteLine($"  Users: {usersNode.SubNodeCount}");

                    for (int i = 0; i < Math.Min(5, usersNode.SubNodeCount); i++)
                    {
                        GscRegNode userNode = usersNode.SubNodeByIndex(i);
                        GscRegVariant nameVariant = new GscRegVariant();

                        userNode.GetValueInfoByName("Name", ref nameVariant);
                        if (nameVariant != null && nameVariant.ValueType == GscNodeType.ntWideString)
                            Console.WriteLine($"    - {nameVariant.Value.WideStringValue}");
                        else
                            Console.WriteLine($"    - {userNode.Name}");
                    }

                    if (usersNode.SubNodeCount > 5)
                    {
                        Console.WriteLine($"    ... and {usersNode.SubNodeCount - 5} more");
                    }
                }
                else
                {
                    Console.WriteLine("  Users: (not found in registry)");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"  Warning: Could not display full summary: {ex.Message}");
            }
        }
    }
}
