"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.joinRemote = exports.hasListener = exports.dumpListeners = exports.haveConnection = exports.checkRemotePath = exports.checkWriteObject = exports.checkWriteDir = exports.checkWriteFile = exports.checkReadDir = exports.checkReadFile = exports.checkReadObject = exports.normalizeRemotePath = exports.checkLocalPath = exports.checkLocalWriteDir = exports.checkLocalWriteFile = exports.checkLocalReadDir = exports.checkLocalReadFile = exports.localAccess = exports.classifyError = exports.localExists = exports.makeCloseListener = exports.makeEndListener = exports.makeErrorListener = exports.handleError = exports.formatError = void 0;
var fs_1 = __importDefault(require("fs"));
var path_1 = __importDefault(require("path"));
var constant_1 = require("./constant");
var types_1 = require("./types");
/**
 * Generate a new Error object with a reformatted error message which
 * is a little more informative and useful to users.
 *
 * @param {Error|string} err - The Error object the new error will be based on
 * @param {number} retryCount - For those functions which use retry. Number of
 *                              attempts to complete before giving up
 * @returns {Error} New error with custom error message
 */
function formatError(err, name, eCode, retryCount) {
    if (name === void 0) { name = 'sftp'; }
    if (eCode === void 0) { eCode = constant_1.errorCode.generic; }
    var msg = '';
    var code = '';
    var retry = retryCount
        ? " after " + retryCount + " " + (retryCount > 1 ? 'attempts' : 'attempt')
        : '';
    if (err === undefined) {
        msg = name + ": Undefined error - probably a bug!";
        code = constant_1.errorCode.generic;
    }
    else if (typeof err === 'string') {
        msg = name + ": " + err + retry;
        code = eCode;
    }
    else if (err.custom) {
        msg = name + "->" + err.message + retry;
        code = err.code;
    }
    else {
        switch (err.code) {
            case 'ENOTFOUND':
                msg =
                    name + ": " + err.level + " error. " +
                        ("Address lookup failed for host " + err.hostname + retry);
                break;
            case 'ECONNREFUSED':
                msg =
                    name + ": " + err.level + " error. Remote host at " +
                        (err.address + " refused connection" + retry);
                break;
            case 'ECONNRESET':
                msg =
                    name + ": Remote host has reset the connection: " +
                        ("" + err.message + retry);
                break;
            case 'ENOENT':
                msg = name + ": " + err.message + retry;
                break;
            default:
                msg = name + ": " + err.message + retry;
        }
        code = err.code ? err.code : eCode;
    }
    var newError = new types_1.ErrorCustom(msg);
    newError.code = code;
    newError.custom = true;
    return newError;
}
exports.formatError = formatError;
/**
 * Tests an error to see if it is one which has already been customised
 * by this module or not. If not, applies appropriate customisation.
 *
 * @param {Error} err - an Error object
 * @param {String} name - name to be used in customised error message
 * @param {Function} reject - If defined, call this function instead of
 *                            throwing the error
 * @throws {Error}
 */
function handleError(err, name, reject) {
    if (reject) {
        if (err.custom) {
            reject(err);
        }
        else {
            reject(formatError(err, name, undefined, undefined));
        }
    }
    else {
        if (err.custom) {
            throw err;
        }
        else {
            throw formatError(err, name, undefined, undefined);
        }
    }
}
exports.handleError = handleError;
/**
 * Remove all ready, error and end listeners.
 *
 * @param {Emitter} emitter - The emitter object to remove listeners from
 */
// function removeListeners(emitter) {
//   const listeners = emitter.eventNames()
//   listeners.forEach((name) => {
//     emitter.removeAllListeners(name)
//   })
// }
/**
 * Simple default error listener. Will reformat the error message and
 * throw a new error.
 *
 * @param {Error} err - source for defining new error
 * @throws {Error} Throws new error
 */
