/**
 * 
 */
package org.forkalsrud.album.db;

import java.nio.charset.Charset;

import org.forkalsrud.album.web.CachedImage;

import com.sleepycat.bind.tuple.TupleBinding;
import com.sleepycat.bind.tuple.TupleInput;
import com.sleepycat.bind.tuple.TupleOutput;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Environment;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.Transaction;

/**
 * @author knut
 * 
 */
public class ThumbnailDatabase extends TupleBinding<CachedImage> {

    private static Charset UTF8 = Charset.forName("utf-8");
    
    private Environment environment;
    private Database db;

    public ThumbnailDatabase(Environment environment) {

        this.environment = environment;

        String dbname = "thumbnails";

        DatabaseConfig databaseConfig = new DatabaseConfig();
        databaseConfig.setAllowCreate(true);
        databaseConfig.setTransactional(true);
        // perform other database configurations
        this.db = environment.openDatabase(null, dbname, databaseConfig);
    }

    public void close() {
        db.close();
    }
    
    public long size() {
        return db.count();
    }

    public CachedImage load(String key) {

        DatabaseEntry data = new DatabaseEntry();
        Transaction txn = environment.beginTransaction(null, null);
        OperationStatus status = db.get(txn, key(key), data, null);
        txn.commitNoSync();
        if (OperationStatus.SUCCESS.equals(status)) {
            return entryToObject(data);
        } else {
            return null;
        }
    }

    public void store(String key, CachedImage img) {

        DatabaseEntry data = new DatabaseEntry();
        objectToEntry(img, data);
        DatabaseEntry binKey = key(key);
        Transaction txn = environment.beginTransaction(null, null);
        db.delete(txn, binKey);
        db.put(txn, binKey, data);
        txn.commitSync();
    }


    private DatabaseEntry key(String key) {
        DatabaseEntry returnValue = new DatabaseEntry();
        returnValue.setData(key.getBytes(UTF8));
        return returnValue;
    }


    @Override
    public CachedImage entryToObject(TupleInput in) {

        CachedImage img = new CachedImage();
        int version = in.readInt();
        if (version != 1) {
            throw new RuntimeException("I only understand version 1");
        }
        img.lastModified = in.readLong();
        img.mimeType = in.readString();
        int lobLen = in.readInt(); 
        img.bits = new byte[lobLen];
        if (lobLen > 0) {
            in.read(img.bits, 0, lobLen);
        }
        return img;
    }


    @Override
    public void objectToEntry(CachedImage img, TupleOutput out) {

        out.writeInt(1);  // version 1
        out.writeLong(img.lastModified);
        out.writeString(img.mimeType);
        if (img.bits != null) {
            out.writeInt(img.bits.length);
            out.write(img.bits);
        } else {
            out.writeInt(0);
        }
    }

}
