/*
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 co = require('co');
var Q = require('q');
var glob = require('glob');
var path = require('path');
var fs = require('fs');
var util = require('util');
var optimist = require('optimist');
var shelljs = require('shelljs');
var apputil = require('./apputil');
var audit_license = require('./audit-license-headers');
var update_release_notes = require('./update-release-notes');
var create_archive = require('./create-verify-archive');
var executil = require('./executil');
var flagutil = require('./flagutil');
var gitutil = require('./gitutil');
var svnutil = require('./svnutil');
var repoutil = require('./repoutil');
var versionutil = require('./versionutil');
var repoupdate = require('./repo-update');
var repoclone = require('./repo-clone');
var reporeset = require('./repo-reset');
var jira_client = require('jira-client');
var inquirer = require('inquirer');
var semver = require('semver');
var linkify = require('jira-linkify');
var print = apputil.print;

/*
 * Pseudo code for plugin automation:
 * 1. Who are you? --> this is the release manager. Can we use JIRA for this?
 */
var jira; // issues.apache.org jira client object
var you; // store label for the user here
var jira_user; // store ref to jira project user
var cordova_project; // store ref to jira project for Cordova
var plugins_release_issue; // store ref to jira issue tracking release.
var jira_issue_types; // store ref to all issue types supported by our JIRA instance
var all_plugins_component; // store the specific component associated to the plugin issue.
var jira_task_issue; // store ref to the "task" issue type
var plugin_base; // parent directory holding all cordova plugins
var plugin_repos; // which plugins are we messing with? initially gets set to all plugin repos, later on gets filtered to only those we will release. an array of objects in a special coho-accepted format.
var dist_dev_svn; // cordova dist/dev repo
var dist_svn; // cordova dist repo
var svn_repos; // cordova dist and dist/dev svn repos
var plugin_data = {}; // massive object containing plugin release-relevant information
var plugins_to_release = []; // array of plugin names that need releasing
var plugins_ommitted = []; // array of plugin names that DO NOT need releasing
var plugins_to_merge_manually = []; // array of plugin names that RM will need to merge master into release branch manually.
var svn_user; // username for apache svn
var svn_password; // password for apache svn
var updated_repos; // sentinel variable for if we did repo updates
var created_distdev_dir; // sentinel var for if a new dir was created in cordova-dist-dev

function *updateDesiredRepos(repos) {
    if (!updated_repos) {
        updated_repos = true;
        yield repoclone.cloneRepos(repos, /*silent*/true, null);
        yield reporeset.resetRepos(repos, ['master']);
        yield repoupdate.updateRepos(repos, ['master'], /*noFetch*/false);
        yield repoclone.cloneRepos(svn_repos, /*silent*/true, null);
        yield findChangesInPluginRepos(repos);
    }
}
function *findChangesInPluginRepos(repos) {
    yield repoutil.forEachRepo(repos, function*(repo) {
        if (repo.repoName == 'cordova-plugins') return;
        var last_release = (yield gitutil.findMostRecentTag())[0];
        plugin_data[repo.repoName] = {
            last_release: last_release
        };
        var changes = yield gitutil.summaryOfChanges(last_release);
        changes = changes.split('\n').filter(function(line) {
            return (line.toLowerCase().indexOf('incremented plugin version') == -1);
        });
        if (changes.length > 0) {
            plugin_data[repo.repoName].needs_release = true;
            plugin_data[repo.repoName].changes = changes.join('\n');
            plugins_to_release.push(repo.repoName);
        } else {
            plugin_data[repo.repoName].needs_release = false;
            plugins_ommitted.push(repo.repoName);
        }
    });
}

function manualPluginSelection() {
    return inquirer.prompt({
        type: 'checkbox',
        name: 'plugins_list',
        message: 'Select the plugins you want to release:',
        choices: plugin_repos.map(function(p) { return p.repoName; }).filter(function(p) { return p != 'cordova-plugins'; })
    }).then(function(answer) {
        return answer.plugins_list;
    });
}

