private IntermediateRegex ConstructIntermediateRegex(IEnumerable <Variable> variables, string basedPattern)
        {
            var intermediateRegex = new IntermediateRegex {
                ConcatenatedFindPattern = basedPattern,
                NumberedFindPattern     = basedPattern,
                VariableMap             = new Dictionary <string, Variable>()
            };

            foreach (var variable in variables.Where(p => !p.HasErrors && p.IsEnabled))
            {
                var idx = 0;
                while (intermediateRegex.ConcatenatedFindPattern.Contains($"#{variable.Name}#"))
                {
                    var groupName           = $"{variable.Name}{idx}";
                    var concatenatedSources = string.Join("|", variable.TranslationPairs.Where(p => !p.HasErrors).Select(p => Regex.Escape(p.Source)));
                    intermediateRegex.ConcatenatedFindPattern = intermediateRegex.ConcatenatedFindPattern.ReplaceFirst($"#{variable.Name}#", $"(?<{groupName}>{concatenatedSources})");
                    intermediateRegex.NumberedFindPattern     =
                        intermediateRegex.NumberedFindPattern.ReplaceFirst($"#{variable.Name}#", $"#{groupName}#");
                    intermediateRegex.VariableMap.Add(groupName, variable);
                    idx++;
                }
            }

            return(intermediateRegex);
        }
        private FinalRegex  ConstructFinalRegex(Regex sourceRegex, Match match, IntermediateRegex intermediateRegex)
        {
            var entireValue       = match.Value;
            var finalMatchPattern = intermediateRegex.NumberedFindPattern;
            var groupNames        = sourceRegex.GetGroupNames();
            var groups            = match.Groups;
            var diff = 0;

            for (int i = 1; i < groupNames.Length; i++)
            {
                var groupName = groupNames[i];
                var group     = groups[groupName];
                if (groupName.IsNumber())
                {
                    continue;
                }
                if (!group.Success || !intermediateRegex.VariableMap.ContainsKey(groupName))
                {
                    continue;
                }

                var variable = intermediateRegex.VariableMap[groupName];
                var pair     = variable.TranslationPairs.FirstOrDefault(x =>
                                                                        !x.HasErrors && x.Source == group.Value);
                if (pair == null)
                {
                    continue;
                }
                finalMatchPattern = finalMatchPattern.ReplaceFirst($"#{groupName}#", Regex.Escape(pair.Target));

                var beforeLen = entireValue.Length;
                entireValue = entireValue.Remove(group.Index - match.Index - diff, group.Length);
                entireValue = entireValue.Insert(group.Index - match.Index - diff, $"{pair.Target}");
                var afterLen = entireValue.Length;
                diff += beforeLen - afterLen;
            }


            return(new FinalRegex
            {
                EvaluatedFindPattern = finalMatchPattern,
                NewSourceText = entireValue
            });
        }