package org.yi.happy.archive.tag;

import java.io.IOException;
import java.util.List;

import org.yi.happy.archive.Fragment;
import org.yi.happy.archive.RetrieveBlock;
import org.yi.happy.archive.block.Block;
import org.yi.happy.archive.file_system.FileSystem;
import org.yi.happy.archive.file_system.RandomOutputFile;
import org.yi.happy.archive.key.FullKey;
import org.yi.happy.archive.restore.RestoreEngine;

/**
 * An incremental file restore process.
 */
public class RestoreFile {
    private final RestoreEngine engine;
    private final RetrieveBlock store;
    private final String path;
    private final FileSystem fs;

    /**
     * the number of blocks read and processed.
     */
    private int progress = 0;

    /**
     * initialize an incremental file restore process.
     * 
     * @param key
     *            the key to the file.
     * @param store
     *            the block source.
     * @param path
     *            the output file name.
     * @param fs
     *            the file system to use.
     */
    public RestoreFile(FullKey key, RetrieveBlock store, String path,
            FileSystem fs) {
        this.engine = new RestoreEngine(key);
        this.store = store;
        this.path = path;
        this.fs = fs;
    }

    /**
     * performs a restore step: if there is data ready, write it out to the
     * named file.
     * 
     * @throws IOException
     */
    public void step() throws IOException {
        engine.start();
        Fragment part = null;
        while (engine.findReady()) {
            Block block = store.retrieveBlock(engine.getKey());
            if (block == null) {
                engine.skip();
                continue;
            }
            part = engine.step(block);
            progress++;
            if (part != null) {
                break;
            }
        }

        if (part == null) {
            return;
        }

        RandomOutputFile f = fs.openRandomOutputFile(path);
        try {
            while (true) {
                if (part != null) {
                    f.writeAt(part.getOffset(), part.getData().toByteArray());
                    part = null;
                }

                if (engine.findReady() == false) {
                    break;
                }

                Block block = store.retrieveBlock(engine.getKey());
                if (block == null) {
                    engine.skip();
                    continue;
                }

                part = engine.step(block);
                progress++;
            }
        } finally {
            f.close();
        }
    }

    /**
     * check if the process is complete.
     * 
     * @return true if there is no more reading to do.
     */
    public boolean isDone() {
        return engine.isDone();
    }

    /**
     * get the list of blocks that are needed at this time.
     * 
     * @return the full keys of the blocks that are needed at this time.
     */
    public List<FullKey> getPending() {
        return engine.getNeeded();
    }

    /**
     * Get the number of blocks read and processed.
     * 
     * @return the number of blocks read and processed.
     */
    public int getProgress() {
        return progress;
    }

}

@@ -1459,54 +1459,83 @@
     
-engine.start();%0A        Fragment part = null;%0A
+RandomOutputFile out = null;%0A        try %7B%0A            engine.start();%0A    
     
@@ -1571,32 +1571,36 @@
 ) %7B%0A            
+ 
+   
 Block block = st
@@ -1639,32 +1639,36 @@
 ));%0A            
+    
 if (block == nul
@@ -1680,32 +1680,36 @@
                 
+   
+ 
 engine.skip();%0A 
@@ -1715,32 +1715,36 @@
                 
+    
 continue;%0A      
@@ -1729,32 +1729,36 @@
       continue;%0A
+    
             %7D%0A  
@@ -1759,32 +1759,45 @@
   %7D%0A            
+    Fragment 
 part = engine.st
@@ -1811,32 +1811,36 @@
 k);%0A            
+    
 progress++;%0A    
@@ -1839,32 +1839,36 @@
 ++;%0A            
+  
+  
 if (part != null
@@ -1887,44 +1887,8 @@
     
-    break;%0A            %7D%0A        %7D%0A%0A
     
@@ -1895,19 +1895,18 @@
     if (
-par
+ou
 t == nul
@@ -1926,53 +1926,23 @@
     
-return;%0A        %7D%0A%0A        RandomOutputFile f
+            out
  = f
@@ -1971,38 +1971,33 @@
 (path);%0A        
-try %7B%0A
+ 
             whil
@@ -1995,59 +1995,9 @@
     
- while (true) %7B%0A                if (part != null) %7B
+%7D
 %0A   
@@ -2013,17 +2013,19 @@
         
-f
+out
 .writeAt
@@ -2094,26 +2094,10 @@
     
-    part = null;%0A 
+%7D%0A
     
@@ -2100,39 +2100,34 @@
             
-   %7D%0A%0A 
+%7D%0A
         
        if (e
@@ -2118,168 +2118,20 @@
     
-       if (engine.findReady() == false) %7B%0A                    break;%0A                %7D%0A%0A                Block block = store.retrieveBlock(engine.getKey());%0A    
+%7D finally %7B%0A
     
@@ -2134,39 +2134,37 @@
             if (
-block =
+out !
 = null) %7B%0A      
@@ -2177,203 +2177,34 @@
     
-    
-engine.skip();%0A                    continue;%0A                %7D%0A%0A                part = engine.step(block);%0A                progress++;%0A            %7D%0A        %7D finally %7B%0A            f.close();
+out.close();%0A            %7D
 %0A   

restructure RestoreFile loop