/*
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 optimist = require('optimist');
var apputil = require('./apputil');
var executil = require('./executil');
var flagutil = require('./flagutil');
var gitutil = require('./gitutil');
var repoutil = require('./repoutil');
var repoupdate = require('./repo-update');
var print = apputil.print;

module.exports = function * (_argv) {
    var opt = flagutil.registerRepoFlag(optimist);
    opt = optimist
        .options('b', {
            alias: 'branch',
            desc: 'The name of the branch to reset. Can be specified multiple times to specify multiple branches.',
            default: 'master'
        });
    opt = flagutil.registerHelpFlag(opt);
    var argv = opt
        .usage('Resets repository branches to match their upstream state.\n' +
               'Performs the following commands on each:\n' +
               '    git commit                             (commit any pending changes)\n' +
               '    git reset --hard origin/$BRANCH_NAME   (revert un-pushed commits)\n' +
               '    if ($BRANCH_NAME exists only locally) then\n' +
               '        git branch -D $BRANCH_NAME\n' +
               '\n' +
               'Usage: $0 repo-reset -r auto -b master -b 2.9.x')
        .argv;

    if (argv.h) {
        optimist.showHelp();
        process.exit(1);
    }
    if (argv.r === 'auto') {
        apputil.fatal('"-r auto" is not allowed for repo-reset. Please enumerate repos explicitly');
    }
    var branches = Array.isArray(argv.b) ? argv.b : [argv.b];
    var repos = flagutil.computeReposFromFlag(argv.r);
    yield module.exports.resetRepos(repos, branches);
};

module.exports.resetRepos = function * (repos, branches) {
    yield repoutil.forEachRepo(repos, function * (repo) {
        // Determine remote name.
        yield repoupdate.updateRepos([repo], [], true);
        var branchName = yield gitutil.retrieveCurrentBranchName();
        if (branches.indexOf(branchName) === -1) {
            yield gitutil.stashAndPop(repo, function * () {
                yield cleanRepo(repo, branches);
            });
        } else {
            yield cleanRepo(repo, branches);
        }
    });
};

function * cleanRepo (repo, branches) {
    for (var i = 0; i < branches.length; ++i) {
        var branchName = branches[i];
        if (!(yield gitutil.localBranchExists(branchName))) {
            continue;
        }
        // Commit local changes so that they can be restored if this was a mistake.
        if (yield gitutil.pendingChangesExist()) {
            print('Committing changes just in case resetting was a mistake.');
            yield executil.execHelper(executil.ARGS('git add --all .'));
            yield executil.execHelper(executil.ARGS('git commit -m', 'Automatically committed by coho repo-reset'));
        }

        if (yield gitutil.remoteBranchExists(repo, branchName)) {
            yield gitutil.gitCheckout(branchName);
            var changes = yield executil.execHelper(executil.ARGS('git log --oneline ' + repo.remoteName + '/' + branchName + '..' + branchName));
            if (changes) {
                print(repo.repoName + ' on branch ' + branchName + ': Local commits exist. Resetting.');
                yield executil.execHelper(executil.ARGS('git reset --hard ' + repo.remoteName + '/' + branchName));
            } else {
                print(repo.repoName + ' on branch ' + branchName + ': No local commits to reset.');
            }
        } else {
            if ((yield gitutil.retrieveCurrentBranchName()) === branchName) {
                yield gitutil.gitCheckout('master');
            }
            print(repo.repoName + ' deleting local-only branch ' + branchName + '.');
            yield executil.execHelper(executil.ARGS('git log --oneline -3 ' + branchName));
            yield executil.execHelper(executil.ARGS('git branch -D ' + branchName));
        }
    }
}
