package com.yutou.nas.utils;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.event.ProgressEvent;
import com.aliyun.oss.event.ProgressEventType;
import com.aliyun.oss.event.ProgressListener;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.StorageClass;
import com.yutou.nas.interfaces.DownloadInterface;

import java.io.File;
import java.io.FileNotFoundException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;

public class OSSManager {
    public static final String TYPE_MUSIC = "oss-name-music";
    public static final String TYPE_PHOTO = "oss-name-photo";
    public static final String TYPE_DEPOT = "oss-name-depot";
    private static final List<String> uploadList = new ArrayList<>();

    private static OSS getOssClient() {
        return new OSSClientBuilder().build(ConfigTools.load(ConfigTools.CONFIG, "oss-url", String.class),
                ConfigTools.load(ConfigTools.CONFIG, "oss-id", String.class),
                ConfigTools.load(ConfigTools.CONFIG, "oss-key", String.class));
    }

    private static void closeClient(OSS oss) {
        oss.shutdown();
    }


    public static void upload(String type, String path, File... files) {
        if (uploadList.contains(path)) {
            Log.i("OSS", "当前路径正在上传 = " + path + ", 文件数量 = " + files.length);
            return;
        }
        boolean music = false, photo = false, depot = false;
        if (type.equals(TYPE_MUSIC) && !ConfigTools.load(ConfigTools.CONFIG, "oss-upload-music", boolean.class, false)) {
            music = true;
        }
        if (type.equals(TYPE_PHOTO) && !ConfigTools.load(ConfigTools.CONFIG, "oss-upload-photo", boolean.class, false)) {
            photo = true;
        }
        if (type.equals(TYPE_DEPOT) && !ConfigTools.load(ConfigTools.CONFIG, "oss-upload-depot", boolean.class, false)) {
            depot = true;
        }
        if (music || photo || depot) {
            System.out.println("music = " + music);
            System.out.println("photo = " + photo);
            System.out.println("depot = " + depot);
            System.out.println("type = " + type + ", path = " + path + ", files = " + Arrays.deepToString(files));
            System.out.println("------------------------------");
            return;
        }
        Log.i("OSS", "上传文件数:" + files.length);
        new Thread(() -> {
            uploadList.add(path);
            OSS client = getOssClient();
            try {
                for (File file : files) {
                    Log.i("OSS", "Next :" + file.getAbsolutePath());
                    if (file.isDirectory()) {
                        continue;
                    }
                    String uploadPath = file.getAbsolutePath().replace(path, "").replace(File.separator, "/");
                    if (uploadPath.startsWith("/")) {
                        uploadPath = uploadPath.substring(1);
                    }
                    String md5 = BinaryUtil.toBase64String(Tools.getFileMD5Byte(file));
                    String redisMd5=RedisTools.get(file.getAbsolutePath(),RedisTools.DATABASES_ALI_OSS);
                    if(!StringUtils.isEmpty(redisMd5)){
                        if(redisMd5.equals(md5)){
                            Log.i("OSS", "[本地]文件已存在:" + file.getName());
                            continue;
                        }
                    }
                    if (isExist(client, ConfigTools.load(ConfigTools.CONFIG, type, String.class), uploadPath, md5)) {
                        Log.i("OSS", "文件已存在:" + file.getName());
                        RedisTools.set(RedisTools.DATABASES_ALI_OSS,file.getAbsolutePath(),md5);
                        continue;
                    }
                    //client.putObject(ConfigTools.load(ConfigTools.CONFIG,type,String.class), uploadPath, file);
                    int limitSpeed = 1024 * 1024 * 8;
                    ObjectMetadata metadata = new ObjectMetadata();
                    metadata.setContentMD5(md5);
                    PutObjectRequest request = new PutObjectRequest(ConfigTools.load(ConfigTools.CONFIG, type, String.class), uploadPath, file);
                    request.setTrafficLimit(limitSpeed);
                    request.setMetadata(metadata);
                    /*request.withProgressListener(new ProgressListener() {
                        private long bytesWritten = 0;
                        private long totalBytes = -1;
                        private boolean succeed = false;
                        @Override
                        public void progressChanged(ProgressEvent progressEvent) {
                            long bytes = progressEvent.getBytes();
                            ProgressEventType eventType = progressEvent.getEventType();
                            switch (eventType){
                                case REQUEST_BYTE_TRANSFER_EVENT:
                                    this.bytesWritten += bytes;
                                    if (this.totalBytes != -1) {
                                        int percent = (int)(this.bytesWritten * 100.0 / this.totalBytes);
                                        System.out.println(file.getName()+" upload progress: " + percent + "%(" + this.bytesWritten + "/" + this.totalBytes + ")");
                                    } else {
                                        System.out.println( "upload ratio: unknown" + "(" + this.bytesWritten + "/...)");
                                    }
                                    break;
                            }
                        }
                    });*/
                    client.putObject(request);
                    Log.i("OSS", file.getName() + "已上传");
                    RedisTools.set(RedisTools.DATABASES_ALI_OSS,file.getAbsolutePath(),md5);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
            Log.i("OSS", "上传完成:" + files.length);
            closeClient(client);
            uploadList.remove(path);
        }).start();

    }

    public static void download(String type, String path, DownloadInterface downloadInterface) {
        new Thread(() -> {
            OSS oss = getOssClient();
            ObjectMetadata metadata = oss.getObjectMetadata(type, path);
            if (metadata.getObjectStorageClass() == StorageClass.Archive) {
                oss.restoreObject(type, path);
                do {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    metadata = oss.getObjectMetadata(type, path);
                } while (!metadata.isRestoreCompleted());
            }
            OSSObject obj = oss.getObject(type, path);
            File file = StreamTools.streamSave(obj.getObjectContent());
            if (file != null) {
                downloadInterface.onDownload(file);
            } else {
                downloadInterface.onError(new FileNotFoundException("没有该文件"));
            }
            closeClient(oss);
        }).start();
    }
    private static boolean isOssExist(OSS oss, String type, String path){
        return  oss.doesObjectExist(type, path, true);
    }
    public static boolean isExist(OSS oss, String type, String path, String md5) {
        if (oss == null) {
            return false;
        }
        boolean flag = oss.doesObjectExist(type, path, true);
        if (flag) {
            if (getFileMd5(oss, type, path).equals(md5)) {
                return true;
            }
        }
        return flag;
    }

    private static String getFileMd5(OSS client, String type, String path) {
        ObjectMetadata metadata = client.getObjectMetadata(type, path);
        return metadata.getContentMD5();
    }

    public static void main(String[] args) {
        //upload(TYPE_PHOTO, "Z:\\相机", new File[]{new File("Z:\\相机\\截图\\QQ截图20190630161109.png")});
        // getFileMd5(getOssClient(),TYPE_PHOTO,"截图/QQ截图20190630161109.png");
        File file=new File("Z:\\相机\\截图\\QQ截图20190630161109.png");
        file=new File("Z:\\相机\\北京\\MVI_0067.MOV");
//        String md5 = BinaryUtil.toBase64String(BinaryUtil.calculateMd5(StreamTools.fileToByte(new File("Z:\\相机\\北京\\MVI_0067.MOV"))));
       String  md5=BinaryUtil.toBase64String(Tools.getFileMD5Byte(file));
        System.out.println("md5 =" +md5);
        System.out.println(getFileMd5(getOssClient(), ConfigTools.load(ConfigTools.CONFIG, TYPE_PHOTO, String.class),"截图/QQ截图20190630161109.png"));
    }
}
