package com.gh.download;

import android.content.Context;
import android.text.TextUtils;

import com.gh.common.util.Utils;

import org.apache.http.HttpStatus;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class DownloadThread extends Thread {

	private static final int CONNECT_TIME = 5000;
	private static final int READ_TIME = 5000;

	private DownloadEntity entry;
	private DownloadListener listener;
	private DownloadStatus status;
	private Context context;

	public DownloadThread(Context context,
						  DownloadEntity entry,
						  DownloadListener listener) {
		this.entry = entry;
		this.listener = listener;
		this.context = context;
	}

	@Override
	public void run() {
		super.run();

		try {
			File targetFile = new File(entry.getPath());
			if (!targetFile.exists()) {
				File dir = targetFile.getParentFile();
				if (dir.exists() || dir.mkdirs()) {
					targetFile.createNewFile();
				}
			}

			FileOutputStream fileOutputStream;
			if (targetFile.length() > 0) {
				fileOutputStream = new FileOutputStream(entry.getPath(), true);
			} else {
				fileOutputStream = new FileOutputStream(entry.getPath());
			}

			URL url = new URL(entry.getUrl());
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			connection.setRequestMethod("GET");
			connection.setConnectTimeout(CONNECT_TIME);
			connection.setReadTimeout(READ_TIME);
			connection.setRequestProperty("RANGE",
					"bytes=" + targetFile.length() + "-");
			Utils.log(DownloadThread.class.getSimpleName(),
					"startPosition-->" + targetFile.length());
			//设置自动重定向
			connection.setInstanceFollowRedirects(true);
			
			int code = connection.getResponseCode();
			if (code == HttpStatus.SC_MOVED_PERMANENTLY
					|| code == HttpStatus.SC_MOVED_TEMPORARILY) {
				//未自动重定向
				String location = connection.getHeaderField("Location");
				Utils.log("location = " + location);
				url = new URL(location);
				connection = (HttpURLConnection) url.openConnection();
				connection.setRequestMethod("GET");
				connection.setConnectTimeout(CONNECT_TIME);
				connection.setReadTimeout(READ_TIME);
				connection.setRequestProperty("RANGE",
						"bytes=" + targetFile.length() + "-");
				Utils.log(DownloadThread.class.getSimpleName(),
						"startPosition-->" + targetFile.length());
				//设置自动重定向
				connection.setInstanceFollowRedirects(true);
			}

			BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
			BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);
			long conentLength = connection.getContentLength();
			String eTag = connection.getHeaderField("ETag");
			if (!TextUtils.isEmpty(eTag) && eTag.startsWith("\"") && eTag.endsWith("\"")) {
				eTag = eTag.substring(1, eTag.length() - 1);
			}
			String eTag2 = entry.getETag();
			if (!TextUtils.isEmpty(eTag2) && !eTag2.equals(eTag)) {
				//链接被劫持，抛出异常
				Utils.log("eTag = " + eTag);
				Utils.log("eTag2 = " + eTag2);
				listener.onStatusChanged(DownloadStatus.hijack);
				Utils.log(DownloadThread.class.getSimpleName(),
						"error-->链接被劫持");
				interrupt();
			} else {
				// 第一次下载记录文件长度
				if (entry.getSize() == 0) {
					entry.setSize(conentLength);
					DownloadDao.getInstance(context).newOrUpdate(entry);
					Utils.log(DownloadThread.class.getSimpleName(),
							"记录第一次长度");
				}
				Utils.log(DownloadThread.class.getSimpleName(),
						"progress:" + entry.getProgress() + "/curfilesize:"
								+ targetFile.length() + "=====contentLength:"
								+ conentLength + "/ totalSize:" + entry.getSize());
				
				byte[] buffer = new byte[2048];
				int len;
				while ((len = bis.read(buffer)) != -1) {
					bos.write(buffer, 0, len);
					listener.onProgressChanged(targetFile.length(), len);
					if (status == DownloadStatus.pause
							|| status == DownloadStatus.cancel) {
						listener.onStatusChanged(status);
						break;
					}
				}
				if (status != DownloadStatus.pause
						&& status != DownloadStatus.cancel) {
					listener.onStatusChanged(DownloadStatus.done);
				}
				bos.flush();
				Utils.log(DownloadThread.class.getSimpleName(),
						"flush==>" + targetFile.length() + ",progress==>"
								+ entry.getProgress());
				
				bis.close();
				bos.close();
			}
		} catch (Exception e) {
			//e.getMessage() will null error
			if (!TextUtils.isEmpty(e.getMessage()) && e.getMessage().contains("connection timeout")) {
				listener.onStatusChanged(DownloadStatus.timeout);
			} else {
				listener.onStatusChanged(DownloadStatus.neterror);
			}
			Utils.log(DownloadThread.class.getSimpleName(),
					"exception-->" + e.toString());
		}
	}

	public void setStatus(DownloadStatus status) {
		this.status = status;
	}

}
