package jp.sourceforge.shovel.xa;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.transaction.xa.XAException;
import javax.transaction.xa.Xid;

import org.seasar.extension.jta.xa.DefaultXAResource;
import org.seasar.framework.exception.SXAException;

import jp.sourceforge.shovel.SizeType;
import jp.sourceforge.shovel.entity.IServerFile;
import jp.sourceforge.shovel.exception.ApplicationException;

/**
 * ファイル管理
 */
public class XAServerFile extends DefaultXAResource {
    class Work {
        IServerFile serverFile_;
        SizeType sizeType_;
        
        IServerFile getServerFile() {
            return serverFile_;
        }
        void setServerFile(IServerFile serverFile) {
            serverFile_ = serverFile;
        }
        SizeType getSizeType() {
            return sizeType_;
        }
        void setSizeType(SizeType sizeType) {
            sizeType_ = sizeType;
        }
        void commit() throws ApplicationException {
            serverFile_.commit(sizeType_);
        }
    }
    
    String root_;
    List<IServerFile> copies_;
    List<IServerFile> removes_;
    List<Work> works_;
    
    public void setCommonProperties( Properties commonProperties ) throws ApplicationException {
        root_ = commonProperties.getProperty("files.dir");
        File dir = new File(root_);
        if (!dir.isDirectory() || !dir.canWrite()) {
            //TODO
            ApplicationException ex = new ApplicationException("");
            ex.setCauseArgs(dir.getPath());
            throw ex;
        }
    }
    protected void doBegin(Xid xid) throws XAException {
        try {
        } catch(Exception ex) {
            throw new SXAException(ex);
        }
    }
    protected void doCommit(Xid xid, boolean onePhase) throws XAException {
        try {
        } catch(Exception e) {
            throw new SXAException(e);
        }
    }
    protected int doPrepare(Xid xid) throws XAException {
        try {
            //TODO ロールバックに備えた処理を書く
            if (copies_ != null) {
                for (IServerFile copy : copies_) {
                    copy.commit(0);
                }
            }
            if (removes_ != null) {
                for (IServerFile remove : removes_) {
                    remove.commit(1);
                }
            }
            if (works_ != null) {
                for (Work work : works_) {
                    work.commit();
                }
            }
            return XA_OK;
        } catch(Exception e) {
            throw new SXAException(e);
        }
    }
    protected void doRollback(Xid xid) throws XAException {
        try {
            //TODO ちゃんとロールバックの処理も書く
            //削除は一時ディレクトリから復帰
            //TODO コピーはコピー先を記憶
            if (copies_ != null) {
                copies_.clear();
            }
            if (removes_ != null) {
                removes_.clear();
            }
            if (works_ != null) {
                works_.clear();
            }
        } catch(Exception e) {
            throw new SXAException(e);
        }
    }
    public void addToCopy(IServerFile serverFile) {
        if (copies_ == null) {
            copies_ = new ArrayList<IServerFile>();
        }
        copies_.add(serverFile);
    }
    public void addToRemove(IServerFile serverFile) {
        if (removes_ == null) {
            removes_ = new ArrayList<IServerFile>();
        }
        removes_.add(serverFile);
    }
    public void addToWork(IServerFile serverFile, SizeType sizeType) {
        if (works_ == null) {
            works_ = new ArrayList<Work>();
        }
        Work work = new Work();
        work.setServerFile(serverFile);
        work.setSizeType(sizeType);
        works_.add(work);
    }
}
