package org.maachang.comet.httpd.engine.script.image;

import java.io.IOException;

import org.maachang.dbm.MDbm;
import org.maachang.util.ConvertParam;

/**
 * イメージマネージャ実装.
 * 
 * @version 2008/01/27
 * @author masahito suzuki
 * @since MaachangComet 1.07
 */
class ImageOpImpl implements ImageOp {
    
    private static final int SEQ_NO = 0 ;
    private static final int KEY_LEN = 16 ;
    private static final byte[] HEAD = {
        ( byte )0x00,( byte )0x00,( byte )0x00,( byte )0x00,
        ( byte )0x01,( byte )0x03,( byte )0x0a,( byte )0x09 } ;
    private MDbm mdbm = null ;
    
    private ImageOpImpl() {
        
    }
    
    protected ImageOpImpl( MDbm mdbm ) {
        this.mdbm = mdbm ;
    }
    
    protected void finalize() throws Exception {
        this.destroy() ;
    }
    
    protected void destroy() {
        try {
            mdbm.commit() ;
        } catch( Exception e ) {
        }
        mdbm = null ;
    }
    
    public void commit() throws Exception {
        if( check() == false ) {
            throw new IOException( "既に破棄されています" ) ;
        }
        this.mdbm.commit() ;
    }
    
    public void rollback() throws Exception {
        if( check() == false ) {
            throw new IOException( "既に破棄されています" ) ;
        }
        this.mdbm.rollback() ;
    }
    
    public long add( int type,byte[] image ) throws Exception {
        if( check() == false ) {
            throw new IOException( "既に破棄されています" ) ;
        }
        if( type < 0 || type >= ImageData.IMAGE_MIME.length ||
            image == null || image.length <= 0 ) {
            throw new IllegalArgumentException( "引数は不正です" ) ;
        }
        long id = mdbm.sequenceId( SEQ_NO ) ;
        byte[] key = imageId( id ) ;
        byte[] value = ImageData.save( type,System.currentTimeMillis(),image ) ;
        mdbm.put( key,value ) ;
        return id ;
    }
    
    public void set( int type,byte[] image,long id ) throws Exception {
        if( check() == false ) {
            throw new IOException( "既に破棄されています" ) ;
        }
        if( id < 0L || type < 0 || type >= ImageData.IMAGE_MIME.length ||
            image == null || image.length <= 0 ) {
            throw new IllegalArgumentException( "引数は不正です" ) ;
        }
        byte[] key = imageId( id ) ;
        byte[] value = ImageData.save( type,System.currentTimeMillis(),image ) ;
        mdbm.put( key,value ) ;
    }
    
    public ImageData get( long id ) throws Exception {
        if( check() == false ) {
            throw new IOException( "既に破棄されています" ) ;
        }
        if( id < 0L ) {
            throw new IllegalArgumentException( "引数は不正です" ) ;
        }
        byte[] bin = mdbm.get( imageId( id ) ) ;
        if( bin != null ) {
            return ImageData.load( bin ) ;
        }
        return null ;
    }
    
    public synchronized void remove( long id ) throws Exception {
        if( check() == false ) {
            throw new IOException( "既に破棄されています" ) ;
        }
        if( id < 0L ) {
            throw new IllegalArgumentException( "引数は不正です" ) ;
        }
        mdbm.remove( imageId( id ) ) ;
    }
    
    public MDbm getMDbm() {
        return mdbm ;
    }
    
    public boolean isImageId( long id ) {
        if( check() == false || id < 0L ) {
            return false ;
        }
        boolean ret = false ;
        try {
            ret = mdbm.containsKey( imageId( id ) ) ;
        } catch( Exception e ) {
            ret = false ;
        }
        return ret ;
    }
    
    public String getDirectory() {
        if( check() == true ) {
            return mdbm.getDirectory() ;
        }
        return null ;
    }
    
    public boolean isWrite() {
        boolean ret = false ;
        try {
            if( mdbm != null ) {
                if( mdbm.isUse() == true ) {
                    mdbm.check() ;
                    ret = true ;
                }
            }
        } catch( Exception e ) {
            ret = false ;
        }
        return ret ;
    }
    
    private boolean check() {
        return ( mdbm != null && mdbm.isUse() == true ) ;
    }
    
    private byte[] imageId( long id ) {
        if( id < 0L ) {
            return null ;
        }
        byte[] ret = new byte[ KEY_LEN ] ;
        int len = HEAD.length ;
        System.arraycopy( HEAD,0,ret,0,len ) ;
        ConvertParam.convertLong( ret,len,id ) ;
        return ret ;
    }
}
