// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

'use strict';

module.exports = (function () {

    var fs = require('fs');
    var path = require('path');

    function stripFrontMatter (text) {

        // get and replace front matter if it's there
        // NOTE:
        //      String.replace() replaces only the first occurrence
        //      of a string, which is what we want
        var rawFrontMatterString = getRawFrontMatterString(text);
        if (rawFrontMatterString !== null) {
            return text.replace(rawFrontMatterString, '');
        }

        return text;
    }

    function getFrontMatterString (text) {
        var rawFrontMatterString = getRawFrontMatterString(text);
        if (rawFrontMatterString !== null) {

            // strip out front matter markers
            var frontMatterString = rawFrontMatterString.replace(/^---\s*$/gm, '');
            return frontMatterString;
        }

        return null;
    }

    function setFrontMatterString (text, frontMatterString) {
        var textOnly = stripFrontMatter(text);
        var newText = '---\n' + frontMatterString + '---\n\n' + textOnly;
        return newText;
    }

    function getRawFrontMatterString (text) {
        // NOTE:
        //      [\s\S]  matches all characters
        //      *?      non-greedy *-match
        var match = text.match(/^(---\s*\r?\n[\s\S]*?\r?\n---\s*\r?\n)[\s\S]*$/);
        if (match === null) {
            return null;
        }
        return match[1];
    }

    function listdirsSync (root) {
        return fs.readdirSync(root).filter(function (fileName) {
            return fs.statSync(path.join(root, fileName)).isDirectory();
        });
    }

    function tocfileName (language, version, suffix) {
        var versionSlug = version.replace(/\./g, '-');
        if (suffix) {
            suffix = '-' + suffix;
        } else {
            suffix = '';
        }
        return language + '_' + versionSlug + suffix + '.yml';
    }

    function srcTocfileName (language, version) {
        return tocfileName(language, version, 'src');
    }

    function genTocfileName (language, version) {
        return tocfileName(language, version, 'gen');
    }

    function mergeObjects (a, b) {
        var c = {};

        // NOTE: b's properties override a's properties
        Object.keys(a).forEach(function (key) {
            c[key] = a[key];
        });
        Object.keys(b).forEach(function (key) {
            c[key] = b[key];
        });
        return c;
    }

    function generatedBy (scriptName) {
        return '# WARNING: This file is generated by ' + path.basename(scriptName);
    }

    return {
        stripFrontMatter: stripFrontMatter,
        getFrontMatterString: getFrontMatterString,
        setFrontMatterString: setFrontMatterString,
        getRawFrontMatterString: getRawFrontMatterString,
        listdirsSync: listdirsSync,
        tocfileName: tocfileName,
        srcTocfileName: srcTocfileName,
        genTocfileName: genTocfileName,
        mergeObjects: mergeObjects,
        generatedBy: generatedBy
    };
})();