function makeErrorListener(reject, client, name) {
    return function (err) {
        client.errorHandled = true;
        reject(formatError(err, name));
    };
}
exports.makeErrorListener = makeErrorListener;
function makeEndListener(client) {
    return function () {
        if (!client.endCalled) {
            console.error('End Listener: Connection ended unexpectedly');
        }
    };
}
exports.makeEndListener = makeEndListener;
function makeCloseListener(client, reject, name) {
    return function () {
        if (!client.endCalled) {
            if (reject) {
                reject(formatError('Connection closed unexpectedly', name));
            }
            else {
                console.error('Connection closed unexpectedly');
            }
        }
        client.sftpWrapper = null;
    };
}
exports.makeCloseListener = makeCloseListener;
/**
 * @async
 *
 * Tests to see if a path identifies an existing item. Returns either
 * 'd' = directory, 'l' = sym link or '-' regular file if item exists. Returns
 * false if it does not
 *
 * @param {String} localPath
 * @returns {Boolean | String}
 */
function localExists(localPath) {
    return new Promise(function (resolve, reject) {
        fs_1.default.stat(localPath, function (err, stats) {
            if (err) {
                if (err.code === 'ENOENT') {
                    resolve('ENOENT');
                }
                else {
                    reject(err);
                }
            }
            else {
                if (stats.isDirectory()) {
                    resolve('d');
                }
                else if (stats.isSymbolicLink()) {
                    resolve('l');
                }
                else if (stats.isFile()) {
                    resolve('-');
                }
                else {
                    resolve('');
                }
            }
        });
    });
}
exports.localExists = localExists;
/**
 * Used by checkRemotePath and checkLocalPath to help ensure consistent
 * error messages.
 *
 * @param {Error} err - original error
 * @param {String} testPath - path associated with the error
 * @returns {Object} with properties of 'msg' and 'code'.
 */
