using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;

namespace Katteker.Changelog
{
    public class ChangelogFile
    {
        private ChangelogFile(string content, ChangelogFileType changelogFileType)
        {
            Content = content;
            ChangelogFileType = changelogFileType;
        }

        public string Content { get; }
        public ChangelogFileType ChangelogFileType { get; }

        /// <summary>
        /// Load changelog from Web or use the local file, if it fails.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public static async Task<ChangelogFile?> LoadChangelogAsync(string? filename, string? path)
        {
            if (filename is null || string.IsNullOrWhiteSpace(filename)) return null;
            if (path is null || string.IsNullOrWhiteSpace(path)) return null;

            if (!path.EndsWith("/", StringComparison.Ordinal))
                path += "/";
            return await ReadFromRemoteFile(path + filename) ?? ReadFromLocalFile(filename);
        }

        private static async Task<ChangelogFile?> ReadFromRemoteFile(string path)
        {
            var webReq = WebRequest.Create(path);
            try
            {
                using var response = await webReq.GetResponseAsync().ConfigureAwait(false);
                var responseStream = response.GetResponseStream();
                if (responseStream is null) return null;
                using var sr = new StreamReader(responseStream);
                return new ChangelogFile(await sr.ReadToEndAsync().ConfigureAwait(false),
                    EvaluateFileType(path));
            }
            catch
            {
                // ignore
            }

            return null;
        }

        private static ChangelogFile? ReadFromLocalFile(string? path)
        {
            try
            {
                var changelogFilename = Path.GetFileName(path);
                if (changelogFilename is null) return null;

                var currentChangelogPath = Path.Combine(Environment.CurrentDirectory, changelogFilename);
                if (File.Exists(currentChangelogPath) && !(path is null))
                {
                    return new ChangelogFile(File.ReadAllText(currentChangelogPath), EvaluateFileType(path));
                }
            }
            catch
            {
                // ignore
            }

            return null;
        }

        /// <summary>
        /// Get FileType from path
        /// </summary>
        private static ChangelogFileType EvaluateFileType(string path)
        {
            var extension = Path.GetExtension(path);
            return extension switch
            {
                ".txt" => ChangelogFileType.TextFile,
                ".md" => ChangelogFileType.MarkdownFile,
                _ => ChangelogFileType.Unknown
            };
        }
    }
}