<commit_before>﻿using System;
using System.Configuration;
using System.Linq;

namespace GitHubSearch
{
    internal class Configuration : IConfiguration
    {
        private readonly Options options;

        private string _outputMode;
        private int? _surroundingLines;
        private string _githubTargetName;
        private string[] _repositoryFilters;
        private string _filenameFilter;
        private string _githubAccessToken;

        public string OutputMode => _outputMode ?? (_outputMode = options.OutputMode ?? ConfigurationManager.AppSettings["OutputMode"]);

        public int SurroundingLines => (_surroundingLines ?? (_surroundingLines = options.SurroundingLines ?? int.Parse(ConfigurationManager.AppSettings["SurroundingLines"]))).Value;

        public string GithubTargetName => _githubTargetName ?? (_githubTargetName = options.GithubTargetName ?? ConfigurationManager.AppSettings["GithubTargetName"]);

        public string[] RepositoryFilters => _repositoryFilters ?? (_repositoryFilters = GetRepositoryFilters());

        public string FilenameFilter => _filenameFilter ?? (_filenameFilter = options.FilenameFilter ?? ConfigurationManager.AppSettings["FilenameFilter"]);

        public string GithubAccessToken => _githubAccessToken ?? (_githubAccessToken = ConfigurationManager.AppSettings["GithubAccessToken"]);

        public Configuration(Options options)
        {
            this.options = options;
        }

        private string[] GetRepositoryFilters()
        {
            var repositoryFilters = options.RepositoryFilters ?? ConfigurationManager.AppSettings["RepositoryFilters"];
            return repositoryFilters.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
                .Select(x => $"^{x}$")
                .ToArray();
        }

        public void StoreAccessToken(string accessToken)
        {
            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            config.AppSettings.Settings["GithubAccessToken"].Value = accessToken;
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
        }
    }

    internal interface IConfiguration
    {
        string OutputMode { get; }
        int SurroundingLines { get; }
        string GithubTargetName { get; }
        string[] RepositoryFilters { get; }
        string FilenameFilter { get; }
        string GithubAccessToken { get; }

        void StoreAccessToken(string accessToken);<commit_msg>Store access token without loosing comments in configuration file (#4)<commit_after>﻿using System;
using System.Configuration;
using System.Drawing;
using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;

namespace GitHubSearch
{
    internal class Configuration : IConfiguration
    {
        private readonly Options options;

        private string _outputMode;
        private int? _surroundingLines;
        private string _githubTargetName;
        private string[] _repositoryFilters;
        private string _filenameFilter;
        private string _githubAccessToken;

        public string OutputMode => _outputMode ?? (_outputMode = options.OutputMode ?? ConfigurationManager.AppSettings["OutputMode"]);

        public int SurroundingLines => (_surroundingLines ?? (_surroundingLines = options.SurroundingLines ?? int.Parse(ConfigurationManager.AppSettings["SurroundingLines"]))).Value;

        public string GithubTargetName => _githubTargetName ?? (_githubTargetName = options.GithubTargetName ?? ConfigurationManager.AppSettings["GithubTargetName"]);

        public string[] RepositoryFilters => _repositoryFilters ?? (_repositoryFilters = GetRepositoryFilters());

        public string FilenameFilter => _filenameFilter ?? (_filenameFilter = options.FilenameFilter ?? ConfigurationManager.AppSettings["FilenameFilter"]);

        public string GithubAccessToken => _githubAccessToken ?? (_githubAccessToken = ConfigurationManager.AppSettings["GithubAccessToken"]);

        public Configuration(Options options)
        {
            this.options = options;
        }

        private string[] GetRepositoryFilters()
        {
            var repositoryFilters = options.RepositoryFilters ?? ConfigurationManager.AppSettings["RepositoryFilters"];
            return repositoryFilters.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
                .Select(x => $"^{x}$")
                .ToArray();
        }

        public void StoreAccessToken(string accessToken)
        {
            try
            {
                var configDoc = XDocument.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, LoadOptions.PreserveWhitespace);

                var accessTokenNode = configDoc.XPathSelectElement("//appSettings/add[@key='GithubAccessToken']");
                XAttribute xAttribute = accessTokenNode.Attribute("value");
                if (xAttribute != null)
                {
                    xAttribute.Value = accessToken;
                }
                configDoc.Save(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
            }
            catch (Exception ex)
            {
                Colorful.Console.WriteLine(" Failed to store access token in configuration file " + AppDomain.CurrentDomain.SetupInformation.ConfigurationFile, Color.Red);
                Colorful.Console.WriteLine(" " + ex.Message, Color.Red);
            }
        }
    }

    internal interface IConfiguration
    {
        string OutputMode { get; }
        int SurroundingLines { get; }
        string GithubTargetName { get; }
        string[] RepositoryFilters { get; }
        string FilenameFilter { get; }
        string GithubAccessToken { get; }

        void StoreAccessToken(string accessToken);
{'fraction_non_alphanumeric': 0.08762621940783843, 'fraction_numerical': 0.00017114495978093444, 'mean_word_length': 3.0387007601935037, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6577338', 'n_tokens_mistral': 1348, 'n_tokens_neox': 1326, 'n_words': 295}