/**
* ******************************************************
*                                                       *
*   Copyright (C) Microsoft. All rights reserved.       *
*                                                       *
* ******************************************************
*/
/// <reference path="../../typings/node.d.ts" />
/// <reference path="../../typings/Q.d.ts" />
/// <reference path="../../typings/vcremote-utils.d.ts" />
/// <reference path="../../typings/vcremote-lib.d.ts" />
/// <reference path="../../typings/express.d.ts" />
/// <reference path="../../typings/semver.d.ts" />
/// <reference path="../../typings/fstream.d.ts" />
/// <reference path="../../typings/zip-stream.d.ts" />
"use strict";
var fs = require("fs");

var archiver = require("archiver");
var child_process = require("child_process");
var spawnSync = require("spawn-sync");
var tmp = require("tmp");

var project = require("../projectsystem/project");

var VCRemoteLib;
(function (VCRemoteLib) {
    function execOpen(req, res) {
        var filepath = req.query.filepath;
        console.info("Opening file %s.", filepath);
        var child = child_process.spawn("open", [filepath], { detached: true });

        // TODO: get return code back to sender.
        res.end();
    }
    VCRemoteLib.execOpen = execOpen;

    function getFiles(req, res) {
        var buf = [];

        req.on('data', function (data) {
            buf.push(data);
        }).on('end', function () {
            var finalBuffer = Buffer.concat(buf).toString();
            var jsonContent = JSON.parse(finalBuffer);

            var incremental = false;

            incremental = Boolean(jsonContent.incremental);
            var rootpath = jsonContent.rootpath;
            var filepaths = jsonContent.filepaths;

            var lastSyncTimeFile = rootpath + "/.lastSyncTime";
            var lastSyncTime;

            if (incremental) {
                try  {
                    var stats = fs.statSync(lastSyncTimeFile);
                    lastSyncTime = stats.mtime;
                    console.log("Syncing difference since %s %s from file %s.", lastSyncTime.toDateString(), lastSyncTime.toTimeString(), lastSyncTimeFile);
                } catch (e) {
                    incremental = false;
                    console.log("Performing full sync because the time of the last sync form file '%s' is unknown.", lastSyncTimeFile);
                }
            }

            if (rootpath != null && filepaths != null) {
                var filepathSeperated = filepaths.split(';');

                res.writeHead(200, "OK", {
                    "Content-Type": "application/zip"
                });

                var archive = archiver.create('zip', {});
                archive.pipe(res);
                archive.on('end', function () {
                    if (fileSent > 0) {
                        touchFile(lastSyncTimeFile);
                    }

                    res.end();
                });

                var fileSent = 0;

                for (var i = 0; i < filepathSeperated.length; i++) {
                    var path = filepathSeperated[i];

                    // if path is not rooted, then root it with rootpath.
                    if (path[0] != '/') {
                        path = rootpath + '/' + path;
                    }

                    try  {
                        var stats = fs.statSync(path);
                        if (!incremental || stats.mtime > lastSyncTime) {
                            console.info("Sending %s.", path);

                            if (stats.isDirectory()) {
                                fileSent++;
                                archive.directory(path, path.substring(rootpath.length + 1));
                            } else {
                                fileSent++;
                                archive.file(path, { name: path.substring(rootpath.length + 1), stats: stats });
                            }
                        } else {
                            console.info("Skipping %s because it is older than last sync time.", path);
                        }
                    } catch (e) {
                        console.info("Error getting info on %s.", path);
                    }
                }

                console.log("Sending %d out of %d.", fileSent, filepathSeperated.length);
                archive.finalize();
            }
        });
    }
    VCRemoteLib.getFiles = getFiles;

    function putFiles(req, res) {
        var projectDir = req.query.directory;

        console.info("Unzipping project to %s.", projectDir);

        var resource = new project.RemoteZipResource(req);

        resource.on("extracted", function () {
            res.end();
        });
        resource.on("error", function () {
            res.end();
        });

        resource.retrieve(projectDir);
    }
    VCRemoteLib.putFiles = putFiles;

    function deleteFiles(req, res) {
        var buf = [];

        req.on('data', function (data) {
            buf.push(data);
        }).on('end', function () {
            var finalBuffer = Buffer.concat(buf).toString();
            var jsonContent = JSON.parse(finalBuffer);

            var incremental = false;

            incremental = Boolean(jsonContent.incremental);
            var rootpath = jsonContent.rootpath;
            var filepaths = jsonContent.filepaths;

            console.info("Cleaning ", rootpath, " and ", filepaths);

            var filepathSeperated = filepaths.split(';');

            if (rootpath != null && filepaths != null) {
                for (var i = 0; i < filepathSeperated.length; i++) {
                    var path = filepathSeperated[i];

                    // if path is not rooted, then root it with rootpath.
                    if (path[0] != '/') {
                        path = rootpath + '/' + path;
                    }

                    deleteFolderRecursive(path);
                }
            }

            res.end();
        });
    }
    VCRemoteLib.deleteFiles = deleteFiles;

    function deleteFolderRecursive(path) {
        if (fs.existsSync(path)) {
            var files = fs.readdirSync(path);

            files.forEach(function (file, index) {
                var curPath = path + "/" + file;
                if (fs.lstatSync(curPath).isDirectory()) {
                    deleteFolderRecursive(curPath);
                } else {
                    fs.unlinkSync(curPath);
                }
            });

            fs.rmdirSync(path);
        }
    }
    ;

    function touchFile(path) {
        if (!fs.existsSync(path))
            fs.writeFileSync(path, "");
        else
            fs.utimesSync(path, NaN, NaN);
    }
})(VCRemoteLib || (VCRemoteLib = {}));
module.exports = VCRemoteLib;