function *interactive_plugins_release() {
    console.log('Hi! So you want to do a plugins release, do you?');
    // sanity check for tooling that will be needed during releaser.
    if (!shelljs.which('gpg')) {
        console.warn("You'll need gpg installed and have your Apache GPG keys all set up to do a plugins release!");
        console.error('I did not find gpg on your PATH!');
        console.error('Refer to ' + create_archive.GPG_DOCS + ' for instructions on how to get that set up as a first step.');
        process.exit(1);
    }
    if (!shelljs.which('svn')) {
        console.warn("You'll need svn installed to do a plugins release!");
        console.error('I did not find `svn` on your PATH!');
        process.exit(1);
    }
    return Q.fcall(function() {
        if (process.env.JIRA_USER && process.env.JIRA_PASSWORD) {
            return {
                username: process.env.JIRA_USER,
                password: process.env.JIRA_PASSWORD
            }
        } else {
            console.log('Let\'s start with your JIRA credentials - this system will be interacting with Apache\'s JIRA instance (issues.apache.org) often.');
            console.log('(Note that you can export environment variables `JIRA_USER` and `JIRA_PASSWORD` so I won\'t ask you next time.)');
            return inquirer.prompt([{
                type: 'input',
                name: 'username',
                message: 'Please enter your JIRA username'
            },{
                type: 'password',
                name: 'password',
                message: 'Please enter your JIRA password'
            }])
        }
    }).then(function(answers) {
        var username = answers.username;
        you = username;
        var password = answers.password;
        jira = new jira_client({
              protocol: 'https',
              host: 'issues.apache.org',
              base: 'jira',
              apiVersion: '2',
              strictSSL: true,
              username: username,
              password: password
        });
        return jira.getCurrentUser();
    }).then(function(user) {
        jira_user = user;
        you = user.displayName || you; // either use JIRA display name, or username
        console.log('Hey', you, '!');
        console.log('Welcome. Let me pull some data from JIRA first...');
        return jira.listProjects();
    }).then(function(projects) {
        // Find the Apache Cordova (CB) project in Apache's JIRA
        for (var i = 0; i < projects.length; i++) {
            var project = projects[i];
            if (project.key == 'CB') {
                cordova_project = project;
                break;
            }
        }
        return jira.listComponents('CB');
    }).then(function(components) {
        // Find the ALlPlugins component in Cordova'a JIRA components
        for (var i = 0; i < components.length; i++) {
            var component = components[i];
            if (component.name == 'AllPlugins') {
                all_plugins_component = component;
                break;
            }
        }
        return jira.listIssueTypes();
    }).then(function(issue_types) {
        jira_issue_types = issue_types;
        for (var i = 0; i < issue_types.length; i++) {
            var it = issue_types[i];
            if (it.name == 'Task') {
                jira_task_issue = it;
            }
        }
        /*
         * 2. Are your gpg keys in place? maybe basic validation
         */
        inquirer.prompt({
            type: 'confirm',
            name: 'gpg',
            message: 'Are your GPG keys in place?'
        }).then(function(answer) {
            if (answer.gpg) {
                console.log('Great! Let\'s keep going.');
                return inquirer.prompt({
                    type: 'confirm',
                    name: 'discuss',
                    message: 'Did you start a "[DISCUSS] Plugins release" thread on the Cordova mailing list?'
                });
            } else {
                console.error('You should get your GPG keys sorted out first!');
                console.warn('Follow the instructions here, then come back and try again: ' + create_archive.GPG_DOCS);
                process.exit(2);
            }
        }).then(function(answer) {
            /* 3. Y/N did you start a "[DISCUSS] Plugins release" thread on the mailing list?
             *   - Bonus: Can we parse the mailing list for this?
             */
            if (answer.discuss) {
                console.log('Nice! Way to keep everyone in the loop!');
                return inquirer.prompt({
                    type: 'confirm',
                    name: 'jira',
                    message: 'Is there a JIRA issue filed for the plugins release? (i.e. "Plugins Release, <recent date>") - if not, I will create one for you.'
                });
            } else {
                console.error('You definitely need to have a discussion about the plugins release on the mailing list first. Go do that!');
                process.exit(3);
            }
        }).then(function(answer) {
            /* 4. Ask for JIRA issue, or, Create JIRA issue; check docs/plugins-release-process.md for details
             *   - lets refer to this JIRA issue as $JIRA from here on out.
             *   - TODO: BONUS: COMMENT to this JIRA issue for each "top-level" step below that is completed.
             */
            if (answer.jira) {
                return inquirer.prompt({
                    type: 'input',
                    name: 'jira',
                    message: 'What is the JIRA issue number for your plugins release? Please provide only the numerical part of the issue key (i.e. CB-XXXXX)'
                }).then(function(answers) {
                    var cb_issue = 'CB-' + answers.jira;
                    console.log('Looking for ' + cb_issue + '...');
                    return jira.findIssue(cb_issue).then(function(issue) {
                        return issue;
                    }, function(err) {
                        console.error('Error finding issue ' + cb_issue + '!');
                        process.exit(4);
                    });
                });
            } else {
                console.warn('OK, no problem. I will create one for you now! Hang tight...');
                var date = (new Date()).toDateString();
                var new_issue = {
                    "fields": {
                        "project": {
                            "id": cordova_project.id
                        },
                        "summary": "Plugins Release, " + date,
                        "description": "Following steps at https://github.com/apache/cordova-coho/blob/master/docs/plugins-release-process.md\nGenerated automatically using cordova-coho.",
                        "assignee": {
                            "name": jira_user.name
                        },
                        "issuetype": {
                            "id": jira_task_issue.id
                        },
                        "components": [
                            {
                                "id": all_plugins_component.id
                            }
                        ]
                    }
                }
                return jira.addNewIssue(new_issue).then(function(issue) {
                    return issue;
                }, function(err) {
                    console.error('There was a problem creating the JIRA issue!', err);
                    process.exit(5);
                });
            }
        }).then(function(jira_issue) {
            console.log('Sweet, our Plugins Release JIRA issue is ' + jira_issue.key + ' (https://issues.apache.org/jira/browse/' + jira_issue.key + ')!');
            plugins_release_issue = jira_issue;
        }).then(function() {
            /* 5: update the repos. ask the RM if they want to create a new set of repos, or use an existing directory */
            return inquirer.prompt([{
                type: 'confirm',
                name: 'use_existing_plugins',
                message: 'Do you want to use an existing set of plugin repositories? WARNING: If no, I will ask for a directory where I will clone all the needed repositories.'
            }, {
                type: 'input',
                name: 'cwd',
                default: apputil.getBaseDir(),
                message: function(answers) {
                    if (answers.use_existing_plugins) {
                        return 'We need to update the plugin and apache SVN repositories. Enter the directory containing all of your Apache Cordova source code repositories (absolute or relative paths work here)';
                    } else {
                        return 'Please enter the directory you want to house the plugin repos we will work with. This directory will be created if it does not exist.';
                    }
                }
            }, {
                type: 'confirm',
                name: 'auto_detect',
                message: 'Do you want me to try to auto-detect which plugins could use releases? If not, you will need to manually select which plugins you want to release. WARNING: if you use auto-detection along with the "clone-all-repos" option, you will be cloning a loooooong time.'
            }, {
                type: 'confirm',
                name: 'ok',
                message: function(answers) {
                    return 'WARNING! Are you sure the following directory is where you want the plugin repositories we will be working with to be located? We will be cloning/updating repos here: ' + path.resolve(path.normalize(answers.cwd));
                }
            }]);
        }).then(function(answers) {
            if (answers.ok) {
                plugin_base = path.resolve(path.normalize(answers.cwd));
                shelljs.mkdir('-p', plugin_base);
                process.chdir(plugin_base);
                plugin_repos = flagutil.computeReposFromFlag('plugins', {includeSvn:true});
                dist_svn = flagutil.computeReposFromFlag('dist', {includeSvn:true});
                dist_dev_svn = flagutil.computeReposFromFlag('dist/dev', {includeSvn:true});
                svn_repos = dist_svn.concat(dist_dev_svn);
                dist_svn = dist_svn[0];
                dist_dev_svn = dist_dev_svn[0];
                if (answers.auto_detect) {
                    return co.wrap(function *() {
                        yield updateDesiredRepos(plugin_repos);
                        return inquirer.prompt({
                            type: 'confirm',
                            name: 'plugins_ok',
                            message: 'I\'ve detected ' + plugins_to_release.length + ' plugin' + (plugins_to_release.length==1?'':'s') + ' to release: ' + plugins_to_release.join(', ') + '\nThat means we\'re skipping ' + plugins_ommitted.length + ' plugin' + (plugins_ommitted.length==1?'':'s') + ': ' + plugins_ommitted.join(', ') + '\nDo you want to proceed with the release process around the specified plugins above (and ommitting the ones specified as well)?'
                        }).then(function(answers) {
                            if (answers.plugins_ok) {
                                return plugins_to_release;
                            } else {
                                return manualPluginSelection();
                            }
                        });
                    })();
                } else {
                    // No auto-detection, manually specified list of plugins.
                    return manualPluginSelection();
                }
            } else {
                console.warn('Womp womp, try again? Probably this flow should be better eh?');
                process.exit(6);
            }
        }).then(function(plugins_list) {
            // at this point we either have a verified, or manually-specified, list of plugins to release.
            plugins_to_release = plugins_list;
            // modify the coho-formatted list of plugin repos to filter out to only the plugins we want to release.
            plugin_repos = plugin_repos.filter(function(plugin) {
                return plugins_to_release.indexOf(plugin.repoName) > -1;
            });
            return co.wrap(function *() {
                yield updateDesiredRepos(plugin_repos);
                // and remove all the data we collected for plugins we no longer care about.
                var data_keys = Object.keys(plugin_data);
                data_keys.forEach(function(key) {
                    if (plugins_to_release.indexOf(key) == -1) {
                        delete plugin_data[key];
                    }
                });
                /* 7. ensure license headers are present everywhere.*/
                console.log('Checking license headers for specified plugin repos...');
                var unknown_licenses = [];
                yield audit_license.scrubRepos(plugin_repos, /*silent*/true, /*allowError*/false, function(repo, stdout) {
                    var unknown = stdout.split('\n').filter(function(line) {
                        return line.indexOf('Unknown Licenses') > -1;
                    })[0];
                    if (unknown[0] != '0') {
                        // There are some unknown licenses!
                        unknown_licenses.push({repo:repo.repoName,unknown:unknown});
                    }
                });
                return yield Promise.resolve(unknown_licenses);
            })();
        }).then(function(unknowns) {
            if (unknowns.length) {
                console.warn('We identified some unknown licenses in plugin repos!');
                console.warn(unknowns);
                return inquirer.prompt({
                    type: 'confirm',
                    name: 'proceed',
                    message: 'Do you want to proceed even though there are license problems?'
                }).then(function(answer) {
                    if (!answer.proceed) {
                        console.error('License audit failed - good idea to abort. Fix it up and come back!');
                        process.exit(7);
                    }
                });
            } else {
                console.log('No license issues found - continuing.');
            }
        }).then(function() {
            return inquirer.prompt({
                type: 'confirm',
                name: 'proceed',
                message: 'We are now ready to start making changes to the selected plugin repo, which will make changes to the master and release branches. Shall we proceed?'
            }).then(function(answers) {
                if (!answers.proceed) {
                    console.error('Bailing!');
                    process.exit(99);
                }
            });
        }).then(function() {
            // TODO: step 8 apparently is "rarely" done based on fil's experience running through the plugin release steps manually.
            // soooo.... what do?
            /* 8. ensure all dependencies and subdependencies have apache-compatible licenses.
             * 9. update plugin versions + release notes.
             *   - for each plugin, remove the `-dev` suffix in plugin.xml, package.json, and plugin.xml of `tests/` subdirectory (if exists)*/
            console.log('Removing the "-dev" suffix from versions in the master branch...');
            return co.wrap(function *() {
                yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                    yield gitutil.gitCheckout('master');
                    var current_version = yield versionutil.getRepoVersion(repo);
                    console.log(repo.repoName, '\'s current version is', current_version);
                    var devless_version = versionutil.removeDev(current_version);
                    plugin_data[repo.repoName].current_release = devless_version;
                    yield versionutil.updateRepoVersion(repo, devless_version, {commitChanges:false});
                });
            })();
        }).then(function() {
            /*   - each plugin may need a version bump.
             *     - how to determine if patch, minor or major? show changes to each plugin and then prompt Release Manager for a decision?
             *     - reuse coho 'update release notes' command */
            return co.wrap(function *() {
                var plugs = Object.keys(plugin_data);
                var release_note_prompts = [];
                yield plugs.map(function*(plugin) {
                    var data = plugin_data[plugin];
                    var changes = data.changes;
                    var final_notes = yield update_release_notes.createNotes(plugin, data.current_release, changes);
                    release_note_prompts.push({
                        type: 'editor',
                        name: plugin,
                        message: 'Please tweak and compile ' + plugin + ' release notes',
                        default: final_notes
                    });
                    /*     - what's the average case? just a patch bump? perhaps, for each plugin, show release notes and let RM override version beyond patch bump if RM believes it is necessary? */
                    release_note_prompts.push({
                        type: 'input',
                        name: plugin + '-version',
                        message: function(answers) {
                            var new_changes = answers[plugin];
                            var first_heading = new_changes.indexOf('###');
                            var second_heading = new_changes.indexOf('###', first_heading + 3);
                            var first_change = new_changes.indexOf('\n', first_heading + 3);
                            var len = second_heading - first_change;
                            var change_summary = new_changes.substr(first_change, len);
                            return 'Please enter a semver-compatible version number for this release of ' + plugin + ', based on the changes below:\n' + change_summary;
                        },
                        default: data.current_release,
                        validate: function(input) {
                            if (semver.valid(input)) {
                                return true;
                            } else {
                                return 'That\'s not a valid semver version!';
                            }
                        }
                    });
                });
                return inquirer.prompt(release_note_prompts);
            })();
        }).then(function(release_notes) {
            return co.wrap(function *() {
                console.log('Writing out new release notes and plugin versions (if applicable)...');
                yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                    var plugin_name = repo.repoName;
                    if (plugin_data[plugin_name].current_release != release_notes[plugin_name + '-version']) {
                        // If, after release notes review, RM decided on a different version...
                        // Overwrite plugin version
                        var previous_assumed_version = plugin_data[plugin_name].current_release;
                        plugin_data[plugin_name].current_release = release_notes[plugin_name + '-version'];
                        yield versionutil.updateRepoVersion(repo, plugin_data[plugin_name].current_release, {commitChanges:false});
                        // also overwrite the version originally specified in the release notes file, since we changed it now!
                        var rn = release_notes[plugin_name];
                        var new_rn = rn.replace(new RegExp('### ' + previous_assumed_version, 'g'), '### ' + plugin_data[plugin_name].current_release);
                        release_notes[plugin_name] = new_rn;
                    }
                    fs.writeFileSync(update_release_notes.FILE, release_notes[plugin_name], {encoding: 'utf8'});
                    /* - commit changes to versions and release notes together with description '$JIRA Updated version and release notes for release $v'
                     * - tag each plugin repo with $v*/
                    if (yield gitutil.pendingChangesExist()) {
                        yield gitutil.commitChanges(plugins_release_issue.key + ' Updated version and RELEASENOTES.md for release ' + plugin_data[plugin_name].current_release + ' (via coho)');
                        yield gitutil.tagRepo(plugin_data[plugin_name].current_release);
                    } else {
                        console.warn('No pending changes detected for ' + plugin_name + '; that\'s probably not good eh?');
                    }
                });
            })();
        }).then(function() {
            /* 10. Create release branch. Check if release branch, which would be named in the form "major.minor.x" (i.e. 2.3.x) already exists */
            return co.wrap(function *() {
                var repos_with_existing_release_branch = [];
                yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                    var plugin_name = repo.repoName;
                    var plugin_version = plugin_data[plugin_name].current_release;
                    var release_branch_name = versionutil.getReleaseBranchNameFromVersion(plugin_version);
                    if (yield gitutil.remoteBranchExists(repo, release_branch_name)) {
                        repos_with_existing_release_branch.push(repo);
                        // also store HEAD of release branch, so later on we can show a diff of the branch before pushing
                        plugin_data[plugin_name].previous_release_branch_head = gitutil.hashForRef(release_branch_name);
                        console.log('Release branch', release_branch_name, 'already exists, time to update it. We will be making changes to this existing branch.');
                        yield repoupdate.updateRepos([repo], [release_branch_name], /*noFetch*/false);
                    } else {
                        yield gitutil.createNewBranch(release_branch_name);
                        console.log('Created branch', release_branch_name, 'in repo', plugin_name);
                    }
                });
                return repos_with_existing_release_branch;
            })();
        }).then(function(repos_with_existing_release_branch) {
            // Here we are passed an array of repos that already had release branches created prior to starting the release process.
            // Our mission in this clause, should we choose to accept it, is to merge master back into the branch. But, this can be dangerous!
            // Ask the RM if they want us to handle the merge automatically.
            // If the RM says no, we will prompt them to handle it manually later.
            var prompts = [];
            repos_with_existing_release_branch.forEach(function(repo) {
                var plugin_name = repo.repoName;
                var rb = versionutil.getReleaseBranchNameFromVersion(plugin_data[plugin_name].current_release)
                prompts.push({
                    type: 'confirm',
                    name: 'rb_automerge_proceed_' + plugin_name,
                    message: plugin_name + ' already has an existing release branch "' + rb + '". Do you want me to automatically merge master into this branch for you? If no, I will prompt you to modify the release branch yourself at a later time in this session.\nWARNING: this will run `git merge master -s recursive -X theirs` from the release branch, essentially favouring master branch changes. Only proceed with the auto-merge if you understand the repercussions of doing so.'
                });
            });
            return inquirer.prompt(prompts);
        }).then(function(answers) {
            return co.wrap(function *() {
                var prompts = [];
                yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                    var plugin_name = repo.repoName;
                    if (answers['rb_automerge_proceed_' + plugin_name]) {
                        // Auto-merge master into the release branch.
                        var rb = versionutil.getReleaseBranchNameFromVersion(plugin_data[plugin_name].current_release);
                        console.log('Checking out "' + rb + '" branch of', plugin_name, 'and merging master in...');
                        yield executil.execHelper(executil.ARGS('git merge -s recursive -X theirs', 'master'), false, false, function() {
                            console.log('Merge was fine, continuing.');
                        }, function(e) {
                        //yield gitutil.merge('master', function() { console.log('merge was fine, continuing.'); }, function(e) {
                            plugins_to_merge_manually.push(plugin_name);
                        });
                    } else {
                        plugins_to_merge_manually.push(plugin_name);
                    }
                });
                return inquirer.prompt(prompts);
            })();
        }).then(function() {
            // prompt the RM about the plugins with manual merging work needed here.
            var prompts = [];
            plugins_to_merge_manually.forEach(function(plugin_name) {
                var rb = versionutil.getReleaseBranchNameFromVersion(plugin_data[plugin_name].current_release)
                prompts.push({
                    type: 'confirm',
                    name: 'rb_manualmerge_proceed_' + plugin_name,
                    message: plugin_name + ' already has an existing release branch "' + rb + '", and it needs a manual merge of master into it (either because you specified that, or because there was a merge conflict during auto-merge. Now is your chance to manually merge / cherry-pick / resolve conflicts on the "' + rb + '" branch. Once you have done this (probably in a separate shell or command prompt), hit Enter to continue.'
                });
            });
            return inquirer.prompt(prompts);
        }).then(function() {
            /* 11. Increment plugin versions back on the master branch to include -dev*/
            // Also increment the patch version
            // So, check out master branch and do the thing.
            return co.wrap(function *() {
                yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                    var plugin_name = repo.repoName;
                    var newest_version = semver.inc(plugin_data[plugin_name].current_release, 'patch') + '-dev';
                    console.log('Checking out master branch of', plugin_name, 'and setting version to', newest_version, ', then committing that change to master branch...');
                    yield gitutil.gitCheckout('master');
                    // store previous master HEAD, for later comparison/showing of diff
                    plugin_data[plugin_name].previous_master_head = gitutil.hashForRef('master');
                    yield versionutil.updateRepoVersion(repo, newest_version, {commitChanges:true});
                });
            })();
        }).then(function() {
            /* 12. Push tags, release branch, and master branch changes.
             * start with pushing tag, then compile diffs for master branch push and ask user if they approve before pushing master */
            return co.wrap(function *() {
                var master_prompts = [];
                yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                    var plugin_name = repo.repoName;
                    var tag = plugin_data[plugin_name].current_release;
                    console.log(plugin_name, ': pushing tag ', tag);
                    yield gitutil.pushToOrigin(tag);
                    /*   - show diff of last master commit for user confirmation*/
                    var diff = yield gitutil.diff(plugin_data[plugin_name].previous_master_head, 'master');
                    master_prompts.push({
                        type: 'confirm',
                        name: 'master_' + plugin_name,
                        message: 'About to push the following changes to the master branch of ' + plugin_name + ': ' + diff + '\nDo you wish to continue?'
                    });
                });
                return inquirer.prompt(master_prompts);
            })();
        }).then(function(answers) {
            /*check confirmations and exit if RM bailed*/
            return co.wrap(function *() {
                yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                    var plugin_name = repo.repoName;
                    if (!answers['master_' + plugin_name]) {
                        console.error('Aborting as master branch changes for ' + plugin_name + ' were not approved!');
                        process.exit(8);
                    }
                });
            })();
        }).then(function() {
            // at this point RM is cool pushing master branch changes up.
            return co.wrap(function *() {
                yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                    // at this point still have master branch checked out
                    yield gitutil.pushToOrigin('master');
                });
            })();
        }).then(function() {
            /*   - show diff of release branch:
            *     - if release branch did not exist before, show diff (simple, just master..branch), confirm, then push
            *     - if release branch did exist before, show diff (last branch commit..HEAD), confirm, then push*/
            return co.wrap(function *() {
                var rb_prompts = [];
                yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                    var plugin_name = repo.repoName;
                    var plugin_version = plugin_data[plugin_name].current_release;
                    var release_branch_name = versionutil.getReleaseBranchNameFromVersion(plugin_version);
                    var previous_release_branch_head = plugin_data[plugin_name].previous_release_branch_head;
                    yield gitutil.gitCheckout(release_branch_name);
                    if (previous_release_branch_head) {
                        // release branch previously existed.
                        var diff = yield gitutil.diff(previous_release_branch_head, 'HEAD');
                        rb_prompts.push({
                            type: 'confirm',
                            name: 'rb_' + plugin_name,
                            message: 'About to push the following changes to the EXISTING release branch (' + release_branch_name + ') of ' + plugin_name + ': ' + diff + '\nDo you wish to continue?'
                        });
                    } else {
                        // release branch did NOT exist previously, this is a new release branch.
                        var diff = yield gitutil.diff('master', release_branch_name);
                        rb_prompts.push({
                            type: 'confirm',
                            name: 'rb_' + plugin_name,
                            message: 'About to push the following changes (compared to master) to the NEW release branch (' + release_branch_name + ') of ' + plugin_name + ': ' + diff + '\nDo you wish to continue?'
                        });
                    }
                });
                return inquirer.prompt(rb_prompts);
            })();
        }).then(function(answers) {
            /*check confirmations and exit if RM bailed*/
            return co.wrap(function *() {
                yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                    var plugin_name = repo.repoName;
                    if (!answers['rb_' + plugin_name]) {
                        console.error('Aborting as release branch changes for ' + plugin_name + ' were not approved!');
                        process.exit(8);
                    }
                });
            })();
        }).then(function() {
            // at this point RM is cool pushing master branch changes up.
            return co.wrap(function *() {
                yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                    var plugin_name = repo.repoName;
                    var plugin_version = plugin_data[plugin_name].current_release;
                    var release_branch_name = versionutil.getReleaseBranchNameFromVersion(plugin_version);
                    // at this point have release branch checked out
                    yield gitutil.pushToOrigin(release_branch_name);
                });
            })();
        }).then(function() {
            // 13. Publish to apache svn:
            // - first update dist-dev repo
            return co.wrap(function *() {
                var orig_dir = process.cwd();
                var dist_dev_repo = path.join(plugin_base, dist_dev_svn.repoName);
                process.chdir(dist_dev_repo);
                console.log('Updating dist-dev svn repo...');
                yield svnutil.update();
                process.chdir(orig_dir);
            })();
        }).then(function() {
            //   - create-archive -r $ACTIVE --dest cordova-dist-dev/$JIRA
            return co.wrap(function *() {
                // location to store the archives in.
                var dist_dev_dir = path.join(plugin_base, dist_dev_svn.repoName, plugins_release_issue.key);
                if (!(fs.existsSync(dist_dev_dir))) {
                    shelljs.mkdir('-p', dist_dev_dir);
                    created_distdev_dir = true;
                }
                yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                    var plugin_name = repo.repoName;
                    var tag = plugin_data[plugin_name].current_release;
                    yield gitutil.gitCheckout(tag);
                    var archive = yield create_archive.createArchive(repo, tag, dist_dev_dir, true/*sign*/);
                    // - verify-archive cordova-dist-dev/$JIRA/*.tgz
                    yield create_archive.verifyArchive(archive);
                    yield gitutil.gitCheckout('master');
                });
            })();
        }).then(function() {
            if (process.env.SVN_USER && process.env.SVN_PASSWORD) {
                return {
                    username: process.env.SVN_USER,
                    password: process.env.SVN_PASSWORD
                };
            } else {
                console.log('We are about to push changes up to Apache SVN! Let me get your SVN credentials.');
                console.log('(For next time, you can export the `SVN_USER` and `SVN_PASSWORD` environment variables to skip me asking you.)');
                return inquirer.prompt([{
                    type: 'input',
                    name: 'username',
                    message: 'Please enter your svn username'
                },{
                    type: 'password',
                    name: 'password',
                    message: 'Please enter your svn password'
                }]);
            }
        }).then(function(answers) {
            svn_user = answers.username;
            svn_password = answers.password;
            //   - upload by running `svn` add and commit commands.
            return co.wrap(function *() {
                var orig_dir = process.cwd();
                var dist_dev_repo = path.join(plugin_base, dist_dev_svn.repoName);
                if (created_distdev_dir) {
                    // if we created the dir containing the archives, then we can
                    // just svn add the entire dir.
                    process.chdir(dist_dev_repo);
                    yield svnutil.add(plugins_release_issue.key);
                    yield svnutil.commit(svn_user, svn_password, plugins_release_issue.key + ': Uploading release candidates for plugins release');
                } else {
                    // if it already existed, then we need to painstakingly add
                    // each individual archive file cause svn is cool
                    var archives_for_plugins = [];
                    yield repoutil.forEachRepo(plugin_repos, function*(repo) {
                        process.chdir(dist_dev_repo);
                        var plugin_name = repo.repoName;
                        var tag = plugin_data[plugin_name].current_release;
                        var fileref = plugin_name + '-' + tag;
                        archives_for_plugins.push(fileref);
                        var files_to_add = glob.sync(path.join(plugins_release_issue.key, fileref + '*'));
                        for (var i = 0; i < files_to_add.length; i++) {
                            yield svnutil.add(files_to_add[i]);
                        }
                    });
                    process.chdir(dist_dev_repo);
                    yield svnutil.commit(svn_user, svn_password, plugins_release_issue.key + ': Uploading release candidates for plugins ' + archives_for_plugins.join(', '));
                }

                process.chdir(orig_dir);
            })();
        }).then(function() {
            console.log('Nicely done! Last few things you should do:');
            /* 14. Dump instructions only? Prepare blog post - perhaps can dump out release notes-based blog content.
             *   - TODO: this apparently ends up as a .md file in cordova-docs. perhaps can dump this as a shell of a file into the cordova-docs repo? maybe even auto-branch the docs repo in prep for a PR?*/
            console.log('1. Prepare a blog post: https://github.com/apache/cordova-coho/blob/master/docs/plugins-release-process.md#prepare-blog-post');
            console.log('2. Start a vote thread! https://github.com/apache/cordova-coho/blob/master/docs/plugins-release-process.md#start-vote-thread');
            console.log('3. You should test these plugins out! Check out cordova-mobile-spec, and in particular, the `createmobilespec` script that comes with it - it\'s a quick way to create a test project with all plugins included.');
            process.exit(0);
        });
    }, function(auth_err) {
        var keys = Object.keys(auth_err);
        console.error('ERROR! There was a problem connecting to JIRA, received a', auth_err.statusCode, 'status code.');
        process.exit(1);
    });
     /* 16. Bonus: separate script to 'approve' a plugins release, which would:
     *   - publish the artifacts to dist/ in apache
     *   - "tell apache about the release" which has a TODO to write a helper to POST the request appropriately.
     *   - publish to npm
     *   - push 'permanent release tags' (for apache) to git
     *   - issue cordova-docs blog post PR (only if we auto-branch in cordova-docs repo, as per step 14)
     *   - dump instructions only? post an ANNOUNCE thread to ML.
     *   - close $JIRA issue
     */

    /*
     * TODO: Need ability to serialize process of plugins release - save state of the process at any point.
     */
}
module.exports.interactive = interactive_plugins_release;

/*
 * A function that handles version if it is defined or undefined
 *
 * @param {String} repo                    current repo
 * @param {String|undefined} ver           current version that can be defined or undefined
 * @param {String|undefined} validate      current version that can be defined or undefined
 *
 * @return {String} version                Returns the calculated version
 *
 */

// TODO: if using this function only to retrieve repo version, use the new
// versionutil.getRepoVersion method instead.
function *handleVersion(repo, ver, validate) {
    var platform = repo.id;
    var version = ver || undefined;

    if (version === undefined) {
        yield repoutil.forEachRepo([repo], function*() {
            // Grabbing version from platformPackageJson
            var platformPackage = path.join(process.cwd(), 'package.json');
            var platformPackageJson = require(platformPackage);
            if(validate === true) {
                version = flagutil.validateVersionString(platformPackageJson.version);
            } else {
                version = platformPackageJson.version;
            }
        });
    }
    return version;
}

