/*
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 nlf = require('nlf');
var treeify = require('treeify');
var optimist = require('optimist');
var fs = require('fs');
var path = require('path');
var Q = require('q');
var flagutil = require('./flagutil');

var jsonObject = {};
var validLicenses = [];
var knownIssues = {};
var licensesFile = path.join('cordova-coho', 'src', 'validLicenses.json');
var knownIssuesFile = path.join('cordova-coho', 'src', 'knownIssues.json');
var reposWithDependencies = [];
var flagged = [];

module.exports = function * () {
    var opt = flagutil.registerRepoFlag(optimist);
    opt = flagutil.registerHelpFlag(opt);
    var argv = opt
        .usage('Go through each specified repo and check the licenses of node modules that are 3rd-party dependencies.\n\n' +
               'Usage: $0 check-license --repo=name [-r repos]')
        .argv;

    if (argv.h) {
        optimist.showHelp();
        process.exit(1);
    }
    var repos = flagutil.computeReposFromFlag(argv.r, { includeModules: true });
    checkLicense(repos);
};

function getRepoLicense (repoName) {
    return Q.nfapply(nlf.find, [{
        directory: path.join(process.cwd(), repoName)
    }
    ]).then(function (p) {
        return p;
    });
}

function checkLicense (repos) {
    // get the license info for each repo's dependencies and sub-dependencies
    var results = [];
    var previous = Q.resolve();
    repos.forEach(function (repo) {
        previous = previous.then(function () {
            var packageDir = findPackageDir(repo);
            if (packageDir) {
                reposWithDependencies.push(repo.id);
                return getRepoLicense(packageDir);
            } else {
                Q.resolve('Repo directory does not exist: ' + repos.repoName + '. First run coho repo-clone.'); // don't end execution if repo doesn't have dependencies or doesn't exist
            }
        }).then(function (data) {
            results.push(data); // push the result of this repo to the results array for later processing
        });
    });

    // process the results after the licenses for all repos have been retrieved
    previous.then(function (result) {
        processResults(results, repos);
    }, function (err) {
        console.log(err);
    });
}

function findPackageDir (repo) {
    var packageDir = repo.repoName;
    if (repo.path) {
        packageDir = path.join(packageDir, repo.path);
    }
    return fs.existsSync(path.join(packageDir, 'package.json')) ? packageDir : null;
}

// process the results of each repo
function processResults (results, repos) {
    // get valid licenses file to flag packages
    validLicenses = fs.readFileSync(licensesFile, 'utf8');
    if (!validLicenses) {
        console.log('No valid licenses file. Please make sure it exists.');
        return;
    }
    validLicenses = (JSON.parse(validLicenses)).validLicenses;

    // get known issues file to report known package issues
    knownIssues = fs.readFileSync(knownIssuesFile, 'utf8');
    if (!knownIssues) {
        console.log('No known issues file. Please make sure it exists.');
        return;
    }
    knownIssues = JSON.parse(knownIssues);

    // go through each repo, get its dependencies and add to json object
    for (var i = 0; i < results.length; ++i) {
        var repo = repos[i];
        if (reposWithDependencies.indexOf(repo.id) > -1) {
            var repoJsonObj = {};
            repoJsonObj.dependencies = getDependencies(results[i]);
            var repoIdentifier = repo.repoName;
            if (repo.path) {
                repoIdentifier += '/' + repo.path;
            }
            jsonObject[repoIdentifier] = repoJsonObj;
        }
    }

    // output results (license info for all packages + list of flagged packages)
    console.log('Below is the license info for all the packages');
    console.log(treeify.asTree(jsonObject, true));
    console.log('\n***********************************************************************************************************************');
    console.log('***********************************************************************************************************************');
    console.log('***********************************************************************************************************************\n');
    if (flagged.length) {
        for (var j = 0; j < flagged.length; ++j) {
            if (knownIssues[ flagged[j].name ]) {
                flagged[j]['known-issues'] = knownIssues[ flagged[j].name ];
            }

            console.log(treeify.asTree(flagged[j], true));
        }
        console.log(flagged.length + ' packages were flagged. Please verify manually that the licenses are valid. See those packages above, and update knownIssues.json with your findings, if applicable.');
    } else {
        console.log('No packages were flagged.');
    }
}

// get dependencies for a repo
function getDependencies (packages) {
    var dependencies = [];
    for (var j = 0; j < packages.length; ++j) {
        // pull out only relevant info and add to dependencies array
        var obj = {};
        obj.name = packages[j].name;
        obj.id = packages[j].id;
        obj.directory = [packages[j].directory];
        obj.licenses = packages[j].licenseSources.package.sources;
        dependencies.push(obj);

        // flag any packages whose licenses may not be compatible
        if (!hasValidLicense(obj)) {
            var duplicate = false;
            // avoid duplicating already flagged packages
            for (var z = 0; z < flagged.length; ++z) {
                if (flagged[z].id === obj.id) {
                    duplicate = true;
                    break;
                }
            }

            if (duplicate) {
                flagged[z].directory = flagged[z].directory.concat(obj.directory); // if it is already flagged then just add the directory to the directories array

            } else { flagged.push(JSON.parse(JSON.stringify(obj))); }
        }
    }

    return dependencies;
}

// check if package has valid licenses
function hasValidLicense (pkg) {
    var isValid = false;

    if (pkg.licenses.length === 0) { return isValid; } else {
        // go through each license of the package
        for (var x = 0; x < pkg.licenses.length; ++x) {
            isValid = false;

            // go through valid licenses and try to match with package license
            for (var y = 0; y < validLicenses.length; ++y) {
                var pattern = new RegExp(validLicenses[y], 'gi'); // construct regular expression from valid license
                if ((pkg.licenses[x].license).match(pattern)) { // match it against the package license
                    isValid = true;
                }
            }

            // shortcut - if one license isn't valid then go ahead and flag it
            if (isValid === false) { break; }
        }
    }

    return isValid;
}
