package com.golshadi.majid.core.chunkWorker;

import com.golshadi.majid.Utils.helper.FileUtils;
import com.golshadi.majid.database.elements.Chunk;
import com.golshadi.majid.database.elements.Task;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;

/**
 * Created by Majid Golshadi on 4/14/2014.
 */
public class AsyncWorker extends Thread{

    private final int BUFFER_SIZE = 1024;

    private final Task task;
    private final Chunk chunk;
    private final Moderator observer;
    private byte[] buffer;
    private ConnectionWatchDog watchDog;

    public boolean stop = false;


    public AsyncWorker(Task task, Chunk chunk, Moderator moderator){
        buffer = new byte[BUFFER_SIZE];

        this.task = task;
        this.chunk = chunk;
        this.observer = moderator;
    }


    @Override
	public void run() {
        try {
        	
            URL url = new URL(task.url);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(1000);
            connection.setReadTimeout(1000);
            if (chunk.end != 0) // support unresumable links
                connection.setRequestProperty("Range", "bytes=" + chunk.begin + "-" + chunk.end);
            
            connection.connect();
            

            File cf = new File(FileUtils.address(task.save_address, String.valueOf(chunk.id)));
            InputStream remoteFileIn = connection.getInputStream();
            FileOutputStream chunkFile = new FileOutputStream(cf, true);
            
            int len = 0;
            // set watchDoger to stop thread after 1sec if no connection lost
            watchDog = new ConnectionWatchDog(5000, this);
            watchDog.start();
            while (!this.isInterrupted() &&  
            		(len = remoteFileIn.read(buffer)) > 0) {
            	
            	watchDog.reset();
                chunkFile.write(buffer, 0, len);
                process(len);
            }
            
            chunkFile.flush();
            chunkFile.close();
            watchDog.interrupt();
            connection.disconnect();
            
            if (!this.isInterrupted()) {
            	observer.rebuild(chunk);
			}
            
           
        }catch (SocketTimeoutException e) {
        	e.printStackTrace();
        	
        	observer.connectionLost(task.id);
        	puaseRelatedTask();
        	
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return;
    }

    private void process(int read) {
        observer.process(chunk.task_id, read);
    }
    
    private void puaseRelatedTask()	{
    	observer.pause(task.id);
    }
    
    private boolean flag = true;
    public void connectionTimeOut(){
    	if (flag) {
    		watchDog.interrupt();
    		flag = false;
    		observer.connectionLost(task.id);
        	puaseRelatedTask();
		}
    	
    }

}

@@ -1209,24 +1209,115 @@
 nection();%0D%0A
+            %0D%0A            %09// Avoid timeout exception which usually occurs in low network%0D%0A
             
@@ -1337,35 +1337,32 @@
 tConnectTimeout(
-100
 0);%0D%0A           
@@ -1392,11 +1392,8 @@
 out(
-100
 0);%0D
@@ -1728,27 +1728,292 @@
         
-InputStream
+// Check response code first to avoid error stream%0D%0A            int status = connection.getResponseCode();%0D%0A           %09InputStream remoteFileIn;%0D%0A              if(status == 416)%0D%0A                remoteFileIn = connection.getErrorStream();%0D%0A              else%0D%0A               
  remoteF
@@ -2042,32 +2042,46 @@
 InputStream();%0D%0A
+            %0D%0A
             File

Update AsyncWorker.java