//  
//   Rebex Sample Code License
// 
//   Copyright 2025, REBEX CR s.r.o.
//   All rights reserved.
//   https://www.rebex.net/
// 
//   Permission to use, copy, modify, and/or distribute this software for any
//   purpose with or without fee is hereby granted.
// 
//   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//   OTHER DEALINGS IN THE SOFTWARE.
// 

using System;
using System.IO;
using Rebex;
using Rebex.Net;
using Rebex.Net.Servers;
using Rebex.IO.FileSystem;

namespace Rebex.Samples
{
    public static class Program
    {
        /// <summary>
        /// The main entry point for the SFTP/SSH server application.
        /// </summary>
        public static void Main()
        {
            // set the trial license key
            Rebex.Licensing.Key = Rebex.Samples.TrialKey.Key;


            // port to listen at
            int port = 8022;

            // server's private key
            SshPrivateKey key = ServerKey.GetServerPrivateKey();

            // set up a user with one of several file system providers
            var user01 = new FileServerUser("user01", "password");
            FileSystemProvider fileSystemProvider = GetFileSystemProvider();
            if (fileSystemProvider == null)
            {
                Console.Write("No provider selected. Ending.");
                return;
            }
            user01.SetFileSystem(fileSystemProvider);

            // create a server instance
            var server = new FileServer();

            // bind SFTP/SSH and SSH shell to port 8022
            server.Bind(port, FileServerProtocol.Sftp);
            server.Bind(port, FileServerProtocol.Shell);

            // add server key
            server.Keys.Add(key);

            // add a user
            server.Users.Add(user01);

            // use console log writer
            server.LogWriter = new ConsoleLogWriter(LogLevel.Info);

            // start server in the background
            server.Start();

            // run the server
            Console.WriteLine("Server is listening at port {0}", port);
            Console.WriteLine("Press 'Enter' to stop.");
            Console.ReadLine();

            // stop the server
            server.Stop();
            Console.WriteLine("Server has been stopped.");
        }

        private static FileSystemProvider GetFileSystemProvider()
        {
            bool windows = (Environment.OSVersion.Platform == PlatformID.Win32NT);

            Console.WriteLine("Select the file system provider to use:");
            Console.WriteLine(" 1. LocalFileSystemProvider (configured to access current user's home folder)");
            Console.WriteLine(" 2. DriveFileSystemProvider with MountCapableFilesystemProvider (configured to access all system drives)");
            Console.WriteLine(" 3. MemoryFileSystemProvider (temporary memory-based file system)");

            if (windows)
            {
                Console.WriteLine(" 4. RegistryFileSystemProvider (system registry as file system)");
            }

            ConsoleKeyInfo keyInfo = Console.ReadKey();
            Console.WriteLine();

            switch (keyInfo.KeyChar)
            {
                case '1':
                    // use the built-in LocalFileSystemProvider to access the user's profile directory
                    // (of course, any other directory could be used instead)

                    string localPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
                    return new LocalFileSystemProvider(localPath);

                case '2':
                    // create a custom DriveFileSystemProvider for each drive on the local computer,
                    // and use the built-in MountCapableFileSystemProvider to make all of those drives accessible
                    // (MountCapableFileSystemProvider accepts any other provider as well)

                    var virtualFileSystemProvider = new MountCapableFileSystemProvider();
                    if (windows)
                    {
                        foreach (DriveInfo drive in DriveInfo.GetDrives())
                        {
                            var fs = new DriveFileSystemProvider(drive);
                            string name = drive.Name.TrimEnd(':', '\\', '/');
                            virtualFileSystemProvider.Mount(name, fs);
                        }
                    }
                    else
                    {
                        var fs = new DriveFileSystemProvider(new DriveInfo("/"));
                        virtualFileSystemProvider.Mount("root", fs);
                    }
                    return virtualFileSystemProvider;

                case '3':
                    // use the built-in MemoryFileSystemProvider to present a memory-based virtual file system
                    return new MemoryFileSystemProvider();

                case '4':
                    if (windows)
                    {
                        // use the custom RegistryFileSystemProvider to present system's registry as a virtual file system
                        return new RegistryFileSystemProvider();
                    }

                    // registry is only available in Windows
                    goto default;

                default:
                    return null;
            }

        }
    }
}
