const db = require('../database.js');

const TABLE_NAME = "accountConfig";

function AccountConfigManager() {
}

AccountConfigManager.prototype.fromAccountId = function(id, cb) {
    var self = this;
    db.database.query(TABLE_NAME, { accountId: id }, (err, result) => {
        if (!result)
            cb(null);
        let accConfigs = [];
        result.forEach((res) => {
            accConfigs.push(self.fromDb(res));
        });
        cb(accConfigs);
    });
};

AccountConfigManager.prototype.fromAccountIdAndVersion = function(id, v, cb) {
    var self = this;
    db.database.query(TABLE_NAME, { accountId: id }, (err, result) => {
        if (!result)
            cb(null);
        for (var i =0, nbConfig = result.length; i < nbConfig; i++) {
            if (result[i].modified > v) {
                var configs = [];
                for (i =0; i < nbConfig; i++) {
                    configs.push(self.fromDb(result[i]));
                }
                cb(configs);
                return;
            }
        }
        cb(null);
    });
};

AccountConfigManager.prototype.newConfigFor = function(account) {
    var conf = new AccountConfigWrapper();
    conf.dirty = true;
    conf.accountId = account.id;
    return conf;
};

AccountConfigManager.prototype.fromId = function(id, cb) {
    var self = this;
    db.database.queryFirst(TABLE_NAME, { id: id }, (err, result) => {
        cb(self.fromDb(result));
    });
};

AccountConfigManager.prototype.fromDb = function(dbResult) {
    if (!dbResult)
        return null;
    return new AccountConfigWrapper(dbResult);
};

function AccountConfigWrapper(dbResult) {
    this.id;

    this.accountId;
    this.serviceId; // Can be null, or a serviceId
    this.deviceId; // Can be null, or a deviceId

    this.config = new AccountConfig();
    this.modified; // modified ts

    if (dbResult) {
        this.id = dbResult.id;

        this.accountId = dbResult.accountId;
        this.serviceId = dbResult.serviceId;
        this.deviceId = dbResult.deviceId;

        this.config.fromDb(dbResult.config);
        this.modified = dbResult.modified;
        this.dirty = false;
    } else {
        this.id = null;

        this.accountId = null;
        this.serviceId = null;
        this.deviceId = null;

        this.modified = Date.now();

        this.dirty = true;
    }
}

AccountConfigWrapper.prototype.toDb = function() {
    return {
        accountId: this.accountId,
        serviceId: this.serviceId,
        deviceId: this.deviceId,
        config: this.config.toDb(),
        modified: this.modified
    };
};

AccountConfigManager.prototype.save = function(account, cb) {
    if (!account.id) {
        // insert and save id
        var data = account.toDb();
        data.id = null;
        db.database.insert(TABLE_NAME, data, (newId) => {
            account.id = newId;
            account.dirty = false;
            cb(account);
        });
    } else if (account.dirty) {
        // update
        db.database.update(TABLE_NAME, account.id, account.toDb(), () => {
            account.dirty = false;
            cb(account);
        });
    } else {
        // not changed
        cb(account);
    }
};

AccountConfigWrapper.prototype.expose = function() {
    return {
        service: this.serviceId,
        device: this.deviceId,
        config: this.config.toDb()
    };
};

function AccountConfig() {
    this.services = [];
}

AccountConfig.prototype.toDb = function() {
    return JSON.stringify({
        services: this.services
    });
};

AccountConfig.prototype.fromDb = function(dbObj) {
    dbObj = JSON.parse(dbObj);
    this.services = dbObj.services || [];
};

module.exports.accountConfigManager = new AccountConfigManager();

module.exports.createTable = function(dbObject, cb) {
    console.info("Creating table " +TABLE_NAME);
    dbObject.run('CREATE TABLE IF NOT EXISTS `' +TABLE_NAME +'` ('
        +"`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
        +"`accountId` STRING NOT NULL,"
        +"`serviceId` STRING,"
        +"`deviceId` STRING,"
        +"`config` STRING NOT NULL,"
        +"`modified` INT NOT NULL"
        +');CREATE INDEX accconfigbyaccount ON ' +TABLE_NAME +'(accountId); CREATE UNIQUE INDEX accconfigUniq ON ' +TABLE_NAME +'(accountId, serviceId, deviceId)', cb);
    //TODO permanent login token array
};

