package id.iptek.utms.agent;

import id.iptek.utms.agent.model.FileReaderCacheObj;
import id.iptek.utms.agent.model.FileWriterCacheObj;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author jakar
 */
public final class HeartbeatFileCache {

    protected Logger logger = LoggerFactory.getLogger(HeartbeatFileCache.class);
    private static HeartbeatFileCache self = null;
    private FileWriterCacheObj writerObj;
    private FileReaderCacheObj readerObj;
    private String fileBaseDir = null;
    private int maxLinePerFile = 1000;
    private HeartbeatFileChangeListener listener;
    private final Object lock = new Object();

    private HeartbeatFileCache() {
    }

    public void setListener(HeartbeatFileChangeListener listener) {
        this.listener = listener;
    }

    public void setFileBaseDir(String fileBaseDir) {
        this.fileBaseDir = fileBaseDir;
    }

    public File startWriter(File file) throws IOException {
        synchronized (lock) {
            // there is previous writer, return old file
            File previousFile = null;
            if (writerObj != null) {
                previousFile = writerObj.getFile();
            } else {
                writerObj = new FileWriterCacheObj();
            }
            writerObj.pointToFile(file);
            return previousFile;
        }
    }

    public void setMaxLinePerFile(int maxLinePerFile) {
        this.maxLinePerFile = maxLinePerFile;
    }

    public int getMaxLinePerFile() {
        return maxLinePerFile;
    }

    public FileWriterCacheObj getWriter() {
        return writerObj;
    }

    public FileWriterCacheObj writeLine(String line) throws IOException {
        synchronized (lock) {
            if (writerObj == null) {
                logger.debug("Create new WriterObj!!");
                // create new file
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
                File newFile = new File(fileBaseDir, sdf.format(new Date()) + UUID.randomUUID().toString() + ".tmp");
                File oldFile = startWriter(newFile);
                logger.debug("Pointed to file: \"{}\"", newFile.getAbsolutePath());
                if (listener != null) {
                    listener.fileChanged(oldFile, newFile);
                }
                writerObj.writeLine(line);
                return writerObj;
            }
            if (!writerObj.writeLineWithMaxLineNo(maxLinePerFile, line)) {
                // create new file
                SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
                File newFile = new File(fileBaseDir, sdf.format(new Date()) + UUID.randomUUID().toString() + ".tmp");
                File oldFile = startWriter(newFile);
                logger.debug("Pointed to file: \"{}\"", newFile.getAbsolutePath());
                if (listener != null) {
                    listener.fileChanged(oldFile, newFile);
                }
                // write the un-written line above
                writerObj.writeLine(line);
                return writerObj;
            }
            return writerObj;
        }
    }

    public void setReaderObj(FileReaderCacheObj readerObj) {
        this.readerObj = readerObj;
    }

    public FileReaderCacheObj getReaderObj() {
        return readerObj;
    }
    
    public static HeartbeatFileCache getInstance() {
        if(self == null) {
            self = new HeartbeatFileCache();
        }
        return self;
    }

    public interface HeartbeatFileChangeListener {

        void fileChanged(File oldFile, File newFile);

    }
}
