/**
 * @since 150524 18:23
 * @author vivaxy
 */
var fs = require('fs'),
    path = require('path'),
    util = require('util'),
    events = require('events'),

    ip = require('ip'),
    ws = require('ws'),
    log = require('log-util'),
    chokidar = require('chokidar'),
    debounce = require('debounce'),

    EventEmitter = events.EventEmitter,
    currentDir = process.cwd(),
    hostname = ip.address(),

    /**
     *
     * @param options
     * @constructor
     */
    Watcher = function (options) {

        EventEmitter.apply(this, arguments);

        this.interval = options.interval;
        this.directory = options.directory;

        this.ignored = options.ignored || '';

        this.port = options.port;
        this.sockets = [];

        this.initialize();
        this.startup();

    };

util.inherits(Watcher, EventEmitter);
var p = Watcher.prototype;
p.constructor = Watcher;
module.exports = Watcher;

/**
 * create instances
 * @returns {Watcher}
 */
p.initialize = function () {
    var _this = this;
    var WebSocketServer = ws.Server,
        wss = new WebSocketServer({port: _this.port}, function () {
            log.info('watcher: listen http://' + hostname + ':' + _this.port + '/');
            _this.emit('success');
        });
    wss.on('connection', function (ws) {
        _this.sockets.push(ws);
        log.error('connection', _this.sockets.length);
        ws.on('close', function () {
            log.error('closing', _this.sockets.indexOf(ws));
            _this.sockets.splice(_this.sockets.indexOf(ws), 1);
            log.error('close', _this.sockets.length);
        });
        ws.on('error', function (e) {
            log.error(e.stack);
        });
    });
    wss.on('error', function (err) {
        if (err.code === 'EADDRINUSE') {
            log.warn('watcher: port ' + _this.port + ' in use');
            _this.port = _this.port + 1;
            return _this.initialize();
        } else {
            log.error(err);
        }
    });
    return this;
};

/**
 * start web socket server
 * @returns {*}
 */
p.startup = function () {
    var _this = this,
        reload = debounce(function () {
            // reload
            log.debug('watcher: reload');
            _this.sockets.forEach(function (ws) {
                ws.send('reload');
            });
        }, this.interval);
    return chokidar.watch(currentDir, {ignored: this.getIgnored.bind(this)}).on('all', function (action, filename) {
        var relativeFilename = path.relative(currentDir, filename);
        log.debug('watcher: ' + _this.toDashedString(action) + ' ' + relativeFilename);
        if (action === 'change' || action === 'add' || action === 'unlink' || action === 'addDir') {
            reload();
        }
    });
};

/**
 * is this file or folder ignored for file watcher
 * @param file
 * @returns {boolean}
 */
p.getIgnored = function (file) {
    var _this = this,
    // todo split ignore config into ignore.js
        ignoreFolders = ['node_modules'],
        ignoreFiles = [];
    if (this.getBaseName(file).indexOf('.') === 0) {
        // start with .
        return true;
    }
    if (!fs.existsSync(file)) {
        return true;
    }
    // ignore files
    if (fs.lstatSync(file).isDirectory()) {
        // folder
        return ignoreFolders.some(function (folder) {
            return _this.getBaseName(file).indexOf(folder) === 0;
        });
    } else {
        // file
        // watch js css html
        return !(path.extname(file) === '.js' || path.extname(file) === '.css' || path.extname(file) === '.html');
    }
};

/**
 * todo what this for? is it path.basename?
 * @param file
 * @returns {*}
 */
p.getBaseName = function (file) {
    var fileSplit = file.split(path.sep);
    return fileSplit[fileSplit.length - 1];
};

/**
 *
 * @returns {*}
 */
p.getPort = function () {
    return this.port;
};

/**
 * convert camel string to dashed string
 * someArgument => some-argument
 * @param string
 * @returns {string}
 */
p.toDashedString = function (string) {
    return Array.prototype.map.call(string, function (letter) {
        if (letter.toUpperCase() === letter) {
            return '-' + letter.toLowerCase();
        } else {
            return letter;
        }
    }).join('');
};

@@ -1352,350 +1352,98 @@
     
-log.error('connection', _this.sockets.length);%0A        ws.on('close', function () %7B%0A            log.error('closing', _this.sockets.indexOf(ws));%0A            _this.sockets.splice(_this.sockets.indexOf(ws), 1);%0A            log.error('close', _this.sockets.length);%0A        %7D);%0A        ws.on('error', function (e) %7B%0A            log.error(e.stack
+ws.on('close', function () %7B%0A            _this.sockets.splice(_this.sockets.indexOf(ws), 1
 );%0A 

remove test log