// 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';

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

var yaml = require('js-yaml');
var optimist = require('optimist');
var chalk = require('chalk');

var util = require('./util');

// constants
var VERBOSE_BY_DEFAULT = false;

// globals
var verbose = VERBOSE_BY_DEFAULT;

// helpers
function augmentEntry (originalEntry, prefix) {
    var augmentedEntry = {};

    // skip entries that have no URI
    if (!originalEntry.url) {
        return originalEntry;
    }

    // get the path to the file to which this entry points
    var filePath = path.join(prefix, originalEntry.url).replace('.html', '.md');

    // skip entries that don't point to a valid file
    if (!fs.existsSync(filePath)) {
        console.warn(chalk.red('WARNING! Possible 404 in ToC: "' + filePath + '"; create the file to fix'));
        return originalEntry;
    }

    // read in the referenced file and get its front matter
    var fileContents = fs.readFileSync(filePath).toString();
    var frontMatterString = util.getFrontMatterString(fileContents);
    var frontMatter = yaml.load(frontMatterString);

    augmentedEntry.name = decideOnName(originalEntry, frontMatter);
    augmentedEntry.url = originalEntry.url;

    if (frontMatter.description) {
        augmentedEntry.description = frontMatter.description;
    }

    return augmentedEntry;
}

function decideOnName (originalEntry, frontMatter) {

    // raise a warning for old-style ToC entry names
    if (originalEntry.name && verbose === true) {
        console.warn("'name' property will be ignored");
    }

    // error out if there is no name
    if (!frontMatter.toc_title && !frontMatter.title) {
        throw Error("can't find out name for ToC entry");
    }

    // use entry's name, and if it's not defined use the front matter name
    return frontMatter.toc_title || frontMatter.title;
}

// public API
function augmentToc (originalToc, prefix) {

    var augmentedToc = [];

    if (typeof prefix === 'undefined') {
        throw new Error('missing prefix for ToC');
    }

    // go through all original entries
    for (var i = 0; i < originalToc.length; i++) {
        var originalEntry = originalToc[i];
        var augmentedEntry = {};

        // recurse for entries with children, replacing their children with
        // their augmented equivalents
        if (originalEntry.children) {

            if (typeof originalEntry.name === 'undefined') {
                throw new Error('entries with children must have a name');
            }

            augmentedEntry.name = originalEntry.name;
            augmentedEntry.children = augmentToc(originalEntry.children, prefix);

        // replace regular entries with their augmented equivalents
        } else {
            augmentedEntry = augmentEntry(originalEntry, prefix);
        }

        augmentedToc.push(augmentedEntry);
    }

    return augmentedToc;
}

function augmentString (srcTocString, prefix) {
    var srcToc = yaml.load(srcTocString);
    var augmentedToc = augmentToc(srcToc, prefix);
    var augmentedTocString = yaml.dump(augmentedToc, { indent: 4 });

    return augmentedTocString;
}

function main () {

    // get args
    var argv = optimist
        .usage('Usage: $0 [options]')
        .demand('srcToc').describe('srcToc', 'the source ToC for the given directory')
        .demand('srcRoot').describe('srcRoot', 'the directory containing files described by the ToC')
        .boolean('verbose').describe('verbose', 'if true, print more helpful information').default('verbose', VERBOSE_BY_DEFAULT)
        .alias('v', 'verbose')
        .argv;

    var srcTocPath = argv.srcToc;
    var srcRootPath = argv.srcRoot;

    // set globals
    verbose = argv.verbose;

    // get augmented ToC
    var srcTocString = fs.readFileSync(srcTocPath);
    var augmentedTocString = augmentString(srcTocString, srcRootPath);

    console.log(util.generatedBy(__filename));
    console.log(augmentedTocString);
}

if (require.main === module) {
    main();
}

module.exports = {
    augmentToc: augmentToc,
    augmentString: augmentString
};