"use strict";

var _ = require("lodash"),
    fh = require("./Filehandler"),
    EventEmitter = require('events')


module.exports = class DB extends EventEmitter {
    constructor(args) {
        super()
        this.db = {}
        this.path = args.path
        this.key = args.key
        this.autoUpdate = true
        //update performes boost
        this.updateCalls = 0
        this.previousCallTime = undefined
        this.canCall = true
        this.canCallTreshold = undefined
        //disables auto update
        if(args.manual){
            this.autoUpdate = false
        }

        this.fileHandler = new fh({
            path: this.path,
            key: this.key
        })
        var data = this.fileHandler.init()
        if (data != null) {
            this.db = data
        }
    }

    addTable(name) {
        if (this.db[name] === undefined) {
            this.db[name] = []
            this.update()
        }
    }

    getAllTableNames() {
        return Object.keys(this.db)
    }

    getTable(name) {
        if (this.db[name] == undefined) {
            return
        }
        return this.db[name]
    }

    insert(tablename, data) {
        try {
            if (data != undefined) {
                if (this.db[tablename] != undefined) {
                    data.id = this.genUUID()
                    this.db[tablename].push(data)
                    if(this.autoUpdate){
                        this.update()
                    }
                    //event emiter
                    this.emit("insert", tablename, data)
                } else {
                    throw new Error("Table wasn't created")
                }
            } else {
                console.error("Error: Data was null or undefined!")
                return
            }
        } catch (err) {
            console.log(err)
        }
    }

    removeAllBy(tablename, args) {
        if (this.db[tablename] != undefined) {
            var removed = this.findAll(tablename, args)
            _.pullAllBy(this.db[tablename], removed)
            if(this.autoUpdate){
                this.update()
            }
            //event emiter
            this.emit("remove", tablename, removed)
        } else {
            throw new Error("Table wasn't created")
        }
    }

    updateByID(tablename, id, data) {
        if (data != undefined) {
            if (this.db[tablename] != undefined) {
                var updated = _.filter(this.db[tablename], {
                    id: id
                })
                if (updated[0] === undefined) {
                    return
                }
                const index = _.sortedIndexBy(this.db[tablename], updated[0])
                Object.assign(this.db[tablename][index], data)
                if(this.autoUpdate){
                    this.update()
                }
                //event emiter
                this.emit("updated", tablename, this.db[tablename][index])
            } else {
                throw new Error("Table wasn't created")
            }
        } else {
            console.error("Error: Data was null or undefined!")
            return
        }
    }

    find(tablename, args) {
        if (this.db[tablename] != undefined) {
            return _.find(this.getTable(tablename), args)
        } else {
            throw new Error("Table wasn't created")
        }
    }

    findLast(tablename, args) {
        if (this.db[name] != undefined) {
            return _.findLast(this.getTable(tablename), args)
        } else {
            throw new Error("Table wasn't created")
        }
    }

    findAll(tablename, args) {
        if (this.db[tablename] != undefined) {
            return _.filter(this.getTable(tablename), args)
        } else {
            throw new Error("Table wasn't created")
        }
    }

    genUUID() {
        function s4() {
            return Math.floor((1 + Math.random()) * 0x10000)
                .toString(16)
                .substring(1);
        }
        return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
            s4() + '-' + s4() + s4() + s4();
    }

    update() {
        this.updateCalls++
            if (this.canCall) {
                this.previousCallTime = new Date()
                this.fileHandler.write(this.db)
                this.emit("write")
            }
        if (this.updateCalls == this.canCallTreshold) {
            this.canCall = true
        } else if ((new Date() - this.previousCallTime) < 65) {
            this.canCallTreshold = this.updateCalls + 10
            this.canCall = false
        }
    }
}
@@ -273,24 +273,37 @@
  = args.key%0A
+%3C%3C%3C%3C%3C%3C%3C HEAD%0A
         this
@@ -593,24 +593,83 @@
 %0A        %7D%0A%0A
+=======%0A%3E%3E%3E%3E%3E%3E%3E parent of 20d032a... Performance enhancing%0A
         this
@@ -1434,24 +1434,37 @@
 .push(data)%0A
+%3C%3C%3C%3C%3C%3C%3C HEAD%0A
             
@@ -1544,32 +1544,91 @@
               %7D%0A
+=======%0A%3E%3E%3E%3E%3E%3E%3E parent of 20d032a... Performance enhancing%0A
                 
@@ -1695,32 +1695,66 @@
 ablename, data)%0A
+                    this.update()%0A
                 
@@ -2219,32 +2219,45 @@
 name%5D, removed)%0A
+%3C%3C%3C%3C%3C%3C%3C HEAD%0A
             if(t
@@ -2309,32 +2309,91 @@
 )%0A            %7D%0A
+=======%0A%3E%3E%3E%3E%3E%3E%3E parent of 20d032a... Performance enhancing%0A
             //ev
@@ -2426,21 +2426,21 @@
 s.emit(%22
-remov
+delet
 e%22, tabl
@@ -2455,16 +2455,42 @@
 emoved)%0A
+            this.update()%0A
         
@@ -3022,32 +3022,45 @@
 %5D%5Bindex%5D, data)%0A
+%3C%3C%3C%3C%3C%3C%3C HEAD%0A
                 
@@ -3124,32 +3124,91 @@
               %7D%0A
+=======%0A%3E%3E%3E%3E%3E%3E%3E parent of 20d032a... Performance enhancing%0A
                 
@@ -3297,16 +3297,46 @@
 index%5D)%0A
+                this.update()%0A
         
@@ -4504,126 +4504,8 @@
 ) %7B%0A
-        this.updateCalls++%0A            if (this.canCall) %7B%0A                this.previousCallTime = new Date()%0A        
     
@@ -4544,32 +4544,24 @@
 db)%0A        
-     
-   
 this.emit(%22w
@@ -4571,274 +4571,8 @@
 e%22)%0A
-            %7D%0A        if (this.updateCalls == this.canCallTreshold) %7B%0A            this.canCall = true%0A        %7D else if ((new Date() - this.previousCallTime) %3C 65) %7B%0A            this.canCallTreshold = this.updateCalls + 10%0A            this.canCall = false%0A        %7D%0A
     

Revert "Performance enhancing"