package com.example.musicplayer.service;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;

import com.example.musicplayer.R;
import com.example.musicplayer.app.Api;
import com.example.musicplayer.app.Constant;
import com.example.musicplayer.download.DownloadListener;
import com.example.musicplayer.download.DownloadTask;
import com.example.musicplayer.entiy.DownloadInfo;
import com.example.musicplayer.event.DownloadEvent;
import com.example.musicplayer.event.SongListNumEvent;
import com.example.musicplayer.util.CommonUtil;
import com.example.musicplayer.util.DownloadUtil;
import com.example.musicplayer.view.MainActivity;

import org.greenrobot.eventbus.EventBus;
import org.litepal.LitePal;

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

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import static com.example.musicplayer.app.Constant.TYPE_DOWNLOADING;

/**
 * <pre>
 *     author : 残渊
 *     time   : 2019/04/08
 *     desc   : 下载服务,保证DownloadTask在后台运行
 * </pre>
 */

public class DownloadService extends Service {
    private static final String TAG = "DownloadService";
    private DownloadTask downloadTask;
    private String downloadUrl;
    private DownloadBinder downloadBinder = new DownloadBinder();
    private LinkedList<DownloadInfo> downloadQueue = new LinkedList<>();//等待队列
    private int position = 0;//下载歌曲在下载歌曲列表的位置
    private DownloadListener listener = new DownloadListener() {
        @Override
        public void onProgress(DownloadInfo downloadInfo) {
            downloadInfo.setStatus(Constant.DOWNLOAD_ING);
            EventBus.getDefault().post(new DownloadEvent(TYPE_DOWNLOADING, downloadInfo)); //通知下载模块
            if(downloadInfo.getProgress()!=100){
                getNotificationManager().notify(1, getNotification("正在下载: "+downloadInfo.getSongName(), downloadInfo.getProgress()));
            }else {
                if(downloadQueue.isEmpty()) getNotificationManager().notify(1, getNotification("下载成功",-1));
            }

        }

        @Override
        public void onSuccess() {
            downloadTask = null;
            DownloadInfo downloadInfo = downloadQueue.poll();
            operateDb(downloadInfo); //操作数据库
            start();//下载队列中的其它歌曲
            //下载成功通知前台服务通知关闭,并创建一个下载成功的通知
            stopForeground(true);
            if(downloadQueue.isEmpty()) getNotificationManager().notify(1, getNotification("下载成功",-1));
        }

        @Override
        public void onDownloaded() {
            downloadTask = null;
            CommonUtil.showToast(DownloadService.this, "已下载");
        }

        @Override
        public void onFailed() {
            downloadTask = null;

            //下载失败通知前台服务通知关闭,并创建一个下载失败的通知
            stopForeground(true);
            getNotificationManager().notify(1, getNotification("下载失败",-1));
            Toast.makeText(DownloadService.this, "下载失败", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onPaused() {
            downloadTask = null;
            DownloadInfo downloadInfo=downloadQueue.poll();//从下载列表中移除该歌曲
            updateDbOfPause(downloadInfo.getSongId());
            getNotificationManager().notify(1, getNotification("下载已暂停:"+downloadInfo.getSongName(), -1));
            start();//下载下载列表中的歌曲
            downloadInfo.setStatus(Constant.DOWNLOAD_PAUSED);
            EventBus.getDefault().post(new DownloadEvent(Constant.TYPE_DOWNLOAD_PAUSED, downloadInfo)); //下载暂停
            Toast.makeText(DownloadService.this, "下载已暂停", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onCanceled() {
            downloadTask = null;
            stopForeground(true);
            Toast.makeText(DownloadService.this, "下载已取消", Toast.LENGTH_SHORT).show();
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return downloadBinder;
    }

    public class DownloadBinder extends Binder {
        public void startDownload(DownloadInfo song) {
            try {
                postDownloadEvent(song);//通知正在下载界面
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (downloadTask != null) {
                CommonUtil.showToast(DownloadService.this, "已经加入下载队列");
            } else {
                CommonUtil.showToast(DownloadService.this, "开始下载");
                start();
            }
        }

        public void pauseDownload(String songId) {
            //暂停的歌曲是否为当前下载的歌曲
            if (downloadTask != null &&downloadQueue.peek().getSongId().equals(songId)) {
                downloadTask.pauseDownload();
            }else {//暂停的歌曲是下载队列的歌曲
                //将该歌曲从下载队列中移除
                for (int i = 0; i < downloadQueue.size(); i++) {
                    DownloadInfo downloadInfo = downloadQueue.get(i);
                    if (downloadInfo.getSongId().equals(songId)) {
                        downloadQueue.remove(i);
                        updateDbOfPause(downloadInfo.getSongId());
                        downloadInfo.setStatus(Constant.DOWNLOAD_PAUSED);
                        EventBus.getDefault().post(new DownloadEvent(Constant.TYPE_DOWNLOAD_PAUSED, downloadInfo)); //下载暂停
                    }
                }
            }
        }


        public void cancelDownload(DownloadInfo song) {
            String songId = song.getSongId();
            //如果该歌曲正在下载,则需要将downloadTask置为null
            if (downloadTask != null && downloadQueue.peek().getSongId().equals(songId)) {
                downloadTask.cancelDownload();
            }
            //将该歌曲从下载队列中移除
            for (int i = 0; i < downloadQueue.size(); i++) {
                DownloadInfo downloadInfo = downloadQueue.get(i);
                if (downloadInfo.getSongId().equals(songId)) downloadQueue.remove(i);
            }
            updateDb(songId);
            deleteDb(songId);
            //取消下载需要将文件删除并将通知关闭
            if (song.getUrl() != null) {
                checkoutFile(song,song.getUrl()); //实际文件长度
            }
            //通知正在下载列表
            EventBus.getDefault().post(new DownloadEvent(Constant.TYPE_DOWNLOAD_CANCELED));

        }

    }
    private void start() {
        if (downloadTask == null && !downloadQueue.isEmpty()) {
            DownloadInfo downloadInfo = downloadQueue.peek();
            List<DownloadInfo> songList =
                    LitePal.where("songId = ?",downloadInfo.getSongId()).find(DownloadInfo.class);
            DownloadInfo currentDownloadInfo = songList.get(0);
            currentDownloadInfo.setStatus(Constant.DOWNLOAD_READY);
            EventBus.getDefault().post(new DownloadEvent(TYPE_DOWNLOADING,currentDownloadInfo));
            downloadUrl = currentDownloadInfo.getUrl();
            downloadTask = new DownloadTask(listener);
            downloadTask.execute(currentDownloadInfo);
            getNotificationManager().notify(1, getNotification("正在下载:"+downloadInfo.getSongName(), 0));
        }
    }


    private NotificationManager getNotificationManager() {
        return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    }

    private Notification getNotification(String title,int progress) {
        Intent intent = new Intent(this, MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String id = "channel_001";
            String name = "下载通知";
            NotificationChannel mChannel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW);
            getNotificationManager().createNotificationChannel(mChannel);
            Notification.Builder builder = new Notification.Builder(this, id);
            builder.setSmallIcon(R.mipmap.icon);
            builder.setContentIntent(pi);
            builder.setContentTitle(title);
            if(progress>0){
                builder.setContentText(progress +"%");
                builder.setProgress(100, progress, false);
            }
            return builder.build();
        } else {
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "default");
            builder.setSmallIcon(R.mipmap.icon);
            builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.icon));
            builder.setContentIntent(pi);
            builder.setContentTitle(title);
            if(progress>0){
                builder.setContentText(progress +"%");
                builder.setProgress(100, progress, false);
            }
            return builder.build();
        }
    }

    private void operateDb(DownloadInfo downloadInfo) {
        updateDb(downloadInfo.getSongId());
        deleteDb(downloadInfo.getSongId());
        EventBus.getDefault().post(new DownloadEvent(Constant.TYPE_DOWNLOAD_SUCCESS));//通知已下载列表
        EventBus.getDefault().post(new SongListNumEvent(Constant.LIST_TYPE_DOWNLOAD)); //通知主界面的下载个数需要改变
    }

    //更新数据库中歌曲列表的位置,即下载完成歌曲后的位置都要减去1;
    private void updateDb(String songId) {
        long id = LitePal.select("id").where("songId = ?", songId).find(DownloadInfo.class).get(0).getId();
        List<DownloadInfo> songIdList = LitePal.where("id > ?", id + "").find(DownloadInfo.class);
        for (DownloadInfo song : songIdList) {
            song.setPosition(song.getPosition() - 1);
            song.save();
        }
    }

    //暂停时更新列表歌曲状态
    private void updateDbOfPause(String songId){
        List<DownloadInfo> statusList =
                LitePal.where("songId = ?",songId).find(DownloadInfo.class,true);
        DownloadInfo downloadInfo = statusList.get(0);
        downloadInfo.setStatus(Constant.DOWNLOAD_PAUSED);
        downloadInfo.save();
    }

    //下载完成时要删除下载歌曲表中的数据以及关联表中的数据
    private void deleteDb(String songId) {
        LitePal.deleteAll(DownloadInfo.class, "songId=?", songId);//删除已下载歌曲的相关列
    }

    private void postDownloadEvent(DownloadInfo downloadInfo) {
        //如果需要下载的表中有该条歌曲,则添加到下载队列后跳过
        List<DownloadInfo> downloadInfoList =
                LitePal.where("songId = ?",downloadInfo.getSongId()).find(DownloadInfo.class,true);
        if (downloadInfoList.size() != 0){
            DownloadInfo historyDownloadInfo = downloadInfoList.get(0);
            historyDownloadInfo.setStatus(Constant.DOWNLOAD_WAIT);
            historyDownloadInfo.save();
            EventBus.getDefault().post(new DownloadEvent(Constant.DOWNLOAD_PAUSED,historyDownloadInfo));
            downloadQueue.offer(historyDownloadInfo);
            return;
        }

        position = LitePal.findAll(DownloadInfo.class).size();
        downloadInfo.setPosition(position);
        downloadInfo.setStatus(Constant.DOWNLOAD_WAIT); //等待
        downloadInfo.save();
        downloadQueue.offer(downloadInfo);//将歌曲放到等待队列中
        EventBus.getDefault().post(new DownloadEvent(Constant.TYPE_DOWNLOAD_ADD));
    }


    //获取歌曲实际大小,然后判断是否存在于文件中
    public void checkoutFile(DownloadInfo song, String downloadUrl){
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder()
                    .url(downloadUrl)
                    .build();
                Call call= client.newCall(request);
                call.enqueue(new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {

                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        if(response.isSuccessful()){
                            long size = response.body().contentLength();
                            String fileName = DownloadUtil.getSaveSongFile(song.getSinger(),song.getSongName(),song.getDuration(),song.getSongId(),size);
                            File downloadFile = new File(Api.STORAGE_SONG_FILE);
                            String directory = String.valueOf(downloadFile);
                            File file = new File(fileName, directory);
                            if (file.exists()) {
                                file.delete();
                            }
                            getNotificationManager().cancel(1);
                            stopForeground(true);
                        }
                    }
                });
    }

}