content: package com.wm.remusic.downmusic;
  
  /**
   * Created by wm on 2016/4/12.
   */
  
  import android.content.Context;
  import android.content.Intent;
  import android.net.Uri;
  import android.text.TextUtils;
  import android.util.Log;
  import android.widget.Toast;
  
  import com.squareup.okhttp.OkHttpClient;
  import com.squareup.okhttp.Request;
  import com.squareup.okhttp.Response;
  import com.squareup.okhttp.ResponseBody;
  import com.wm.remusic.provider.DownFileStore;
  
  import java.io.BufferedInputStream;
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.RandomAccessFile;
  import java.util.ArrayList;
  import java.util.List;
  
  
  /**
   * Created by dzc on 15/11/21.
   */
  public class DownloadTask implements Runnable {
      private DownloadDBEntity dbEntity;
      private DownFileStore downFileStore;
      private OkHttpClient client;
      private Context mContext;
  
      private String id;
      private long totalSize;
      private long completedSize;         //  Download section has been completed
      //    private float percent;        //  Percent Complete
      private String url;
      private String saveDirPath;
      private RandomAccessFile file;
      private int UPDATE_SIZE = 50 * 1024;    // The database is updated once every 50k
      private int downloadStatus = DownloadStatus.DOWNLOAD_STATUS_INIT;
  
      private String fileName;    // File name when saving
      private String artist;
      private String temp = ".temp";
      private boolean isPreparingDown;
      private String TAG = "DownloadTask";
  
  
      private List<DownloadTaskListener> listeners;
  
      public DownloadTask(Context context) {
          mContext = context.getApplicationContext();
          listeners = new ArrayList<>();
          downFileStore = DownFileStore.getInstance(context);
      }
  
      public DownloadTask(Context context, Builder builder) {
          //  mContext = context.getApplicationContext();
          listeners = new ArrayList<>();
          downFileStore = DownFileStore.getInstance(context);
          init(builder);
      }
  
      private void init(Builder builder) {
          mContext = builder.context;
          fileName = builder.fileName;
          artist = builder.art;
          saveDirPath = builder.saveDirPath;
          completedSize = builder.completedSize;
          dbEntity = builder.dbEntity;
          url = builder.url;
          totalSize = builder.totalSize;
          completedSize = builder.completedSize;
          id = builder.id;
          downloadStatus = builder.downloadStatus;
          UPDATE_SIZE = builder.UPDATE_SIZE;
          listeners = builder.listeners;
  
      }
  
      public static class Builder {
  
          private String url;
          private String fileName = url;    // File name when saving
          private String art;
          private String saveDirPath;
          private Context context;
          private DownloadDBEntity dbEntity = null;
  
          private String id;
          private long totalSize;
          private long completedSize;         //  Download section has been completed
  
          private int UPDATE_SIZE = 50 * 1024;    // The database is updated once every 50k
  
          private int downloadStatus = DownloadStatus.DOWNLOAD_STATUS_INIT;
  
          private List<DownloadTaskListener> listeners = new ArrayList<>();
  
          public Builder(Context context) {
              this.context = context.getApplicationContext();
          }
  
  
          public Builder(Context context, String url) {
              this.url = url;
              this.context = context.getApplicationContext();
          }
  
          public Builder setFileName(String fileName) {
              this.fileName = fileName;
              return this;
          }
  
          public Builder setArtName(String art) {
              this.art = art;
              return this;
          }
  
          public Builder setSaveDirPath(String saveDirPath) {
              this.saveDirPath = saveDirPath;
              return this;
          }
  
          public Builder setId(String id) {
              this.id = id;
              return this;
          }
  
          public Builder setCache(int UPDATE_SIZE) {
              this.UPDATE_SIZE = UPDATE_SIZE;
              return this;
          }
  
  
          public Builder setCompletedSize(long completedSize) {
              this.completedSize = completedSize;
              return this;
          }
  
          public Builder setTotalSize(long totalSize) {
              this.totalSize = totalSize;
              return this;
          }
  
          public Builder setDBEntity(DownloadDBEntity dbEntity) {
              this.dbEntity = dbEntity;
              downloadStatus = dbEntity.getDownloadStatus();
              url = dbEntity.getUrl();
              id = dbEntity.getDownloadId();
              fileName = dbEntity.getFileName();
              art = dbEntity.getArtist();
              saveDirPath = dbEntity.getSaveDirPath();
              completedSize = dbEntity.getCompletedSize();
              totalSize = dbEntity.getTotalSize();
  
              return this;
          }
  
  
          public Builder setListeners(List<DownloadTaskListener> listeners) {
              this.listeners = listeners;
              return this;
          }
  
          public Builder setDownloadStatus(int downloadStatus) {
              this.downloadStatus = downloadStatus;
              return this;
          }
  
  
          public DownloadTask build() {
              // id = (saveDirPath + fileName).hashCode() + "";
  
              return new DownloadTask(context, this);
          }
  
      }
  
  
      @Override
      public void run() {
          Log.e("start", completedSize + "");
          downloadStatus = DownloadStatus.DOWNLOAD_STATUS_PREPARE;
          //  id = (saveDirPath + fileName).hashCode() + "";
  
          onPrepare();
  
          InputStream inputStream = null;
          BufferedInputStream bis = null;
          try {
              dbEntity = downFileStore.getDownLoadedList(id);
              file = new RandomAccessFile(saveDirPath + fileName, "rwd");
              if (dbEntity != null) {
                  completedSize = dbEntity.getCompletedSize();
                  totalSize = dbEntity.getTotalSize();
              }
              if (file.length() < completedSize) {
                  completedSize = file.length();
              }
              long fileLength = file.length();
              if (fileLength != 0 && totalSize == fileLength) {
                  downloadStatus = DownloadStatus.DOWNLOAD_STATUS_COMPLETED;
                  totalSize = completedSize = fileLength;
                  dbEntity = new DownloadDBEntity(id, totalSize, completedSize, url, saveDirPath, fileName, artist, downloadStatus);
                  downFileStore.insert(dbEntity);
                  Log.e(TAG, "file is completed , file length = " + fileLength + "  file totalsize = " + totalSize);
                  Toast.makeText(mContext, fileName + "已经下载完成", Toast.LENGTH_SHORT).show();
                  onCompleted();
                  return;
              } else if (fileLength > totalSize) {
                  completedSize = 0;
                  totalSize = 0;
              }
              downloadStatus = DownloadStatus.DOWNLOAD_STATUS_START;
  
              onStart();
              Request request = new Request.Builder()
                      .url(url)
                      .header("RANGE", "bytes=" + completedSize + "-")//  Http value set breakpoints RANGE
                      .addHeader("Referer", url)
                      .build();
              Log.e("comlesize", completedSize + "");
              file.seek(completedSize);
              Response response = client.newCall(request).execute();
              ResponseBody responseBody = response.body();
              if (responseBody != null) {
                  downloadStatus = DownloadStatus.DOWNLOAD_STATUS_DOWNLOADING;
                  if (totalSize <= 0)
                      totalSize = responseBody.contentLength();
  
                  inputStream = responseBody.byteStream();
                  bis = new BufferedInputStream(inputStream);
                  byte[] buffer = new byte[4 * 1024];
                  int length = 0;
                  int buffOffset = 0;
                  if (dbEntity == null) {
                      dbEntity = new DownloadDBEntity(id, totalSize, 0L, url, saveDirPath, fileName, artist, downloadStatus);
                      downFileStore.insert(dbEntity);
                  }
                  while ((length = bis.read(buffer)) > 0 && downloadStatus != DownloadStatus.DOWNLOAD_STATUS_CANCEL && downloadStatus != DownloadStatus.DOWNLOAD_STATUS_PAUSE) {
                      file.write(buffer, 0, length);
                      completedSize += length;
                      buffOffset += length;
                      if (buffOffset >= UPDATE_SIZE) {
                          // Update download information database
                          if (totalSize <= 0 || dbEntity.getTotalSize() <= 0)
                              dbEntity.setToolSize(totalSize);
                          buffOffset = 0;
                          dbEntity.setCompletedSize(completedSize);
                          dbEntity.setDownloadStatus(downloadStatus);
                          downFileStore.update(dbEntity);
                          onDownloading();
                      }
                  }
                  //这两句根据需要自行选择是否注释，注释掉的话由于少了数据库的读取，速度会快一点，但同时如果在下载过程程序崩溃的话，程序不会保存最新的下载进度
                  dbEntity.setCompletedSize(completedSize);
                  dbEntity.setDownloadStatus(downloadStatus);
                  downFileStore.update(dbEntity);
  
                  onDownloading();
              }
          } catch (FileNotFoundException e) {
              downloadStatus = DownloadStatus.DOWNLOAD_STATUS_ERROR;
              onError(DownloadTaskListener.DOWNLOAD_ERROR_FILE_NOT_FOUND);
              return;
  //            e.printStackTrace();
          } catch (IOException e) {
              downloadStatus = DownloadStatus.DOWNLOAD_STATUS_ERROR;
              onError(DownloadTaskListener.DOWNLOAD_ERROR_IO_ERROR);
              return;
          } finally {
  
              //String  nP = fileName.substring(0, path.length() - 5);
              dbEntity.setCompletedSize(completedSize);
              dbEntity.setFileName(fileName);
              downFileStore.update(dbEntity);
              if (bis != null) try {
                  bis.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
              if (inputStream != null) try {
                  inputStream.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
              if (file != null) try {
                  file.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
  
          }
          if (totalSize == completedSize) {
              String path = saveDirPath + fileName;
              File file = new File(path);
              Log.e("rename", path.substring(0, path.length() - 5));
              boolean c = file.renameTo(new File(path + ".mp3"));
              Log.e("rename", c + "");
  
              downloadStatus = DownloadStatus.DOWNLOAD_STATUS_COMPLETED;
              dbEntity.setDownloadStatus(downloadStatus);
              downFileStore.update(dbEntity);
              Uri contentUri = Uri.fromFile(new File(saveDirPath + fileName + ".mp3"));
              Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, contentUri);
              mContext.sendBroadcast(mediaScanIntent);
          }
  
  
          switch (downloadStatus) {
              case DownloadStatus.DOWNLOAD_STATUS_COMPLETED:
                  onCompleted();
                  break;
              case DownloadStatus.DOWNLOAD_STATUS_PAUSE:
                  onPause();
                  break;
              case DownloadStatus.DOWNLOAD_STATUS_CANCEL:
                  downFileStore.deleteTask(dbEntity.getDownloadId());
                  File temp = new File(saveDirPath + fileName);
                  if (temp.exists()) temp.delete();
                  onCancel();
                  break;
          }
      }
  
  
      public String getId() {
          return id;
      }
  
      public void setId(String id) {
          this.id = id;
      }
  
  
      public float getPercent() {
          if (totalSize == 0) {
              return 0;
          }
          return completedSize * 100 / totalSize;
      }
  
      public void setPreparingDown(boolean b) {
          isPreparingDown = b;
      }
  
      public boolean getPreparingDown() {
          return isPreparingDown;
      }
  
      public long getTotalSize() {
          return totalSize;
      }
  
      public void setTotalSize(long totalSize) {
          this.totalSize = totalSize;
      }
  
  
      public long getCompletedSize() {
          return completedSize;
      }
  
      public void setCompletedSize(long completedSize) {
          this.completedSize = completedSize;
      }
  
      public String getSaveDirPath() {
          return saveDirPath;
      }
  
      public void setSaveDirPath(String saveDirPath) {
          this.saveDirPath = saveDirPath;
      }
  
      public int getDownloadStatus() {
          return downloadStatus;
      }
  
      public void setDownloadStatus(int downloadStatus) {
          this.downloadStatus = downloadStatus;
      }
  
      public void setdownFileStore(DownFileStore downFileStore) {
          this.downFileStore = downFileStore;
      }
  
      public void setDbEntity(DownloadDBEntity dbEntity) {
          this.dbEntity = dbEntity;
      }
  
      public DownloadDBEntity getDbEntity() {
          return dbEntity;
      }
  
      public String getUrl() {
          return url;
      }
  
      public void setUrl(String url) {
          this.url = url;
      }
  
      public void setHttpClient(OkHttpClient client) {
          this.client = client;
      }
  
      public String getFileName() {
          return fileName;
      }
  
      public String getArtistName() {
          return artist;
      }
  
      public void setFileName(String fileName) {
          this.fileName = fileName;
      }
  
  
      public void cancel() {
          setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_CANCEL);
          File temp = new File(saveDirPath + fileName);
          if (temp.exists()) temp.delete();
      }
  
      public void pause() {
          setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_PAUSE);
      }
  
      private void onPrepare() {
          if (listeners == null) {
              return;
          }
          for (DownloadTaskListener listener : listeners) {
              listener.onPrepare(this);
          }
      }
  
      private void onStart() {
          if (listeners == null) {
              return;
          }
          for (DownloadTaskListener listener : listeners) {
              listener.onStart(this);
          }
      }
  
      private void onDownloading() {
          if (listeners == null) {
              return;
          }
          for (DownloadTaskListener listener : listeners) {
              listener.onDownloading(this);
          }
      }
  
      private void onCompleted() {
          if (listeners == null) {
              return;
          }
          for (DownloadTaskListener listener : listeners) {
              listener.onCompleted(this);
          }
      }
  
      private void onPause() {
          if (listeners == null) {
              return;
          }
          for (DownloadTaskListener listener : listeners) {
              listener.onPause(this);
          }
      }
  
      private void onCancel() {
          if (listeners == null) {
              return;
          }
          for (DownloadTaskListener listener : listeners) {
              listener.onCancel(this);
          }
      }
  
      private void onError(int errorCode) {
          if (listeners == null) {
              return;
          }
          for (DownloadTaskListener listener : listeners) {
              listener.onError(this, errorCode);
          }
      }
  
      public void addDownloadListener(DownloadTaskListener listener) {
          Log.e("downtask", (listeners == null) + "");
          if (listener != null)
              listeners.add(listener);
      }
  
      /**
       * if listener is null,clear all listener
       *
       * @param listener
       */
      public void removeDownloadListener(DownloadTaskListener listener) {
          if (listener == null) {
              listeners.clear();
          } else {
              listeners.remove(listener);
          }
      }
  
      @Override
      public boolean equals(Object o) {
          if (this == o) {
              return true;
          }
          if (!(o instanceof DownloadTask)) {
              return false;
          }
          if (TextUtils.isEmpty(url) || TextUtils.isEmpty(saveDirPath)) {
              return false;
          }
          return url.equals(((DownloadTask) o).url) && saveDirPath.equals(((DownloadTask) o).saveDirPath);
      }
  
      public static DownloadTask parse(DownloadDBEntity entity, Context context) {
          //  DownloadTask task = new DownloadTask(context);
          DownloadTask task = new Builder(context).setDBEntity(entity).build();
  
  //        task.setDownloadStatus(entity.getDownloadStatus());
  //        task.setId(entity.getDownloadId());
  //        task.setUrl(entity.getUrl());
  //        task.setFileName(entity.getFileName());
  //        task.setSaveDirPath(entity.getSaveDirPath());
  //        task.setCompletedSize(entity.getCompletedSize());
  //        task.setDbEntity(entity);
  //        task.setTotalSize(entity.getTotalSize());
          return task;
      }
  }
  