

"use strict";

var socketio = require('socket.io');
var _ = require("underscore");
var log = require("./log");
var addr = require("./addr");
var dpt = require("./dpt");
var knxd = require("./knxd");
var config = require("./config");
var cache = require("./cache");
var db = require("./db");

function WebSocket() {
    this.io = null;
}

WebSocket.prototype.start = function(server) {
    var self = this;
    self.io = socketio(server);
    log.info("socket.io server started");

    // register socket.io websocket callback
    self.io.on('connection', function(socket) {
        log.debug("WebSocket client connected");

        socket.on('disconnect', function() {
            log.debug('WebSocket client disconnected');
        });

        socket.on('getConfig', function() {
            socket.emit('getConfig', config.getConfig());
        });

        socket.on('getCache', function() {
            socket.emit('getCache', cache.getValues());
        });

        socket.on('groupWrite', function(obj) {
            var groupAddr = new addr.GroupAddr(obj.ga),
                conf = config.getAddressConfig(obj.ga),
                buffer;

            if (conf) {
                knxd.sendGroup(groupAddr, obj.value, conf.dpt);
                // update cache about changed value
                cache.updateValue(obj.ga, obj.value);
            } else {
                log.error("Error writing to group, group address config not found.");
            }
        });

        socket.on('error', function(err) {
            log.error('WebSocket client got error: %s', err+'');
        });

        socket.on('getEvents', function(obj) {
            log.debug("WebSocket getEvents(): ga=%s, from=%s, to=%s", obj.ga, obj.from, obj.to);

            db.getEvents(obj.ga, obj.from, obj.to, function(events) {
                var result = _.map(events, function(e) {
                    var value;
                    try {
                        value = dpt.decode(e.payload, e.dpt);
                        return [e.ts, value];
                    } catch(e) {
                        log.error(e);
                        return [e.ts, null];
                    }
                });
                socket.emit('getEvents', {ga: obj.ga, from: obj.from, to: obj.to, events: result });
            });
        });
    });

    /**
     * Notifies all connected clients.
     */
    knxd.onTelegramReceived(tg => {
        if (tg.hasValue()) {
            self.io.emit('groupChange', {
                ga: tg.dst+'',
                value: tg.value
            });
        }
    });
};

WebSocket.prototype.close = function(server) {
    var self = this;
    if (self.io) {
        self.io.close();
        log.info("socket.io server closed");
    }
};

var ws = new WebSocket();

module.exports = ws;