using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Tellurium.MvcPages.SeleniumUtils.FileUploading.WindowsInternals;

namespace Tellurium.MvcPages.SeleniumUtils.FileUploading
{
    public static class FileUploadingExtensions
    {
        public static void UploadFileForCurrentBrowser(string filePath)
        {
            UploadFile(BrowserAdapterContext.Current.BrowserName, filePath);
        }

        public static void UploadFile(string browserName, string filePath)
        {
            var absoluteFilePath = GetAbsoluteExistingPath(filePath);
            var uploadWindow = Robot.GetUploadWindow(browserName);
            uploadWindow.Activate();
            var fileNameInput = uploadWindow.GetControls("Edit").First();
            fileNameInput.Activate();
            WindowsMethods.SendText(fileNameInput, absoluteFilePath);

            var confirmButton = uploadWindow.GetControls("Button").First();
            confirmButton.Activate();
            WindowsMethods.SendClick(confirmButton);
        }

        public static string GetAbsoluteExistingPath(string filePath)
        {
            if (filePath.Contains("\""))
            {
                var absoluteFilesPaths = filePath.Split('"')
                    .Where(x=> string.IsNullOrWhiteSpace(x) == false)
                    .Select(MapToAbsoluteFilePath)
                    .ToList();

                foreach (var path in absoluteFilesPaths)
                {
                    if (File.Exists(path) == false)
                    {
                        throw new FileUploadException($"Cannot upload file '{path}'. File does not exist.");
                    }
                }
                var quotedPaths = absoluteFilesPaths.Select(x => $"\"{x}\"");
                return string.Join(" ", quotedPaths);
            }
            var absoluteFilePath = MapToAbsoluteFilePath(filePath);

            if (File.Exists(absoluteFilePath) == false)
            {
                throw new FileUploadException($"Cannot upload file '{absoluteFilePath}'. File does not exist.");
            }
            return absoluteFilePath;
        }

        private static string MapToAbsoluteFilePath(string filePath)
        {
            return Path.IsPathRooted(filePath) ? filePath : ToAbsolutePath(filePath);
        }

        private static string ToAbsolutePath(string filePath)
        {
            if (AppDomain.CurrentDomain.SetupInformation.PrivateBinPath != null)
            {
                foreach (var rootPath in AppDomain.CurrentDomain.SetupInformation.PrivateBinPath.Split(';'))
                {
                    var absolutePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, rootPath, filePath);
                    if (File.Exists(absolutePath))
                    {
                        return absolutePath;
                    }
                }
            }
            return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, filePath);
        }

        private static string ReadFileContentFromEmbededResource(string fileName)
        {
            var assembly = Assembly.GetExecutingAssembly();
            var currentNamespace = typeof(FileUploadingExtensions).Namespace;
            using (Stream stream = assembly.GetManifestResourceStream($"{currentNamespace}.{fileName}"))
            {
                if (stream == null)
                {
                    throw new ApplicationException("Cannot load file from embeded resource");
                }
                using (StreamReader reader = new StreamReader(stream))
                {
                    return reader.ReadToEnd();
                }
            }
        }
    }
}
