/**
 * Cut external symbolic links and replace them with file copy.
 * @function ci.worker.cutAndReplaceLinks
 * @param {object} config - Task configuration
 * @param {string} config.basedir - Base directory name.
 * @param {function} callback - Callback when done.
 * @author Taka Okunishi
 */
var path = require('path'),
    fs = require('fs'),
    lib = require('../../lib'),
    file = lib.file,
    debug = require('./_debug');

exports = module.exports = function (config, callback) {
    var basedir = path.resolve(config.basedir, '.');
    exports._symlinksInDir(basedir, function (err, filenames) {
        if (err) {
            callback(err);
            return;
        }
        exports._replaceLinks(filenames, function (err) {
            if (!err) {
                debug('Cut and replace links in dir: %s', basedir);
            }
            callback(null);
        });
    });
};

exports._replaceLinks = function (links, callback) {
    var link = links.shift();
    if (link) {
        fs.readlink(link, function (err, src) {
            if (err) {
                callback(err);
                return;
            }
            file.forceUnlink(link, function (err) {
                if (err) {
                    callback(err);
                    return;
                }
                exports._copy(src, link, function (err) {
                    if (err) {
                        callback(err);
                        return;
                    }
                    debug.didCopyFile(src, link);
                    debug('Cut and replace link: %s', link);
                    exports._replaceLinks(links, callback);
                });
            });
        });
    } else {
        callback(null);
    }
};


exports._symlinksInDir = function (basedir, callback) {
    file.readdirRecursive(basedir, function (err, filenames) {
        if (err) {
            callback(err);
            return;
        }
        filenames = filenames
            .filter(function (filename) {
                var names = filename.split(path.sep);
                var ignoreNames = ['node_modules', '.git', 'work'];
                for (var i = 0; i < ignoreNames.length; i++) {
                    var ignoreName = ignoreNames[i],
                        hit = ~names.indexOf(ignoreName);
                    if (hit) {
                        return false;
                    }
                }
                return true;
            })
            .map(function (filename) {
                return path.resolve(basedir, filename);
            });
        exports._filterSymlinks(filenames, callback);
    });
};

exports._filterSymlinks = function (filenames, callback) {
    var filename = filenames.shift();
    if (filename) {
        exports._filterSymlinks(filenames, function (err, result) {
            if (err) {
                callback(err);
                return;
            }
            fs.lstat(filename, function (err, stats) {
                if (err) {
                    callback(err);
                    return;
                }
                if (stats.isSymbolicLink()) {
                    result.unshift(filename);
                }
                callback(null, result);
            });
        });
    } else {
        callback(null, []);
    }
};


exports._copy = function (src, dest, callback) {
    fs.exists(src, function (exits) {
        if (!exits) {
            callback(null);
        }
        fs.stat(src, function (err, stats) {
            if (err) {
                callback(err);
                return;
            }
            if (stats.isDirectory()) {
                file.copyDir(src, dest, callback);
            } else {
                file.copyFile(src, dest, callback);
            }
        });
    });
};