/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
*/
(function() {
    'use strict';
    /* global myApp */
    /* global chrome */

// Server actions:
//
// Show in-app overlay menu:
//     curl -v -X POST "http://$IP_ADDRESS:2424/menu"
//
// Execute a JS snippet:
//     curl -v -X POST "http://$IP_ADDRESS:2424/exec?code='alert(1)'"
//
// Starts the app with the given ID (or the first app if none is given):
//     curl -v -X POST "http://$IP_ADDRESS:2424/launch?appId=a.b.c"
//
// Returns JSON of server info / app state:
//     curl -v "http://$IP_ADDRESS:2424/info"
//
// Returns JSON of the asset manifest for the given app ID (or the first app if none is given):
//     curl -v "http://$IP_ADDRESS:2424/assetmanifest?appId=a.b.c"
//
// Deletes a set of files within the given app ID (or the first app if none is given):
//     echo '{"paths":["www/index.html"]}' | curl -v -X POST -d @- "http://$IP_ADDRESS:2424/deletefiles?appId=a.b.c"
//
// Updates a single file within the given app ID (or the first app if none is given):
//     cat file | curl -v -X PUT -d @- "http://$IP_ADDRESS:2424/assetmanifest?appId=a.b.c&appType=cordova&path=www/index.html&etag=1234"
//
// Deletes the app with the given ID (or the first app if none is given):
//     curl -v -X POST "http://$IP_ADDRESS:2424/deleteapp?appId=a.b.c"
//     curl -v -X POST "http://$IP_ADDRESS:2424/deleteapp?all=true" # Delete all apps.
//
// Send a set of files within the given app ID (or the first app if none is given):
//     cat file | curl -v -X POST -d @- "http://$IP_ADDRESS:2424/zippush?appId=a.b.c&appType=cordova"
// The zip file must contain a zipassetmanifest.json file at its root that is a map of "srcPath"->{"path":dstPath, "etag":"0"}.
//
// Send a partial update of files within the given app ID (or the first app if none is given):
//     cat file | curl -v -X POST -d @- "http://$IP_ADDRESS:2424/zippush?appId=a.b.c&appType=cordova&movetype=file"
// The zip file must contain a zipassetmanifest.json file at its root that is a map of "srcPath"->{"path":dstPath, "etag":"0"}.
// With this method, the files are moved one at a time and will overwrite any existing file of the same name.
//
    myApp.factory('HarnessServer', ['$q', 'HttpServer', 'ResourcesLoader', 'AppHarnessUI', 'AppsService', 'notifier', 'APP_VERSION', function($q, HttpServer, ResourcesLoader, AppHarnessUI, AppsService, notifier, APP_VERSION) {

        var PROTOCOL_VER = 2;
        var server = null;
        var listenAddress = null;

        function ensureMethodDecorator(method, func) {
            return function(req, resp) {
                if (req.method != method) {
                    throw new HttpServer.ResponseException(405, 'Method Not Allowed');
                }
                return func(req, resp);
            };
        }

        function pipeRequestToFile(req, destUrl) {
            var writer = null;
            function handleChunk(arrayBuffer) {
                var ret = $q.when();
                if (writer == null) {
                   ret = ResourcesLoader.createFileWriter(destUrl)
                   .then(function(w) {
                       writer = w;
                   });
                }
                return ret.then(function() {
                    var deferred = $q.defer();
                    writer.onwrite = deferred.resolve;
                    writer.onerror = function() {
                      deferred.reject(writer.error);
                    };
                    writer.write(arrayBuffer);
                    return deferred.promise;
                })
                .then(function() {
                    if (req.bytesRemaining > 0) {
                        return req.readChunk().then(handleChunk);
                    }
                });
            }
            return req.readChunk().then(handleChunk);
        }

        function handleExec(req, resp) {
            var js = req.getQueryParam('code');
            return AppHarnessUI.evalJs(js)
            .then(function() {
                resp.sendTextResponse(200, '');
            });
        }

        function handleMenu(req, resp) {
            resp.sendTextResponse(200, '');
            return AppHarnessUI.fireEvent('showMenu');
        }

        function handleLaunch(req, resp) {
            var appId = req.getQueryParam('appId');
            return AppsService.getAppById(appId)
            .then(function(app) {
                if (app) {
                    return AppsService.launchApp(app)
                    .then(function() {
                        return resp.sendTextResponse(200, '');
                    });
                }
                throw new HttpServer.ResponseException(412, 'No apps available for launch');
            });
        }

        function getAssetManifestJson(app) {
            return {
                'assetManifest': app && app.directoryManager.getAssetManifest(),
                'assetManifestEtag': app ? app.directoryManager.getAssetManifestEtag() : '0',
                'platform': cordova.platformId,
                'cordovaVer': cordova.version,
                'protocolVer': PROTOCOL_VER
            };
        }

        function handleAssetManifest(req, resp) {
            var appId = req.getQueryParam('appId');
            return AppsService.getAppById(appId)
            .then(function(app) {
                return resp.sendJsonResponse(200, getAssetManifestJson(app));
            });
        }

        function handleDeleteFiles(req, resp) {
            var appId = req.getQueryParam('appId');
            var manifestEtag = req.getQueryParam('manifestEtag');
            return AppsService.getAppById(appId)
            .then(function(app) {
                return req.readAsJson()
                .then(function(requestJson) {
                    if (app) {
                        if (manifestEtag && app.directoryManager.getAssetManifestEtag() !== manifestEtag) {
                            return resp.sendJsonResponse(409, getAssetManifestJson(app));
                        }
                        var paths = requestJson['paths'];
                        for (var i = 0; i < paths.length; ++i) {
                            app.directoryManager.deleteFile(paths[i]);
                        }
                    } else {
                        console.log('Warning: tried to delete files from non-existant app: ' + appId);
                    }
                    return resp.sendTextResponse(200, '');
                });
            });
        }

        function handleDeleteApp(req, resp) {
            var appId = req.getQueryParam('appId');
            var all = req.getQueryParam('all');
            var ret;
            if (all) {
                ret = AppsService.uninstallAllApps();
            } else {
                ret = AppsService.getAppById(appId)
                .then(function(app) {
                    if (app) {
                        return AppsService.uninstallApp(app);
                    }
                });
            }
            return ret.then(function() {
                return resp.sendTextResponse(200, '');
            });
        }

        function handlePutFile(req, resp) {
            var appId = req.getQueryParam('appId');
            var appType = req.getQueryParam('appType') || 'cordova';
            var path = req.getQueryParam('path');
            var etag = req.getQueryParam('etag');
            var manifestEtag = req.getQueryParam('manifestEtag');
            if (!path || !etag) {
                throw new Error('Request is missing path or etag query params');
            }
            return AppsService.getAppById(appId, appType)
            .then(function(app) {
                // Checking the manifest ETAG is meant to catch the case where
                // the client has cached the manifest from a first push, and
                // wants to validate that it is still valid at the start of a
                // subsequent push (e.g. make sure the device hasn't changed).
                if (manifestEtag && app.directoryManager.getAssetManifestEtag() !== manifestEtag) {
                    return resp.sendJsonResponse(409, getAssetManifestJson(app));
                }
                startUpdateProgress(app, req);
                var tmpUrl = ResourcesLoader.createTmpFileUrl();
                return pipeRequestToFile(req, tmpUrl)
                .then(function() {
                    return importFile(tmpUrl, path, app, etag);
                })
                .then(function() {
                    return incrementUpdateStatusAndSendManifest(app, req, resp);
                });
            });
        }

        // This is set at the beginning of a push to show progress bar
        // across multiple requests.
        function startUpdateProgress(app, req) {
            // This is passed for the first file only, and is used to track total progress.
            var expectTotal = +req.getQueryParam('expectBytes') || req.headers['content-length'];
            app.updatingStatus = 0;
            app.updateBytesTotal = expectTotal;
            app.updateBytesSoFar = 0;
        }

        function incrementUpdateStatusAndSendManifest(app, req, resp) {
            if (app.updatingStatus !== null) {
                // TODO: Add a timeout that resets updatingStatus if no more requests come in.
                app.updateBytesSoFar += +req.headers['content-length'];
                app.updatingStatus = app.updateBytesTotal / app.updateBytesSoFar;
                if (app.updatingStatus === 1) {
                    app.updatingStatus = null;
                    app.lastUpdated = new Date();
                    AppsService.triggerAppListChange();
                    notifier.success('Update complete.');
                }
            }
            return resp.sendJsonResponse(200, {
                'assetManifestEtag': app.directoryManager.getAssetManifestEtag()
            });
        }

        function importFile(fileUrl, destPath, app, etag) {
            console.log('Adding file: ' + destPath);
            if (destPath == 'www/cordova_plugins.js') {
                destPath = 'orig-cordova_plugins.js';
            }
            return app.directoryManager.addFile(fileUrl, destPath, etag);
        }

        function handleZipPush(req, resp) {
            var appId = req.getQueryParam('appId');
            var appType = req.getQueryParam('appType') || 'cordova';
            var manifestEtag = req.getQueryParam('manifestEtag');
            var movetype = req.getQueryParam('movetype') || 'bulk';
            return AppsService.getAppById(appId, appType)
            .then(function(app) {
                if (manifestEtag && app.directoryManager.getAssetManifestEtag() !== manifestEtag) {
                    return resp.sendJsonResponse(409, getAssetManifestJson(app));
                }
                startUpdateProgress(app, req);
                var tmpZipUrl = ResourcesLoader.createTmpFileUrl();
                var tmpDirUrl = ResourcesLoader.createTmpFileUrl() + '/';
                return pipeRequestToFile(req, tmpZipUrl)
                .then(function() {
                    console.log('Extracting update zip');
                    return ResourcesLoader.extractZipFile(tmpZipUrl, tmpDirUrl);
                })
                .then(function() {
                    // This file looks like:
                    // {"path/within/zip": { "path": "dest/path", "etag": "foo" }}
                    return ResourcesLoader.readJSONFileContents(tmpDirUrl + 'zipassetmanifest.json');
                }, null, function(unzipPercentage) {
                    app.updatingStatus = unzipPercentage;
                })
                .then(function(zipAssetManifest) {
                    if (movetype == 'bulk') {
                        console.log('Moving files in bulk');
                        return $q.when()
                        .then(function(){
                            // get the source base path from the first file
                            // all files need to be in the same place
                            var firstfile = Object.keys(zipAssetManifest)[0];
                            var fpath = tmpDirUrl + firstfile;
                            var pathendposition = fpath.lastIndexOf(zipAssetManifest[firstfile]['path']);
                            var fromurl = fpath.substr(0,pathendposition-1);
                            return app.directoryManager.bulkAddFile(zipAssetManifest, fromurl);
                        });
                    } else {
                        var keys = Object.keys(zipAssetManifest);
                        console.log('Moving '+keys.length+ ' files separately');
                        return $q.when()
                        .then(function next() {
                            var k = keys.shift();
                            if (k) {
                                return  importFile(tmpDirUrl + k, zipAssetManifest[k]['path'], app, zipAssetManifest[k]['etag'])
                                .then(next);
                            }
                        });
                    }
                }, function() {
                    throw new HttpServer.ResponseException(400, 'Zip file missing zipassetmanifest.json');
                })
                .then(function() {
                    return incrementUpdateStatusAndSendManifest(app, req, resp);
                })
                .finally(function() {
                    app.updatingStatus = null;
                    ResourcesLoader.delete(tmpZipUrl);
                    ResourcesLoader.delete(tmpDirUrl);
                });
            });
        }

        function handleInfo(req, resp) {
            var activeApp = AppsService.getActiveApp();
            var json = {
                'platform': cordova.platformId,
                'cordovaVer': cordova.version,
                'protocolVer': PROTOCOL_VER,
                'harnessVer': APP_VERSION,
                'supportedAppTypes': ['cordova'],
                'userAgent': navigator.userAgent,
                'activeAppId': activeApp && activeApp.appId,
                'appList': AppsService.getAppListAsJson()
            };
            resp.sendJsonResponse(200, json);
        }

        function start() {
            if (server) {
                return;
            }
            server = new HttpServer()
                .addRoute('/exec', ensureMethodDecorator('POST', handleExec))
                .addRoute('/menu', ensureMethodDecorator('POST', handleMenu))
                .addRoute('/launch', ensureMethodDecorator('POST', handleLaunch))
                .addRoute('/info', ensureMethodDecorator('GET', handleInfo))
                .addRoute('/assetmanifest', ensureMethodDecorator('GET', handleAssetManifest))
                .addRoute('/deletefiles', ensureMethodDecorator('POST', handleDeleteFiles))
                .addRoute('/putfile', ensureMethodDecorator('PUT', handlePutFile))
                .addRoute('/zippush', ensureMethodDecorator('POST', handleZipPush))
                .addRoute('/deleteapp', ensureMethodDecorator('POST', handleDeleteApp));
            return server.start();
        }

        function getListenAddress(skipCache) {
            if (listenAddress && !skipCache) {
                return $q.when(listenAddress);
            }
            var deferred = $q.defer();
            chrome.socket.getNetworkList(function(interfaces) {
                // Filter out ipv6 addresses.
                var ret = interfaces.filter(function(i) {
                    return i.address.indexOf(':') === -1;
                }).map(function(i) {
                    return i.address;
                }).join(', ');
                listenAddress = ret;
                deferred.resolve(ret);
            });
            return deferred.promise;
        }

        return {
            start: start,
            getListenAddress: getListenAddress
        };
    }]);
})();
