const sqlite3 = require('sqlite3'),
    createAccountTable = require('./models/accounts.js').createTable,
    createAccountConfigTable = require('./models/accountConfig.js').createTable;

const DB_PATH = __dirname +"/../database.sqlite";

function Database() {
    this.db = null;
};

Database.prototype.initDb = function(cb) {
    var self = this;
    if (self.db) {
        cb(null);
    } else {
        self.db = new sqlite3.Database(DB_PATH, sqlite3.OPEN_READWRITE, (err) => {
            if (err) {
                if (err.code === "SQLITE_CANTOPEN") {
                    self.db = new sqlite3.Database(DB_PATH, sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, (err) => {
                        if (!err) {
                            self.createAllTables([
                                createAccountTable,
                                createAccountConfigTable
                            ], 0, cb);
                        } else {
                            cb(err);
                        }
                    });
                } else {
                    cb(err);
                }
            } else {
                cb(null);
            }
        });
    }
};

Database.prototype.createAllTables = function(factories, i, cb) {
    var self = this;

    if (factories[i]) {
        factories[i](self.db, (err) => {
            if (!err)
                self.createAllTables(factories, ++i, cb);
            else
                cb(err);
        });
    } else {
        cb(null);
    }
};

Database.prototype.query = function(table, fields, cb) {
    var args = [];
    for (var i in fields)
        args.push(fields[i]);
    this.db.all("SELECT * FROM `" +table +"` WHERE `" +Object.keys(fields).join("`=? AND") +"`=?", args, (err, rows) => {
        if (err) {
            console.warn(err);
            cb(err, null);
        } else {
            cb(null, rows);
        }
    });
};

Database.prototype.queryFirst = function(table, fields, cb) {
    var args = [];
    for (var i in fields)
        args.push(fields[i]);
    this.db.get("SELECT * FROM `" +table +"` WHERE `" +Object.keys(fields).join("`=? AND") +"`=?", args, (err, row) => {
        if (err) {
            console.warn(err);
            cb(err, null);
        } else {
            cb(null, row || null);
        }
    });
};

Database.prototype.insert = function(table, data, cb) {
    var args = []
        ,keys = []
        ,templateArgs = [];
    for (var i in data) {
        keys.push('`' +i +'`');
        args.push(data[i]);
        templateArgs.push('?');
    }

    this.db.run("INSERT INTO " +table +" ("+ keys.join(",") +") VALUES(" +templateArgs.join(', ') +")", args, function(err) {
        if (err) {
            console.error(err);
            cb(null);
        }
        cb(this.lastID);
    });
};

Database.prototype.update = function(table, id, fields, cb) {
    var args = [];
    for (var i in fields)
        args.push(fields[i]);
    args.push(id);
    this.db.run("UPDATE " +table +" SET `" +Object.keys(fields).join("`=?,`") +"`=? WHERE id=?", args, (err) => {
        if (err) {
            console.error(err);
        }
        cb();
    });
};

const singleton = new Database();

module.exports.database = singleton;

