'use strict';

var Backbone = require('backbone'),
    Locale = require('../util/locale'),
    Logger = require('../util/logger');

var Launcher;

var logger = new Logger('launcher');

if (window.process && window.process.versions && window.process.versions.electron) {
    /* jshint node:true */
    Launcher = {
        name: 'electron',
        version: window.process.versions.electron,
        req: window.require,
        electron: function() {
            return this.req('electron');
        },
        remoteApp: function() {
            return this.electron().remote.app;
        },
        remReq: function(mod) {
            return this.electron().remote.require(mod);
        },
        openLink: function(href) {
            this.electron().shell.openExternal(href);
        },
        devTools: true,
        openDevTools: function() {
            this.electron().remote.getCurrentWindow().openDevTools();
        },
        getSaveFileName: function(defaultPath, cb) {
            if (defaultPath) {
                var homePath = this.remReq('electron').app.getPath('userDesktop');
                defaultPath = this.req('path').join(homePath, defaultPath);
            }
            this.remReq('dialog').showSaveDialog({
                title: Locale.launcherSave,
                defaultPath: defaultPath,
                filters: [{ name: Locale.launcherFileFilter, extensions: ['kdbx'] }]
            }, cb);
        },
        getUserDataPath: function(fileName) {
            return this.req('path').join(this.remoteApp().getPath('userData'), fileName || '');
        },
        getTempPath: function(fileName) {
            return this.req('path').join(this.remoteApp().getPath('temp'), fileName || '');
        },
        getAppPath: function(fileName) {
            return this.req('path').join(__dirname, fileName || '');
        },
        writeFile: function(path, data) {
            this.req('fs').writeFileSync(path, new window.Buffer(data));
        },
        readFile: function(path, encoding) {
            var contents = this.req('fs').readFileSync(path, encoding);
            return typeof contents === 'string' ? contents : new Uint8Array(contents);
        },
        fileExists: function(path) {
            return this.req('fs').existsSync(path);
        },
        deleteFile: function(path) {
            this.req('fs').unlinkSync(path);
        },
        statFile: function(path) {
            return this.req('fs').statSync(path);
        },
        parsePath: function(fileName) {
            var path = this.req('path');
            return { path: fileName, dir: path.dirname(fileName), file: path.basename(fileName) };
        },
        createFsWatcher: function(path) {
            return this.req('fs').watch(path, { persistent: false });
        },
        preventExit: function(e) {
            e.returnValue = false;
            return false;
        },
        exit: function() {
            this.exitRequested = true;
            this.requestExit();
        },
        requestExit: function() {
            var app = this.remoteApp();
            if (this.restartPending) {
                app.restartApp();
            } else {
                app.quit();
            }
        },
        requestRestart: function() {
            this.restartPending = true;
            this.requestExit();
        },
        cancelRestart: function() {
            this.restartPending = false;
        },
        setClipboardText: function(text) {
            return this.electron().clipboard.writeText(text);
        },
        getClipboardText: function() {
            return this.electron().clipboard.readText();
        },
        clearClipboardText: function() {
            return this.electron().clipboard.clear();
        },
        minimizeApp: function() {
            this.remoteApp().minimizeApp();
        },
        canMinimize: function() {
            return process.platform !== 'darwin';
        },
        updaterEnabled: function() {
            return this.electron().remote.process.argv.indexOf('--disable-updater') === -1;
        },
        resolveProxy: function(url, callback) {
            var window = this.remoteApp().getMainWindow();
            var session = window.webContents.session;
            session.resolveProxy(url, function(proxy) {
                var match = /^proxy\s+([\w\.]+):(\d+)+\s*/i.exec(proxy);
                proxy = match && match[1] ? { host: match[1], port: +match[2] } : null;
                callback(proxy);
            });
        },
        openWindow: function(opts) {
            return this.remoteApp().openWindow(opts);
        },
        hideWindowIfActive: function() {
            var app = this.remoteApp();
            var win = app.getMainWindow();
            var visible = win.isVisible(), focused = win.isFocused();
            if (!visible || !focused) {
                return false;
            }
            if (process.platform === 'darwin') {
                app.hide();
            } else {
                win.minimize();
            }
            return true;
        },
        spawn: function(config) {
            var ts = logger.ts();
            var complete = config.complete;
            var ps = this.req('child_process').spawn(config.cmd, config.args);
            [ps.stdin, ps.stdout, ps.stderr].forEach(function(s) { s.setEncoding('utf-8'); });
            var stderr = '';
            var stdout = '';
            ps.stderr.on('data', function(d) { stderr += d.toString('utf-8'); });
            ps.stdout.on('data', function(d) { stdout += d.toString('utf-8'); });
            ps.on('close', function(code) {
                stdout = stdout.trim();
                stderr = stderr.trim();
                var msg = 'spawn ' + config.cmd + ': ' + code + ', ' + logger.ts(ts);
                if (code) {
                    logger.error(msg + '\n' + stdout + '\n' + stderr);
                } else {
                    logger.info(msg + (stdout ? '\n' + stdout : ''));
                }
                if (complete) {
                    complete(code ? 'Exit code ' + code : null, stdout, code);
                    complete = null;
                }
            });
            ps.on('error', function(err) {
                logger.error('spawn error: ' + config.cmd + ', ' + logger.ts(ts), err);
                if (complete) {
                    complete(err);
                    complete = null;
                }
            });
            if (config.data) {
                ps.stdin.write(config.data);
                ps.stdin.end();
            }
            return ps;
        },
        platform: function() {
            return process.platform;
        }
    };
    Backbone.on('launcher-exit-request', function() {
        setTimeout(function() { Launcher.exit(); }, 0);
    });
    Backbone.on('launcher-minimize', function() {
        setTimeout(function() { Backbone.trigger('app-minimized'); }, 0);
    });
    window.launcherOpen = function(path) {
        Backbone.trigger('launcher-open-file', path);
    };
    if (window.launcherOpenedFile) {
        console.log('Open file request', window.launcherOpenedFile);
        Backbone.trigger('launcher-open-file', window.launcherOpenedFile);
        delete window.launcherOpenedFile;
    }
}

module.exports = Launcher;
