package lc.mecha.http.client;

import lc.mecha.log.MechaLogger;
import lc.mecha.log.MechaLoggerFactory;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Date;

public class PersistentCookieStore extends BasicCookieStore {
    private static final MechaLogger logger = MechaLoggerFactory.getLogger(PersistentCookieStore.class);
    private final Path outputPath;

    public PersistentCookieStore(Path outputPath) {
        this.outputPath = outputPath;
        logger.info("New PCS.");
    }

    public static PersistentCookieStore loadOrNew(Path db) throws IOException, ClassNotFoundException {
        File dbf = db.toFile();
        if (!dbf.exists()) {
            logger.info("Did not find existing persistent cookie store. Creating new store.");
            return new PersistentCookieStore(db);
        }

        try (ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(dbf)))) {
            return (PersistentCookieStore) ois.readObject();
        }
    }

    private synchronized void persist() {
        logger.info("Persisting cookie store. [fn: {}]", outputPath);

        try {
            File tmpFile = File.createTempFile("cookie", "tmp");
            try (ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(tmpFile)))) {
                oos.writeObject(this);
            }
            Files.move(tmpFile.toPath(), outputPath, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void addCookie(Cookie cookie) {
        logger.info("addCookie() called");
        super.addCookie(cookie);
        persist();
    }

    public void addCookies(final Cookie[] cookies) {
        logger.info("addCookies() called");
        super.addCookies(cookies);
        persist();
    }

    @Override
    public boolean clearExpired(Date date) {
        boolean b = super.clearExpired(date);
        persist();
        return b;
    }

    @Override
    public void clear() {
        super.clear();
        persist();
    }
}
