package org.bdware.sc.db;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.sc.Jedion;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class KeyValueDBUtil {
    private static final Logger LOGGER = LogManager.getLogger(KeyValueDBUtil.class);
    public static KeyValueDBUtil instance;
    private final Map<String, Jedion> dbLink;
    public String dbPath;

    private KeyValueDBUtil(String path) {
        dbLink = new HashMap<>();
        dbPath = path;
    }

    public static void setupNC() {
        if (null == instance) {
            instance = new KeyValueDBUtil("./NodeCenterDB");
            LOGGER.info("init nc Jedion in ./NodeCenterDB");
        }
    }

    public static void setupCM() {
        if (null == instance) {
            instance = new KeyValueDBUtil("./ContractManagerDB");
            LOGGER.info("init cm Jedion in ./ContractManagerDB");
        }
    }

    private static void deleteJelck(File file) {
        if (file.exists()) {
            LOGGER.trace("delete file" + file.getAbsolutePath() + ": " + file.delete());
        }
    }

    private Jedion getDB(String dbName) {
        if (!dbLink.containsKey(dbName)) {
            setupDB(dbName);
        }
        return dbLink.get(dbName);
    }

    public boolean containsKey(String dbName, String key) {
        String res = getValue(dbName, key);
        return res != null && !res.isEmpty();
    }

    public List<String> getKeys(String dbName) {
        Jedion db = getDB(dbName);
        return db.getEveryItem();
    }

    public List<Jedion.KV> getKeyValues(String dbName) {
        Jedion db = getDB(dbName);
        return db.getEveryKeyValue();
    }

    public String getValue(String dbName, String key) {
        try {
            Jedion db = getDB(dbName);
            return db.readFromDatabase(key);
        } catch (Exception e) {
            return null;
        }
    }

    public void setValue(String dbName, String key, String value) {
        try {
            Jedion db = getDB(dbName);
            db.writeToDatabase(key, value, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void delete(String dbName, String key) {
        try {
            Jedion db = getDB(dbName);
            db.deleteFromDatabase(key);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void setupDB(String dbName) {
        Jedion db = new Jedion(dbName);
        File file = new File(dbPath + "/" + dbName);
        deleteJelck(new File(file, "je.lck"));
        if (!file.exists()) {
            LOGGER.trace("create directory " + file.getAbsolutePath() + ": " + file.mkdirs());
        }
        db.configEnvironment(file);
        db.createDatabase();
        dbLink.put(dbName, db);
    }

    public long getCount(String dbName) {
        try {
            Jedion db = getDB(dbName);
            return db.getCount();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0L;
    }

    public void visitDB(String dbName, Jedion.JedionVisitor visitor) {
        try {
            Jedion db = getDB(dbName);
            db.visitAllItem(visitor);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