function classifyError(err, testPath) {
    switch (err.code) {
        case 'EACCES':
            return {
                msg: "Permission denied: " + testPath,
                code: constant_1.errorCode.permission
            };
        case 'ENOENT':
            return {
                msg: "No such file: " + testPath,
                code: constant_1.errorCode.notexist
            };
        case 'ENOTDIR':
            return {
                msg: "Not a directory: " + testPath,
                code: constant_1.errorCode.notdir
            };
        default:
            return {
                msg: err.message,
                code: err.code ? err.code : constant_1.errorCode.generic
            };
    }
}
exports.classifyError = classifyError;
function localAccess(localPath, mode) {
    return new Promise(function (resolve) {
        fs_1.default.access(localPath, mode, function (err) {
            if (err) {
                var _a = classifyError(err, localPath), msg = _a.msg, code = _a.code;
                resolve({
                    path: localPath,
                    valid: false,
                    msg: msg,
                    code: code
                });
            }
            else {
                resolve({
                    path: localPath,
                    valid: true
                });
            }
        });
    });
}
exports.localAccess = localAccess;
function checkLocalReadFile(localPath, localType) {
    return __awaiter(this, void 0, void 0, function () {
        var rslt, access, err_1;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    _a.trys.push([0, 4, , 5]);
                    rslt = {
                        path: localPath,
                        type: localType
                    };
                    if (!(localType === 'd')) return [3 /*break*/, 1];
                    rslt.valid = false;
                    rslt.msg = "Bad path: " + localPath + " must be a file";
                    rslt.code = constant_1.errorCode.badPath;
                    return [2 /*return*/, rslt];
                case 1: return [4 /*yield*/, localAccess(localPath, fs_1.default.constants.R_OK)];
                case 2:
                    access = _a.sent();
                    if (access.valid) {
                        rslt.valid = true;
                        return [2 /*return*/, rslt];
                    }
                    else {
                        rslt.valid = false;
                        rslt.msg = access.msg;
                        rslt.code = access.code;
                        return [2 /*return*/, rslt];
                    }
                    _a.label = 3;
                case 3: return [3 /*break*/, 5];
                case 4:
                    err_1 = _a.sent();
                    throw formatError(err_1, 'checkLocalReadFile');
                case 5: return [2 /*return*/];
            }
        });
    });
}
exports.checkLocalReadFile = checkLocalReadFile;
function checkLocalReadDir(localPath, localType) {
    return __awaiter(this, void 0, void 0, function () {
        var rslt, access, err_2;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    _a.trys.push([0, 5, , 6]);
                    rslt = {
                        path: localPath,
                        type: localType
                    };
                    if (!!localType) return [3 /*break*/, 1];
                    rslt.valid = false;
                    rslt.msg = "No such directory: " + localPath;
                    rslt.code = constant_1.errorCode.notdir;
                    return [2 /*return*/, rslt];
                case 1:
                    if (!(localType !== 'd')) return [3 /*break*/, 2];
                    rslt.valid = false;
                    rslt.msg = "Bad path: " + localPath + " must be a directory";
                    rslt.code = constant_1.errorCode.badPath;
                    return [2 /*return*/, rslt];
                case 2: return [4 /*yield*/, localAccess(localPath, fs_1.default.constants.R_OK | fs_1.default.constants.X_OK)];
                case 3:
                    access = _a.sent();
                    if (!access.valid) {
                        rslt.valid = false;
                        rslt.msg = access.msg;
                        rslt.code = access.code;
                        return [2 /*return*/, rslt];
                    }
                    rslt.valid = true;
                    return [2 /*return*/, rslt];
                case 4: return [3 /*break*/, 6];
                case 5:
                    err_2 = _a.sent();
                    throw formatError(err_2, 'checkLocalReadDir');
                case 6: return [2 /*return*/];
            }
        });
    });
}
exports.checkLocalReadDir = checkLocalReadDir;
function checkLocalWriteFile(localPath, localType) {
    return __awaiter(this, void 0, void 0, function () {
        var rslt, dir, parent_1, access, err_3;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    _a.trys.push([0, 6, , 7]);
                    rslt = {
                        path: localPath,
                        type: localType
                    };
                    if (!(localType === 'd')) return [3 /*break*/, 1];
                    rslt.valid = false;
                    rslt.msg = "Bad path: " + localPath + " must be a file";
                    rslt.code = constant_1.errorCode.badPath;
                    return [2 /*return*/, rslt];
                case 1:
                    if (!!localType) return [3 /*break*/, 3];
                    dir = path_1.default.parse(localPath).dir;
                    return [4 /*yield*/, localAccess(dir, fs_1.default.constants.W_OK)];
                case 2:
                    parent_1 = _a.sent();
                    if (parent_1.valid) {
                        rslt.valid = true;
                        return [2 /*return*/, rslt];
                    }
                    else {
                        rslt.valid = false;
                        rslt.msg = parent_1.msg;
                        rslt.code = parent_1.code;
                        return [2 /*return*/, rslt];
                    }
                    return [3 /*break*/, 5];
                case 3: return [4 /*yield*/, localAccess(localPath, fs_1.default.constants.W_OK)];
                case 4:
                    access = _a.sent();
                    if (access.valid) {
                        rslt.valid = true;
                        return [2 /*return*/, rslt];
                    }
                    else {
                        rslt.valid = false;
                        rslt.msg = access.msg;
                        rslt.code = access.code;
                        return [2 /*return*/, rslt];
                    }
                    _a.label = 5;
                case 5: return [3 /*break*/, 7];
                case 6:
                    err_3 = _a.sent();
                    throw formatError(err_3, 'checkLocalWriteFile');
                case 7: return [2 /*return*/];
            }
        });
    });
}
exports.checkLocalWriteFile = checkLocalWriteFile;
function checkLocalWriteDir(localPath, localType) {
    return __awaiter(this, void 0, void 0, function () {
        var rslt, parent_2, access, access, err_4;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    _a.trys.push([0, 6, , 7]);
                    rslt = {
                        path: localPath,
                        type: localType
                    };
                    if (!!localType) return [3 /*break*/, 2];
                    parent_2 = path_1.default.parse(localPath).dir;
                    return [4 /*yield*/, localAccess(parent_2, fs_1.default.constants.W_OK)];
                case 1:
                    access = _a.sent();
                    if (access.valid) {
                        rslt.valid = true;
                        return [2 /*return*/, rslt];
                    }
                    else {
                        rslt.valid = false;
                        rslt.msg = access.msg;
                        rslt.code = access.code;
                        return [2 /*return*/, rslt];
                    }
                    return [3 /*break*/, 5];
                case 2:
                    if (!(localType !== 'd')) return [3 /*break*/, 3];
                    rslt.valid = false;
                    rslt.msg = "Bad path: " + localPath + " must be a directory";
                    rslt.code = constant_1.errorCode.badPath;
                    return [2 /*return*/, rslt];
                case 3: return [4 /*yield*/, localAccess(localPath, fs_1.default.constants.W_OK)];
                case 4:
                    access = _a.sent();
                    if (access.valid) {
                        rslt.valid = true;
                        return [2 /*return*/, rslt];
                    }
                    else {
                        rslt.valid = false;
                        rslt.msg = access.msg;
                        rslt.code = access.code;
                        return [2 /*return*/, rslt];
                    }
                    _a.label = 5;
                case 5: return [3 /*break*/, 7];
                case 6:
                    err_4 = _a.sent();
                    throw formatError(err_4, 'checkLocalWriteDir');
                case 7: return [2 /*return*/];
            }
        });
    });
}
exports.checkLocalWriteDir = checkLocalWriteDir;
function checkLocalPath(lPath, target) {
    if (target === void 0) { target = constant_1.targetType.readFile; }
    return __awaiter(this, void 0, void 0, function () {
        var localPath, type, err_5;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    _a.trys.push([0, 2, , 3]);
                    localPath = path_1.default.resolve(lPath);
                    return [4 /*yield*/, localExists(localPath)];
                case 1:
                    type = _a.sent();
                    switch (target) {
                        case constant_1.targetType.readFile:
                            return [2 /*return*/, checkLocalReadFile(localPath, type)];
                        case constant_1.targetType.readDir:
                            return [2 /*return*/, checkLocalReadDir(localPath, type)];
                        case constant_1.targetType.writeFile:
                            return [2 /*return*/, checkLocalWriteFile(localPath, type)];
                        case constant_1.targetType.writeDir:
                            return [2 /*return*/, checkLocalWriteDir(localPath, type)];
                        default:
                            return [2 /*return*/, {
                                    path: localPath,
                                    type: type,
                                    valid: true
                                }];
                    }
                    return [3 /*break*/, 3];
                case 2:
                    err_5 = _a.sent();
                    throw new Error(err_5);
                case 3: return [2 /*return*/];
            }
        });
    });
}
exports.checkLocalPath = checkLocalPath;
function normalizeRemotePath(client, aPath) {
    return __awaiter(this, void 0, void 0, function () {
        var root, root, err_6;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    _a.trys.push([0, 5, , 6]);
                    if (!aPath.startsWith('..')) return [3 /*break*/, 2];
                    return [4 /*yield*/, client.realPath('..')];
                case 1:
                    root = _a.sent();
                    return [2 /*return*/, root + client.remotePathSep + aPath.substring(3)];
                case 2:
                    if (!aPath.startsWith('.')) return [3 /*break*/, 4];
                    return [4 /*yield*/, client.realPath('.')];
                case 3:
                    root = _a.sent();
                    return [2 /*return*/, root + client.remotePathSep + aPath.substring(2)];
                case 4: return [2 /*return*/, aPath];
                case 5:
                    err_6 = _a.sent();
                    throw formatError(err_6, 'normalizeRemotePath');
                case 6: return [2 /*return*/];
            }
        });
    });
}
exports.normalizeRemotePath = normalizeRemotePath;
function checkReadObject(aPath, type) {
    return {
        path: aPath,
        type: type,
        valid: type ? true : false,
        msg: type ? undefined : "No such file " + aPath,
        code: type ? undefined : constant_1.errorCode.notexist
    };
}
exports.checkReadObject = checkReadObject;
function checkReadFile(aPath, type) {
    if (!type) {
        return {
            path: aPath,
            type: type,
            valid: false,
            msg: "No such file: " + aPath,
            code: constant_1.errorCode.notexist
        };
    }
    else if (type === 'd') {
        return {
            path: aPath,
            type: type,
            valid: false,
            msg: "Bad path: " + aPath + " must be a file",
            code: constant_1.errorCode.badPath
        };
    }
    return {
        path: aPath,
        type: type,
        valid: true
    };
}
exports.checkReadFile = checkReadFile;
function checkReadDir(aPath, type) {
    if (!type) {
        return {
            path: aPath,
            type: type,
            valid: false,
            msg: "No such directory: " + aPath,
            code: constant_1.errorCode.notdir
        };
    }
    else if (type !== 'd') {
        return {
            path: aPath,
            type: type,
            valid: false,
            msg: "Bad path: " + aPath + " must be a directory",
            code: constant_1.errorCode.badPath
        };
    }
    return {
        path: aPath,
        type: type,
        valid: true
    };
}
exports.checkReadDir = checkReadDir;
function checkWriteFile(client, aPath, type) {
    return __awaiter(this, void 0, void 0, function () {
        var _a, root, dir, parentType;
        return __generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    if (!(type && type === 'd')) return [3 /*break*/, 1];
                    return [2 /*return*/, {
                            path: aPath,
                            type: type,
                            valid: false,
                            msg: "Bad path: " + aPath + " must be a regular file",
                            code: constant_1.errorCode.badPath
                        }];
                case 1:
                    if (!!type) return [3 /*break*/, 3];
                    _a = path_1.default.parse(aPath), root = _a.root, dir = _a.dir;
                    // let parentDir = path.parse(aPath).dir;
                    if (!dir) {
                        return [2 /*return*/, {
                                path: aPath,
                                type: false,
                                valid: false,
                                msg: "Bad path: " + aPath + " cannot determine parent directory",
                                code: constant_1.errorCode.badPath
                            }];
                    }
                    if (root === dir) {
                        return [2 /*return*/, {
                                path: aPath,
                                type: type,
                                valid: true
                            }];
                    }
                    return [4 /*yield*/, client.exists(dir)];
                case 2:
                    parentType = _b.sent();
                    if (!parentType) {
                        return [2 /*return*/, {
                                path: aPath,
                                type: type,
                                valid: false,
                                msg: "Bad path: " + dir + " parent not exist",
                                code: constant_1.errorCode.badPath
                            }];
                    }
                    else if (parentType !== 'd') {
                        return [2 /*return*/, {
                                path: aPath,
                                type: type,
                                valid: false,
                                msg: "Bad path: " + dir + " must be a directory",
                                code: constant_1.errorCode.badPath
                            }];
                    }
                    return [2 /*return*/, {
                            path: aPath,
                            type: type,
                            valid: true
                        }];
                case 3: return [2 /*return*/, {
                        path: aPath,
                        type: type,
                        valid: true
                    }];
            }
        });
    });
}
exports.checkWriteFile = checkWriteFile;
function checkWriteDir(client, aPath, type) {
    return __awaiter(this, void 0, void 0, function () {
        var _a, root, dir, parentType;
        return __generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    if (!(type && type !== 'd')) return [3 /*break*/, 1];
                    return [2 /*return*/, {
                            path: aPath,
                            type: type,
                            valid: false,
                            msg: "Bad path: " + aPath + " must be a directory",
                            code: constant_1.errorCode.badPath
                        }];
                case 1:
                    if (!!type) return [3 /*break*/, 3];
                    _a = path_1.default.parse(aPath), root = _a.root, dir = _a.dir;
                    if (root === dir) {
                        return [2 /*return*/, {
                                path: aPath,
                                type: type,
                                valid: true
                            }];
                    }
                    if (!dir) {
                        return [2 /*return*/, {
                                path: aPath,
                                type: false,
                                valid: false,
                                msg: "Bad path: " + aPath + " cannot determine directory parent",
                                code: constant_1.errorCode.badPath
                            }];
                    }
                    return [4 /*yield*/, client.exists(dir)];
                case 2:
                    parentType = _b.sent();
                    if (parentType && parentType !== 'd') {
                        return [2 /*return*/, {
                                path: aPath,
                                type: type,
                                valid: false,
                                msg: 'Bad path: Parent Directory must be a directory',
                                code: constant_1.errorCode.badPath
                            }];
                    }
                    _b.label = 3;
                case 3: 
                // don't care if parent does not exist as it might be created
                // via recursive call to mkdir.
                return [2 /*return*/, {
                        path: aPath,
                        type: type,
                        valid: true
                    }];
            }
        });
    });
}
exports.checkWriteDir = checkWriteDir;
function checkWriteObject(aPath, type) {
    // for writeObj, not much error checking we can do
    // Just return path, type and valid indicator
    return {
        path: aPath,
        type: type,
        valid: true
    };
}
exports.checkWriteObject = checkWriteObject;
function checkRemotePath(client, rPath, target) {
    if (target === void 0) { target = constant_1.targetType.readFile; }
    return __awaiter(this, void 0, void 0, function () {
        var aPath, type;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, normalizeRemotePath(client, rPath)];
                case 1:
                    aPath = _a.sent();
                    return [4 /*yield*/, client.exists(aPath)];
                case 2:
                    type = _a.sent();
                    switch (target) {
                        case constant_1.targetType.readObj:
                            return [2 /*return*/, checkReadObject(aPath, type)];
                        case constant_1.targetType.readFile:
                            return [2 /*return*/, checkReadFile(aPath, type)];
                        case constant_1.targetType.readDir:
                            return [2 /*return*/, checkReadDir(aPath, type)];
                        case constant_1.targetType.writeFile:
                            return [2 /*return*/, checkWriteFile(client, aPath, type)];
                        case constant_1.targetType.writeDir:
                            return [2 /*return*/, checkWriteDir(client, aPath, type)];
                        case constant_1.targetType.writeObj:
                            return [2 /*return*/, checkWriteObject(aPath, type)];
                        default:
                            throw formatError("Unknown target type: " + target, 'checkRemotePath', constant_1.errorCode.generic);
                    }
                    return [2 /*return*/];
            }
        });
    });
}
exports.checkRemotePath = checkRemotePath;
/**
 * Check to see if there is an active sftp connection
 *
 * @param {Object} client - current sftp object
 * @param {String} name - name given to this connection
 * @param {Function} reject - if defined, call this rather than throw
 *                            an error
 * @returns {Boolean} True if connection OK
 * @throws {Error}
 */
