const jsl = require("svjsl");

const packageJSON = require("./package.json");
const { getProp } = require("./src/env");

const col = jsl.colors.fg;
const bgc = jsl.colors.bg;


/*
 * Notes:
 * - to change environment-dependent properties that use getProp(), go to './src/env.js'
 * - to change the environment, set the `NODE_ENV` environment variable (in the '.dotenv' file)
 */


const settings = {
    debug: {
        verboseLogging: false,      // set to true to enable extra debug output
        progressBarDisabled: true,  // set to true to disable the progress bar - greatly improves readability of verbose debug output
        onlyLogErrors: true,        // set to true to disable sending any console logs but error messages
    },
    info: {
        name: getProp("name"),                      // the name of JokeAPI
        desc: packageJSON.description,                  // the description of JokeAPI
        projGitHub: "https://github.com/Sv443/JokeAPI", // URL to the project's GitHub page
        version: packageJSON.version,                   // the version as a string
        versionInt: packageJSON.version.split("."),     // the version as a number array
        docsURL: getProp("baseUrl"),                    // the URL to the documentation of JokeAPI
        author: {
            name: packageJSON.author.name,   // author name
            email: packageJSON.author.email, // author email
            website: packageJSON.author.url, // author website
            github: `https://github.com/${packageJSON.author.name}`, // author github page
        },
        privacyPolicyUrl: "https://sv443.net/privacypolicy/en",
        contribGuideUrl: "https://github.com/Sv443/JokeAPI/blob/master/.github/Contributing.md",
    },
    wrapper: {
        mainFilePath: "./src/main.js",          // main script file
        skipWrapping: true,                     // whether or not to skip the wrapping through node-wrap
        wrapperSettings: {
            console: true,                      // whether Node-Wrap should log to the console
            crashTimeout: 2000,                 // timeout (in ms) until the process should be restarted after a crash
            logFile: "./data/logs/wrapper.log", // Node-Wrap log file
            logTimestamp: true,                 // whether to add a timestamp to the log
            restartOnCrash: true,               // whether to restart the process after a crash
            restartTimeout: 0,                  // timeout (in ms) until the process should be started again after a restart has been requested
        },
    },
    init: {
        initDirs: [ // directories that should be generated if they don't exist - paths relative to root of project - doesn't necessarily need trailing slash
            "./data/logs",
            "./data/submissions",
            "./docs/compiled",
            "./data/lists"
        ],
        exitSignals: [ // all signals that should cause a soft exit
            "SIGINT",
            "SIGTERM"
        ],
    },
    logging: {
        logChar: "▌",                  // character that gets logged on each request
        spacerAfter: 10,               // after how many logged requests a spacer should be put - set to 0 to disable
        disableLogging: false,         // set to true to disable logging a character on each request
        blacklistLoggingEnabled: true, // whether or not to log the character when an IP is on the blacklist
    },
    jokes: {
        jokesFormatVersion: 3,                             // current joke format version
        jokesFolderPath: "./data/jokes/",                  // path to the jokes folder - needs trailing slash
        jokeSubmissionURL: `${getProp("baseUrl")}#submit`, // joke submission url
        jokeSubmissionPath: "./data/submissions/",         // path to a directory where joke submissions should be saved to - needs trailing slash
        submissions: {
            timeFrame: 60,                              // time frame of submission rate limiter (in seconds)
            rateLimiting: 5,                            // how many requests per timeframe should be allowed
            invalidCharRegex: /(?![\u0000-\u0fff])./gm, // eslint-disable-line no-control-regex
            minLength: 2,                               // minimum amount of characters needed in joke submissions (per property)
        },
        jokesTemplateFile: "template.json",  // relative to "jokes.jokesFolderPath"
        possible: {
            anyCategoryName: "Any", // the name of the "Any" category - case insensitive / readable name
            categories: [           // all categories (excluding "Any") - case insensitive / readable name
                "Misc",
                "Programming",
                "Dark",
                "Pun",
                "Spooky",
                "Christmas"
            ],
            categoryAliases: { // aliases of categories. Alias at key gets resolved to category at value. Value has to be present in the "categories" array above - case sensitive / readable names
                "Miscellaneous": "Misc",
                "Coding": "Programming",
                "Development": "Programming",
                "Halloween": "Spooky"
            },
            flags: [ // all flags - HAVE TO BE LOWER CASE!
                "nsfw",
                "religious",
                "political",
                "racist",
                "sexist",
                "explicit",
            ],
            formats: [ // all file formats - HAVE TO BE LOWER CASE!
                "json",
                "xml",
                "yaml",
                "txt",
            ],
            types: [ // all joke types - HAVE TO BE LOWER CASE!
                "single",
                "twopart"
            ],
        },
        fileFormatsPath: "./data/fileFormats.json", // path to the file formats file
        defaultFileFormat: {
            fileFormat: "json",           // the default file format string
            mimeType: "application/json", // the default file format mime type
        },
        lastIDsMaxLength: 15,          // the maximum amount of joke IDs that get saved to the blacklist-array
        jokeRandomizationAttempts: 25, // after how many attempts of selecting a random joke to stop trying
        splitChars: [ ",", "+", "-" ], // which characters should separate the values of parameters with support for multiple values
        splitCharRegex: /[,+-]/gm,     // which characters should separate the values of parameters with support for multiple values
        maxAmount: 10,                 // the maximum amount of jokes that can be fetched with a single call to the get jokes endpoint
        encodeAmount: 5,               // if more than this number of jokes is requested, encode them
    },
    httpServer: {
        port: getProp("httpPort"), // http server port
        allowCORS: true,           // whether or not to allow Cross Origin Resource Sharing
        rateLimiting: 120,         // amount of allowed requests per below defined timeframe
        timeFrame: 60,             // timeframe in seconds
        urlPathOffset: 0,          // example: "/jokeapi/info" with an offset of 1 will only start parsing the path beginning at "info" - an Apache reverse proxy will do this automatically though
        maxPayloadSize: 5120,      // max size (in bytes) that will be accepted in a PUT request - if payload exceeds this size, it will abort with status 413
        maxUrlLength: 250,         // max amount of characters of the URL - if the URL is longer than this, the request will abort with status 414
        disableCache: true,        // whether or not to disable the cache - default: true (setting to false may prevent the users from getting new jokes)
        infoHeaders: true,         // whether or not to add an informational header about JokeAPI to each request
        reverseProxy: true,        // whether or not JokeAPI gets its requests from a reverse proxy
        startupTimeout: 30,        // in seconds, timeout after which startup fails if the HTTP server couldn't start up (blocked port, etc.)
        ipSanitization: {          // used to sanitize IP addresses so they can be used in file paths
            regex: /[^A-Za-z0-9\-_./]|^COM[0-9]([/.]|$)|^LPT[0-9]([/.]|$)|^PRN([/.]|$)|^CLOCK\$([/.]|$)|^AUX([/.]|$)|^NUL([/.]|$)|^CON([/.]|$)/gm,
            replaceChar: "#", // what character to use instead of illegal characters
        },
        ipHashing: {
            enabled: true,       // hashes all IP addresses. If set to false, JokeAPI is not GDPR compliant anymore!
            algorithm: "sha256", // the algorithm of the hash - available algorithms depend on the OpenSSL version installed on the machine (on linux can be listed with "openssl list -digest-algorithms")
            digest: "hex",       // the output format of the hash - can be "base64", "hex" or "latin1"
        },
        encodings: {
            gzip: true,    // Whether or not Gzip encoding should be enabled for the documentation page
            deflate: true, // Whether or not Deflate encoding should be enabled for the documentation page
            brotli: true,  // Whether or not Brotli encoding should be enabled for the documentation page
        },
        encodingPriority: [ // The priority of the encodings. Items with a lower array index (further to the left) have a higher priority
            "brotli", "gzip", "deflate"
        ],
    },
    errors: {
        errorLogDir: "./data/logs/",               // path to the error log directory - needs trailing slash
        errorMessagesPath: "./data/errorMessages", // path to error messages file
    },
    lists: {
        blacklistPath: "./data/lists/ipBlacklist.json",             // path to the IP blacklist
        whitelistPath: "./data/lists/ipWhitelist.json",             // path to the IP whitelist
        consoleBlacklistPath: "./data/lists/consoleBlacklist.json", // path to the IP console blacklist
    },
    documentation: {
        dirPath: "./docs/",                // path to the documentation directory - needs trailing slash
        compiledPath: "./docs/compiled/", // path to the compiled docs directory - needs trailing slash
        faviconPath: "./docs/static/favicon.ico", // path to the favicon.ico file - don't add trailing slash
        rawDirPath: "./docs/raw/",            // path to the raw documentation files directory - needs trailing slash
        daemonInterval: 2,                    // interval (in seconds) at which the daemon checks for changes in the documentation directory
        errorPagePath: "./docs/raw/errorPage.html", // path to the error page
        codeFontFileName: "static/external/CascadiaCode_2108.26.ttf", // the name of the font file that is going to be used in code blocks - relative to the directory specified with the above property "dirPath"
        submissionForm: {
            dirPath: "./docs/raw/", // path to the submission form directory - needs trailing slash
            fileNames: {
                html: "submit.html", // name of the HTML file of the submission form - relative to the parameter "documentation.submissionForm.dirPath"
                js: "../static/submit.js", // name of the JS file of the submission form - relative to the parameter "documentation.submissionForm.dirPath"
                css: "../static/submit.css", // name of the CSS file of the submission form - relative to the parameter "documentation.submissionForm.dirPath"
            },
        },
    },
    endpoints: {
        dirPath: "./endpoints/", // path to the dir containing all the endpoint scripts
        ratelimitBlacklist: [    // calling an endpoint in this array will not count towards the rate limit counter
            "static",
        ],
    },
    colors: {
        success: col.green,     // when request was successful
        error: col.red,         // when request was errored
        ratelimit: col.magenta, // when request was rate limited
        docs: col.yellow,                      // when docs were requested
        blacklisted: bgc.red + col.yellow,     // when a request IP is blacklisted
        docsrecompiled: bgc.yellow + col.blue, // when the docs were recompiled
    },
    analytics: {
        enabled: false, // whether or not the analytics module should be enabled
        dirPath: "./data/analytics/", // path to the analytics directory - needs trailing slash
        sqlTableName: "analytics",    // name of the SQL table
    },
    sql: { // (login credentials are set in the .env file)
        host: "localhost",   // IP address to the DB host - default for local device is "localhost"
        database: "jokeapi", // the name of the DB
        port: 3306,          // the port of the DB - default is 3306
    },
    auth: {
        tokenListFile: "./data/tokens.json", // path to the token list file
        tokenHeaderName: "authorization",     // the name of the token header (lower case)
        tokenValidHeader: "Token-Valid",     // the name of the token validity response header (normal case, not lower case)
        daemonInterval: 20, // after how many seconds the auth tokens should be refreshed
    },
    languages: {
        langFilePath: "./data/languages.json",        // file containing all language codes and corresponding language information
        defaultLanguage: "en",                        // default language (two character code, lowercase)
        translationsFile: "./data/translations.json", // translations file
    },
    tests: { // unit tests
        location: "./tests/",  // folder where unit tests are located - requires trailing slash
        initPingInterval: 250, // in ms - interval between init pings (default: 250)
    }
}

module.exports = Object.freeze(settings); // use Object.freeze() to prevent modifications at runtime