"use strict";
const minimatch = require("minimatch");
const path = require("path");
const util = require("util");
class ProjectFilesManager {
    constructor($fs, $localToDevicePathDataFactory, $logger, $mobileHelper, $projectFilesProvider) {
        this.$fs = $fs;
        this.$localToDevicePathDataFactory = $localToDevicePathDataFactory;
        this.$logger = $logger;
        this.$mobileHelper = $mobileHelper;
        this.$projectFilesProvider = $projectFilesProvider;
    }
    getProjectFiles(projectFilesPath, excludedProjectDirsAndFiles, filter, opts) {
        let projectFiles = this.$fs.enumerateFilesInDirectorySync(projectFilesPath, (filePath, stat) => {
            let isFileExcluded = this.isFileExcluded(path.relative(projectFilesPath, filePath));
            let isFileFiltered = filter ? filter(filePath, stat).wait() : false;
            return !isFileExcluded && !isFileFiltered;
        }, opts);
        this.$logger.trace("enumerateProjectFiles: %s", util.inspect(projectFiles));
        return projectFiles;
    }
    isFileExcluded(filePath, excludedProjectDirsAndFiles) {
        let isInExcludedList = !!_.find(excludedProjectDirsAndFiles, (pattern) => minimatch(filePath, pattern, { nocase: true }));
        return isInExcludedList || this.$projectFilesProvider.isFileExcluded(filePath);
    }
    createLocalToDevicePaths(deviceAppData, projectFilesPath, files, excludedProjectDirsAndFiles, projectFilesConfig) {
        files = files || this.getProjectFiles(projectFilesPath, excludedProjectDirsAndFiles, null, { enumerateDirectories: true });
        let localToDevicePaths = files
            .map(projectFile => this.$projectFilesProvider.getProjectFileInfo(projectFile, deviceAppData.platform, projectFilesConfig))
            .filter(projectFileInfo => projectFileInfo.shouldIncludeFile)
            .map(projectFileInfo => this.$localToDevicePathDataFactory.create(projectFileInfo.filePath, projectFilesPath, projectFileInfo.onDeviceFileName, deviceAppData.deviceProjectRootPath));
        return localToDevicePaths;
    }
    processPlatformSpecificFiles(directoryPath, platform, excludedDirs) {
        return (() => {
            let contents = this.$fs.readDirectory(directoryPath).wait();
            let files = [];
            _.each(contents, fileName => {
                let filePath = path.join(directoryPath, fileName);
                let fsStat = this.$fs.getFsStats(filePath).wait();
                if (fsStat.isDirectory() && !_.includes(excludedDirs, fileName)) {
                    this.processPlatformSpecificFilesCore(platform, this.$fs.enumerateFilesInDirectorySync(filePath)).wait();
                }
                else if (fsStat.isFile()) {
                    files.push(filePath);
                }
            });
            this.processPlatformSpecificFilesCore(platform, files).wait();
        }).future()();
    }
    processPlatformSpecificFilesCore(platform, files) {
        return (() => {
            _.each(files, filePath => {
                let projectFileInfo = this.$projectFilesProvider.getProjectFileInfo(filePath, platform);
                if (!projectFileInfo.shouldIncludeFile) {
                    this.$fs.deleteFile(filePath).wait();
                }
                else if (projectFileInfo.onDeviceFileName) {
                    let onDeviceFilePath = path.join(path.dirname(filePath), projectFileInfo.onDeviceFileName);
                    let extension = path.extname(projectFileInfo.onDeviceFileName);
                    if (onDeviceFilePath !== filePath) {
                        if (extension === ".js" || extension === ".map") {
                            let oldName = extension === ".map" ? this.getFileName(filePath, extension) : path.basename(filePath);
                            let newName = extension === ".map" ? this.getFileName(projectFileInfo.onDeviceFileName, extension) : path.basename(projectFileInfo.onDeviceFileName);
                            let fileContent = this.$fs.readText(filePath).wait();
                            fileContent = fileContent.replace(new RegExp(oldName, 'g'), newName);
                            this.$fs.writeFile(filePath, fileContent).wait();
                        }
                        this.$fs.rename(filePath, onDeviceFilePath).wait();
                    }
                }
            });
        }).future()();
    }
    getFileName(filePath, extension) {
        return path.basename(filePath.replace(extension === ".map" ? ".js.map" : ".js", ""));
    }
}
exports.ProjectFilesManager = ProjectFilesManager;
$injector.register("projectFilesManager", ProjectFilesManager);
