package org.jivesoftware.smackx.ikey.record;

import org.bouncycastle.openpgp.PGPSecretKeyRing;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.util.Objects;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.ikey.element.IkeyElement;
import org.jivesoftware.smackx.ikey.provider.IkeyElementProvider;
import org.jivesoftware.smackx.ox.OpenPgpSecretKeyBackupPassphrase;
import org.jxmpp.jid.EntityBareJid;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;

public class FileBasedIkeyStore implements IkeyStore {

    private final File baseFile;

    public FileBasedIkeyStore(File file) {
        this.baseFile = Objects.requireNonNull(file);
    }

    @Override
    public IkeyRecord loadIkeyRecord(EntityBareJid jid) throws IOException {
        File file = new File(baseFile, jid.asUrlEncodedString());
        return loadIkeyRecordFromFile(file);
    }

    @Override
    public void storeIkeyRecord(EntityBareJid jid, IkeyRecord record) throws IOException {
        File file = new File(baseFile, jid.asUrlEncodedString());
        writeIkeyRecordToFile(record, file);
    }

    @Override
    public IkeyRecord loadContenderIkeyRecord(EntityBareJid jid) throws IOException {
        File file = new File(baseFile, jid.asUrlEncodedString() + "_contender");
        return loadIkeyRecordFromFile(file);
    }

    @Override
    public void storeContenderIkeyRecord(EntityBareJid jid, IkeyRecord element) throws IOException {
        File file = new File(baseFile, jid.asUrlEncodedString());
        writeIkeyRecordToFile(element, file);
    }

    @Override
    public void clearContenderIkeyRecord(EntityBareJid jid) throws IOException {
        File file = new File(baseFile, jid.asUrlEncodedString() + "_contender");
        if (file.exists()) {
            file.delete();
        }
    }

    private void writeIkeyRecordToFile(IkeyRecord record, File file) throws IOException {
        if (!file.exists()) {
            file.createNewFile();
        }
        writeToFile(new FileOutputStream(file), record);
    }

    private static void writeToFile(FileOutputStream fos, Object object) throws IOException {

        try (ObjectOutputStream oout = new ObjectOutputStream(fos)) {
            oout.writeObject(object);
        }
    }

    private IkeyRecord loadIkeyRecordFromFile(File file) throws IOException {
        if (!file.exists() || file.isDirectory()) {
            return null;
        }
        return (IkeyRecord) readFile(file);
    }

    private static Object readFile(File file) {
        try (ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file))) {
            Object object = oin.readObject();
            return object;
        } catch (FileNotFoundException e) {
            throw new AssertionError(e);
        } catch (IOException | ClassNotFoundException e) {
            return null;
        }
    }

    private static String getFileContent(FileInputStream fis) throws IOException {
        try (BufferedReader br = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8))) {
            StringBuilder sb = new StringBuilder();
            String line;
            while((line = br.readLine()) != null) {
                sb.append(line);
                sb.append('\n');
            }
            return sb.toString();
        }
    }

    @Override
    public PGPSecretKeyRing loadSecretKey() {
        return null;
    }

    @Override
    public void storeSecretKey(PGPSecretKeyRing secretKey) {

    }

    @Override
    public OpenPgpSecretKeyBackupPassphrase loadBackupPassphrase() {
        return null;
    }

    @Override
    public void storeBackupPassphrase(OpenPgpSecretKeyBackupPassphrase passphrase) {

    }

}
