/*
 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.
 */

var fs = require('fs');
var path = require('path');
var stream = require('stream');
var optimist = require('optimist');
var executil = require('./executil');
var flagutil = require('./flagutil');
var gitutil = require('./gitutil');
var repoutil = require('./repoutil');
var linkify = require('jira-linkify');
var co_stream = require('co-stream');

var relNotesFile = 'RELEASENOTES.md';

module.exports = function * () {
    var opt = flagutil.registerRepoFlag(optimist);
    opt = flagutil.registerHelpFlag(opt)
        .usage('Updates release notes with commits since the most recent tag.\n' +
        '\n' +
        'Usage: $0 update-release-notes [--repo=ios]'
        )
        .options('from-tag', { desc: 'Update since a specific tag instead of the "most recent" tag' })
        .options('to-tag', { desc: 'Update to a specific tag instead of "master"' })
        .options('override-date', { desc: 'Update to a specific date instead of today.' })
        .options('last-two-tags', { desc: 'Update with the latest and previous tagged commits' });
    let argv = opt.argv;

    if (argv.h) {
        optimist.showHelp();
        process.exit(1);
    }

    var repos = flagutil.computeReposFromFlag(argv.r, { includeModules: true });

    yield repoutil.forEachRepo(repos, function * (repo) {
        // TODO: we should use gitutil.summaryOfChanges here.
        var cmd = executil.ARGS('git log --topo-order --no-merges');
        cmd.push(['--pretty=format:* %s']);
        var fromTag, toTag, hasOneTag;
        hasOneTag = false;
        if (argv['last-two-tags']) {
            var last_two = (yield gitutil.findMostRecentTag(repo.versionPrefix));
            if (last_two) {
                toTag = last_two[0];
                if (last_two.length > 1) {
                    fromTag = last_two[1];
                } else {
                    hasOneTag = true;
                    fromTag = toTag;
                }
            }
        } else {

            if (argv['from-tag']) {
                fromTag = argv['from-tag'];
            } else {
                try {
                    fromTag = (yield gitutil.findMostRecentTag(repo.versionPrefix))[0];
                } catch (e) {
                    console.log(`no tags exist in ${repo.packageName}`);
                    throw 'update-release-notes will not work';
                }
            }
            if (argv['to-tag']) {
                toTag = argv['to-tag'];
            } else {
                toTag = 'master';
            }
        }

        if (!hasOneTag) {
            cmd.push(fromTag + '..' + toTag);
        }
        var repoDesc = repo.repoName;
        if (repo.path) {
            repoDesc += '/' + repo.path;
        }
        console.log('Finding commits in ' + repoDesc + ' from tag ' + fromTag + ' to tag ' + toTag);
        var output = yield executil.execHelper(cmd.concat(repoutil.getRepoIncludePath(repo)), true);
        if (output) {
            var newVersion;
            if (toTag === 'master') {
                delete require.cache[path.join(process.cwd(), 'package.json')];
                newVersion = require(path.join(process.cwd(), 'package.json')).version;
            } else {
                newVersion = toTag;
            }
            var final_notes = yield createNotes(repo, newVersion, output, argv['override-date']);
            fs.writeFileSync(relNotesFile, final_notes, { encoding: 'utf8' });
            return linkify.file(relNotesFile);
        }
    });
};

function backtick (text, token) {
    return text.replace(new RegExp(' ' + token, 'gi'), ' `' + token + '`');
}

function bold (text, token) {
    return text.replace(new RegExp(' ' + token, 'gi'), ' **' + token + '**');
}

var GITHUB_CLOSE_COMMIT_MSG = /^\*\s+Closes?\s+\#\d+$/gi; // eslint-disable-line no-useless-escape
var VIA_COHO_COMMIT_MSG = /\(via coho\)/gi;

function * createNotes (repo, newVersion, changes, overrideDate) {
    // pump changes through JIRA linkifier first through a stream pipe
    var transformer = linkify.stream('CB');
    var read = new stream.Readable();
    read._read = function () {};// noop
    read.push(changes);
    read.push(null);
    var write = new stream.Writable();
    var data = '';
    write._write = function (chunk, encoding, done) {
        data += chunk.toString();
        done();
    };
    read.pipe(transformer).pipe(write);
    yield co_stream.wait(write); // wait for the writable stream to finish/end
    // remove any commit logs in the form "Close #xxx", used for closing github pull requests.
    var lines = data.split('\n');
    data = lines.filter(function (line) {
        return !(
            line.match(GITHUB_CLOSE_COMMIT_MSG) ||
           line.match(VIA_COHO_COMMIT_MSG)
        );
    }).join('\n');

    // some more release note linting: enclose in backticks certain tokens
    ['plugin.xml', 'package.json', 'config.xml', 'README', 'InAppBrowser'].forEach(function (token) {
        data = backtick(data, token);
    });
    flagutil.computeReposFromFlag('platforms').map(function (r) { return r.repoName; }).forEach(function (platform_name) {
        data = backtick(data, platform_name);
    });
    // bold platform labels (with optional version numbers, too)
    var version_labels = [];
    repoutil.repoGroups.platforms.filter(function (p) {
        // first only pull out the platform repos that we have explicitly labeled with nice version strings
        return p.versions && p.versions.length;
    }).forEach(function (p) {
        // next, generate the labels for later tokenization
        p.versions.forEach(function (v) {
            version_labels.push(p.title + ' ' + v);
        });
    });
    version_labels.forEach(function (label) {
        data = bold(data, label);
    });
    repoutil.repoGroups.platforms.map(function (r) { return r.title; }).forEach(function (platform) {
        data = bold(data, platform);
    });
    // then interpolate linkified changes into existing release notes and compose the final release notes string
    var relNotesData;
    // if being run in cordova directy, cd into repo
    if (path.basename(process.cwd()) === 'cordova') {
        relNotesData = fs.readFileSync(path.join(process.cwd(), repo, relNotesFile), { encoding: 'utf8' });
    } else {
        // being run in repo directory (Eg cordova/cordova-plugin-device)
        relNotesData = fs.readFileSync(path.join(process.cwd(), relNotesFile), { encoding: 'utf8' });
    }
    var headerPos = relNotesData.indexOf('### ');
    var date;
    if (overrideDate) {
        date = new Date(overrideDate).toDateString().split(' ');
    } else {
        date = new Date().toDateString().split(' ');
    }
    return relNotesData.substr(0, headerPos) + '### ' + newVersion + ' (' + date[1] + ' ' + date[2] + ', ' + date[3] + ')\n' + data + '\n\n' + relNotesData.substr(headerPos);
}

module.exports.createNotes = createNotes;
module.exports.FILE = relNotesFile;
