using eSuite.WorkBench.Models;
using eSuite.WorkBench.WpfHelper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace eSuite.WorkBench.Commands
{
    public class SelectBranchVersionCommand : AsyncCommandBase
    {
        private readonly MainWindowViewModel _mainWindowViewModel;

        public SelectBranchVersionCommand(MainWindowViewModel mainWindowViewModel, Action<Exception> onException, EventHandler<FeedbackEventArgs> addFeedbackMessage) : base(onException)
        {
            FeedbackMessage += addFeedbackMessage;
            _mainWindowViewModel = mainWindowViewModel;
        }

        protected override Task ExecuteAsync(object parameter)
        {
            
            var branchVersion = parameter as Branch;
            var branchFeature = $"{branchVersion.Parent?.BranchName}-{branchVersion.BranchName}".TrimStart('-');
            DoFeedbackMessage($"Selecting {branchFeature}");

            if (branchFeature == "master")
            {
                branchFeature = string.Empty;
            }

            try
            {
                _mainWindowViewModel.AvailableProxyTags.SelectedItem = GetBestAvailableVersion(branchFeature, _mainWindowViewModel.AvailableProxyTags);
            }
            catch (Exception)
            {
                _mainWindowViewModel.AvailableProxyTags.SelectedItem = string.Empty;
            }

            try
            {
                _mainWindowViewModel.AvailableWebUiTags.SelectedItem = GetBestAvailableVersion(branchFeature, _mainWindowViewModel.AvailableWebUiTags);
            }
            catch (Exception)
            {
                _mainWindowViewModel.AvailableWebUiTags.SelectedItem = string.Empty;
            }

            try
            {
                _mainWindowViewModel.AvailableApiTags.SelectedItem = GetBestAvailableVersion(branchFeature, _mainWindowViewModel.AvailableApiTags);
            }
            catch (Exception)
            {
                _mainWindowViewModel.AvailableApiTags.SelectedItem = string.Empty;
            }

            try
            {
                _mainWindowViewModel.AvailableDbMigratorTags.SelectedItem = GetBestAvailableVersion(branchFeature, _mainWindowViewModel.AvailableDbMigratorTags);
            }
            catch (Exception)
            {
                _mainWindowViewModel.AvailableDbMigratorTags.SelectedItem = string.Empty;
            }

            try
            {
                _mainWindowViewModel.AvailableSchedulerTags.SelectedItem = GetBestAvailableVersion(branchFeature, _mainWindowViewModel.AvailableSchedulerTags);
            }
            catch (Exception)
            {
                _mainWindowViewModel.AvailableSchedulerTags.SelectedItem = string.Empty;
            }

            try
            {
                _mainWindowViewModel.AvailableMessageProcessorTags.SelectedItem = GetBestAvailableVersion(branchFeature, _mainWindowViewModel.AvailableMessageProcessorTags);
            }
            catch (Exception)
            {
                _mainWindowViewModel.AvailableMessageProcessorTags.SelectedItem = string.Empty;
            }

            DoFeedbackMessage($"{branchFeature} selected");
            return Task.CompletedTask;
        }

        private static string GetBestAvailableVersion(string branchFeature, IEnumerable<string> availableTags)
        {
            List<string> tags;
            if (branchFeature == string.Empty)
            {
                tags = availableTags.Where(x => !x.Contains("-")).ToList();
            }
            else tags = availableTags.Where(x => x.Contains(branchFeature)).ToList();
            if (!tags.Any())
            {
                tags = availableTags.Where(x => x.Contains("develop")).ToList();
            }
            
            tags.Sort((x, y) =>
            {
                var xNumbers = CalcXNumbers(x);
                var yNumbers = CalcXNumbers(y);

                if (xNumbers.Count != yNumbers.Count)
                    return string.CompareOrdinal(x, y);

                return xNumbers.Select((t, i) => t.CompareTo(yNumbers[i])).FirstOrDefault(order => order != 0);
            } );


            return tags.Last();
        }

        private static readonly Regex Regex = new(@"\d+\.\d+\.\d+.\d+");

        private static List<long> CalcXNumbers(string value)
        {
            var parts = Regex.Match(value).Value.Split('.');

            return parts.Select(part => long.Parse(part)).ToList();
        }
    }
}
