"use strict";
var android_device_file_system_1 = require("../../../mobile/android/android-device-file-system");
var yok_1 = require("../../../yok");
var errors_1 = require("../../../errors");
var file_system_1 = require("../../../file-system");
var logger_1 = require("../../../logger");
var mobile_helper_1 = require("../../../mobile/mobile-helper");
var device_platforms_constants_1 = require("../../../mobile/device-platforms-constants");
var Future = require("fibers/future");
var path = require("path");
var chai_1 = require("chai");
var myTestAppIdentifier = "org.nativescript.myApp";
var isAdbPushExecuted = false;
var AndroidDebugBridgeMock = (function () {
    function AndroidDebugBridgeMock() {
    }
    AndroidDebugBridgeMock.prototype.executeCommand = function (args) {
        if (args[0] === "push") {
            isAdbPushExecuted = true;
        }
        return Future.fromResult();
    };
    AndroidDebugBridgeMock.prototype.executeShellCommand = function () {
        return Future.fromResult();
    };
    return AndroidDebugBridgeMock;
})();
var LocalToDevicePathDataMock = (function () {
    function LocalToDevicePathDataMock(filePath) {
        this.filePath = filePath;
    }
    LocalToDevicePathDataMock.prototype.getLocalPath = function () {
        return this.filePath;
    };
    LocalToDevicePathDataMock.prototype.getDevicePath = function () {
        return "/data/local/tmp/" + path.basename(this.filePath);
    };
    return LocalToDevicePathDataMock;
})();
var MobilePlatformsCapabilitiesMock = (function () {
    function MobilePlatformsCapabilitiesMock() {
    }
    MobilePlatformsCapabilitiesMock.prototype.getPlatformNames = function () {
        return _.keys(this.getAllCapabilities());
    };
    MobilePlatformsCapabilitiesMock.prototype.getAllCapabilities = function () {
        return {
            iOS: {
                "wirelessDeploy": false,
                "cableDeploy": true,
                "companion": false,
                "hostPlatformsForDeploy": ["darwin"]
            },
            Android: {
                "wirelessDeploy": false,
                "cableDeploy": true,
                "companion": false,
                "hostPlatformsForDeploy": ["win32", "darwin", "linux"]
            }
        };
    };
    return MobilePlatformsCapabilitiesMock;
})();
function createTestInjector() {
    var injector = new yok_1.Yok();
    injector.register("fs", file_system_1.FileSystem);
    injector.register("logger", logger_1.Logger);
    injector.register("mobileHelper", mobile_helper_1.MobileHelper);
    injector.register("config", {});
    injector.register("options", {});
    injector.register("errors", errors_1.Errors);
    injector.register("mobilePlatformsCapabilities", MobilePlatformsCapabilitiesMock);
    injector.register("devicePlatformsConstants", device_platforms_constants_1.DevicePlatformsConstants);
    return injector;
}
function createAndroidDeviceFileSystem(injector) {
    var adb = new AndroidDebugBridgeMock();
    var androidDeviceFileSystem = injector.resolve(android_device_file_system_1.AndroidDeviceFileSystem, { "adb": adb, "identifier": myTestAppIdentifier });
    androidDeviceFileSystem.createFileOnDevice = function () { return Future.fromResult(); };
    return androidDeviceFileSystem;
}
function createDeviceAppData() {
    return { deviceProjectRootPath: "/data/local/tmp/sync", appIdentifier: myTestAppIdentifier };
}
describe("Android device file system tests", function () {
    describe("Transfer directory unit tests", function () {
        it("pushes the whole directory when hash file doesn't exist on device", function () {
            var injector = createTestInjector();
            var deviceAppData = createDeviceAppData();
            var fileToShasumDictionary = {
                "~/TestApp/app/test.js": "1",
                "~/TestApp/app/myfile.js": "2"
            };
            var localToDevicePaths = _.keys(fileToShasumDictionary).map(function (file) { return injector.resolve(LocalToDevicePathDataMock, { filePath: file }); });
            var fs = injector.resolve("fs");
            fs.getFileShasum = function (filePath) { return (function () { return fileToShasumDictionary[filePath]; }).future()(); };
            fs.exists = function (filePath) { return Future.fromResult(false); };
            fs.exists = function (filePath) { return Future.fromResult(false); };
            fs.getFsStats = function (filePath) { return Future.fromResult({
                isDirectory: function () { return false; },
                isFile: function () { return true; }
            }); };
            var androidDeviceFileSystem = createAndroidDeviceFileSystem(injector);
            androidDeviceFileSystem.transferDirectory(deviceAppData, localToDevicePaths, "~/TestApp/app").wait();
            chai_1.assert.isTrue(isAdbPushExecuted);
            isAdbPushExecuted = false;
        });
        it("pushes the whole directory when force option is specified", function () {
            var injector = createTestInjector();
            var options = injector.resolve("options");
            options.force = true;
            var fs = injector.resolve("fs");
            fs.getFileShasum = function (filePath) { return (function () { return "0"; }).future()(); };
            var androidDeviceFileSystem = createAndroidDeviceFileSystem(injector);
            androidDeviceFileSystem.transferDirectory(createDeviceAppData(), [], "~/TestApp/app").wait();
            chai_1.assert.isTrue(isAdbPushExecuted);
            isAdbPushExecuted = false;
        });
        it("pushes only changed file when hash file exists on device", function () {
            var injector = createTestInjector();
            var deviceAppData = createDeviceAppData();
            var fileToShasumDictionary = {
                "~/TestApp/app/test.js": "1",
                "~/TestApp/app/myfile.js": "2"
            };
            var localToDevicePaths = _.keys(fileToShasumDictionary).map(function (file) { return injector.resolve(LocalToDevicePathDataMock, { filePath: file }); });
            var fs = injector.resolve("fs");
            fs.getFileShasum = function (filePath) { return (function () { return fileToShasumDictionary[filePath]; }).future()(); };
            fs.exists = function (filePath) { return Future.fromResult(true); };
            fs.readJson = function (filePath) { return (function () { return ({ "~/TestApp/app/test.js": "0", "~/TestApp/app/myfile.js": "2" }); }).future()(); };
            fs.getFsStats = function (filePath) { return Future.fromResult({
                isDirectory: function () { return false; },
                isFile: function () { return true; }
            }); };
            var androidDeviceFileSystem = createAndroidDeviceFileSystem(injector);
            androidDeviceFileSystem.transferFile = function (localPath, devicePath) {
                chai_1.assert.equal(localPath, "~/TestApp/app/test.js");
                return Future.fromResult();
            };
            androidDeviceFileSystem.transferDirectory(deviceAppData, localToDevicePaths, "~/TestApp/app").wait();
        });
        it("pushes only changed files when hashes file exists on device", function () {
            var injector = createTestInjector();
            var deviceAppData = createDeviceAppData();
            var fileToShasumDictionary = {
                "~/TestApp/app/test.js": "1",
                "~/TestApp/app/myfile.js": "2",
                "~/TestApp/app/notchangedFile.js": "3"
            };
            var localToDevicePaths = _.keys(fileToShasumDictionary).map(function (file) { return injector.resolve(LocalToDevicePathDataMock, { filePath: file }); });
            var fs = injector.resolve("fs");
            fs.getFileShasum = function (filePath) { return (function () { return fileToShasumDictionary[filePath]; }).future()(); };
            fs.exists = function (filePath) { return Future.fromResult(true); };
            fs.readJson = function (filePath) { return (function () { return ({ "~/TestApp/app/test.js": "0", "~/TestApp/app/myfile.js": "4", "~/TestApp/app/notchangedFile.js": "3" }); }).future()(); };
            fs.getFsStats = function (filePath) { return Future.fromResult({
                isDirectory: function () { return false; },
                isFile: function () { return true; }
            }); };
            var androidDeviceFileSystem = createAndroidDeviceFileSystem(injector);
            var transferedFilesOnDevice = [];
            androidDeviceFileSystem.transferFile = function (localPath, devicePath) {
                transferedFilesOnDevice.push(localPath);
                return Future.fromResult();
            };
            androidDeviceFileSystem.transferDirectory(deviceAppData, localToDevicePaths, "~/TestApp/app").wait();
            chai_1.assert.equal(transferedFilesOnDevice.length, 2);
            chai_1.assert.isTrue(_.contains(transferedFilesOnDevice, "~/TestApp/app/test.js"));
            chai_1.assert.isTrue(_.contains(transferedFilesOnDevice, "~/TestApp/app/myfile.js"));
            chai_1.assert.isFalse(_.contains(transferedFilesOnDevice, "~/TestApp/app/notchangedFile.js"));
        });
        it("pushes files which has different location when hash file exists on device", function () {
            var injector = createTestInjector();
            var deviceAppData = createDeviceAppData();
            var fileToShasumDictionary = {
                "~/TestApp/app/newDir/test.js": "1",
                "~/TestApp/app/myfile.js": "2"
            };
            var localToDevicePaths = _.keys(fileToShasumDictionary).map(function (file) { return injector.resolve(LocalToDevicePathDataMock, { filePath: file }); });
            var fs = injector.resolve("fs");
            fs.getFileShasum = function (filePath) { return (function () { return fileToShasumDictionary[filePath]; }).future()(); };
            fs.exists = function (filePath) { return Future.fromResult(true); };
            fs.readJson = function (filePath) { return (function () { return ({ "~/TestApp/app/test.js": "0", "~/TestApp/app/myfile.js": "2" }); }).future()(); };
            fs.getFsStats = function (filePath) { return Future.fromResult({
                isDirectory: function () { return false; },
                isFile: function () { return true; }
            }); };
            var androidDeviceFileSystem = createAndroidDeviceFileSystem(injector);
            androidDeviceFileSystem.transferFile = function (localPath, devicePath) {
                chai_1.assert.equal(localPath, "~/TestApp/app/newDir/test.js");
                return Future.fromResult();
            };
            androidDeviceFileSystem.transferDirectory(deviceAppData, localToDevicePaths, "~/TestApp/app").wait();
        });
        it("pushes files which has different location and different shasum when hash file exists on device", function () {
            var injector = createTestInjector();
            var deviceAppData = createDeviceAppData();
            var fileToShasumDictionary = {
                "~/TestApp/app/newDir/test.js": "2",
                "~/TestApp/app/myfile.js": "2"
            };
            var localToDevicePaths = _.keys(fileToShasumDictionary).map(function (file) { return injector.resolve(LocalToDevicePathDataMock, { filePath: file }); });
            var fs = injector.resolve("fs");
            fs.getFileShasum = function (filePath) { return (function () { return fileToShasumDictionary[filePath]; }).future()(); };
            fs.exists = function (filePath) { return Future.fromResult(true); };
            fs.readJson = function (filePath) { return (function () { return ({ "~/TestApp/app/test.js": "0", "~/TestApp/app/myfile.js": "2" }); }).future()(); };
            fs.getFsStats = function (filePath) { return Future.fromResult({
                isDirectory: function () { return false; },
                isFile: function () { return true; }
            }); };
            var androidDeviceFileSystem = createAndroidDeviceFileSystem(injector);
            androidDeviceFileSystem.transferFile = function (localPath, devicePath) {
                chai_1.assert.equal(localPath, "~/TestApp/app/newDir/test.js");
                return Future.fromResult();
            };
            androidDeviceFileSystem.transferDirectory(deviceAppData, localToDevicePaths, "~/TestApp/app").wait();
        });
    });
});