function haveConnection(client, name, reject) {
    if (!client.sftpWrapper) {
        var newError = formatError('No SFTP connection available', name, constant_1.errorCode.connect);
        if (reject) {
            reject(newError);
            return false;
        }
        else {
            throw newError;
        }
    }
    return true;
}
exports.haveConnection = haveConnection;
function dumpListeners(emitter) {
    var eventNames = emitter.eventNames();
    if (eventNames.length) {
        console.log('Listener Data');
        eventNames.map(function (n) {
            var listeners = emitter.listeners(n);
            console.log(n + ": " + emitter.listenerCount(n));
            console.dir(listeners);
            listeners.map(function (l) {
                console.log("listener name = " + l.name);
            });
        });
    }
}
exports.dumpListeners = dumpListeners;
function hasListener(emitter, eventName, listenerName) {
    var listeners = emitter.listeners(eventName);
    var matches = listeners.filter(function (l) { return l.name === listenerName; });
    return matches.length === 0 ? false : true;
}
exports.hasListener = hasListener;
function joinRemote(client) {
    var _a, _b;
    var args = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        args[_i - 1] = arguments[_i];
    }
    if (client.remotePathSep === path_1.default.win32.sep) {
        return (_a = path_1.default.win32).join.apply(_a, args);
    }
    return (_b = path_1.default.posix).join.apply(_b, args);
}
exports.joinRemote = joinRemote;
