package cn.pluss.platform.util;


import cn.jiguang.common.utils.StringUtils;
import cn.pluss.platform.config.OssConfig;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.*;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyun.oss.model.PutBucketImageRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * aliyun oss upload utils
 */
@Component
public class OssOperatUtil {

    private static Logger logger = LoggerFactory.getLogger(OssOperatUtil.class);

    @Autowired
    private OssConfig ossConfig;

    private static OssConfig  config = null;

    public static  final String  APP_PATH = "app/";

    public static  final String  IMAGE_PATH = "images/";

    public static final  String imageType = "jpg|png|jpeg|bmp|tif|svg";

    public static final  String appType = "apk|ipa";

    public static final  String OTHER_PATH = "other/";

    //利用@PostConstruct将yml中配置的值赋给本地的变量
    @PostConstruct
    public void getConfig(){
        config = this.ossConfig;
    }


    /**
     * OSS上传 上传公开文件至公共读写bucket
     * @author LH_Yu
     * @Param fileType 文件类型
     * @Param is 上传文件
     * @Param fileName
     * @Param suffix 文件后缀名
     */
    public static String upload(InputStream is, String fileName, String suffix) {
        OSS client = null;
        String folderName = null;
        try{
            if(StringUtil.isEmpty(suffix)){
                logger.error("===========>上传文件后缀名不能为空<============");
                return null;
            }
            if(".".contains(suffix)){
                suffix = suffix.replace(".","");
            }
            if(imageType.contains(suffix)){
                folderName = IMAGE_PATH;
            }else if(appType.contains(suffix)){
                folderName = APP_PATH;
            }else{
                folderName = OTHER_PATH;
            }
            client = config.ossClient();
            String fileKey = folderName + fileName +"."+suffix;
            client.putObject(config.getBucketname(),fileKey , is);
            client.shutdown();
            return getUrl(fileKey);
        } catch (Exception e){
            logger.error("===============上传文件至oss服务器出错，错误信息：{}===============",e.getMessage());
            e.printStackTrace();
        }
        return null;
    }


    public static String upload(File file, String suffix) {
        OSS client = null;
        try{
            client = config.ossClient();
            String fileName = file.getName();
            String folderName = null;
            if(imageType.contains(suffix)){
                folderName = IMAGE_PATH;
            }else if(appType.contains(suffix)){
                folderName = APP_PATH;
            }else{
                folderName = OTHER_PATH;
            }
            String fileKey = folderName + fileName;
            client.putObject(config.getBucketname(),fileKey,file);
            client.shutdown();
            return getUrl(fileKey);
        } catch (Exception e){
            logger.error("===============上传文件至oss服务器出错，错误信息：{}===============",e.getMessage());
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 获得url链接
     *
     * @param key
     * @return
     */
    public static String getUrl(String key) {
        // 设置URL过期时间为10年 3600l* 1000*24*365*10
        OSS oss = config.ossClient();
        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
        // 生成URL
        URL url = oss.generatePresignedUrl(config.getBucketname(), key, expiration);
        oss.shutdown();
        if (url != null) {
            return url.toString();
        }
        return null;
    }
    /**
     * OSS下载文件
     * @param filename
     * @param path
     * @return
     */
    public static boolean download(String filename, String path){
        boolean flag = false;
        try{
            OSS oss = config.ossClient();
            oss.getObject(new GetObjectRequest(config.getBucketname(), filename), new File(path));
            oss.shutdown();
        }catch(Exception e){
            logger.error("===============从OSS下载文件出错，错误信息：{}===============", e);
            return flag;
        }
        logger.info("===============从OSS下载文件成功！===============");
        return true;
    }

    /**
     * 创建文件夹
     * @param folderName
     * @return
     */
    public static boolean createFolder(String folderName){
        try {
            OSS oss = config.ossClient();
            if(StringUtils.isEmpty(folderName)){
                return false;
            }
            if(!folderName.endsWith("/")){
                folderName = folderName + "/";
            }
            //Create an empty folder without request body, note that the key must be suffixed with a slash
            oss.putObject(config.getBucketname(), folderName, new ByteArrayInputStream(new byte[0]));
            oss.shutdown();
            logger.info("===============OSS创建文件夹成功===============");
            return true;
        } catch (OSSException oe) {
            logger.error("===============OSS创建文件夹异常，异常信息：{}===============" ,oe);
        } catch (ClientException ce) {
            logger.error("===============OSS创建文件夹异常，异常信息：{}===============" ,ce);
        }
        return false;
    }

    /**
     * 删除文件
     *
     * @param filename   文件名字(全名-路径+文件名)
     * @return
     */
    public static boolean deleteFile(String filename){
        try {
            OSS oss = config.ossClient();
            if(StringUtils.isEmpty(filename)){
                return false;
            }
            oss.deleteObject(config.getBucketname(), filename);
            oss.shutdown();
            return true;
        } catch (OSSException oe) {
            logger.error("===============OSS删除文件异常，异常信息：{}===============" ,oe);
        } catch (ClientException ce) {
            logger.error("===============OSS删除文件异常，异常信息：{}===============" ,ce);
        }
        return false;
    }

    /**
     * 删除oss链接形式的文件
     * @param url
     * @return
     */
    public static boolean deleteUrlFile(String url){
        try {
            URI uri = new URI(url);
            String host = uri.getScheme()+"://" + uri.getHost() + "/";
            String domain = url.split("\\?")[0];
            String fileKey = domain.replace(host, "");
            return deleteFile(fileKey);
        } catch (URISyntaxException e) {
            e.printStackTrace();
            logger.error("阿里云oss文件删除失败，失败原因：{}",e.getMessage());
            return false;
        }
    }

    public static Map<String,String> getUploadParam() {
        logger.info("==============>获取上传参数:{}<===================",config);
        Map<String,String> result = new HashMap<>(7);
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(config.getEndpoint(), config.getKeyid(), config.getKeysecret());
        try {
            long expireTime = 60;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            String dir = OssOperatUtil.APP_PATH;
            String enpoint = config.getEndpoint().replace("https://","").replace("http://","");
            String host = "https://" + config.getBucketname() + "." + enpoint; // host的格式为 bucketname.endpoint
            // callbackUrl为 上传回调服务器的URL，请将下面的IP和Port配置为您自己的真实信息。
            // PostObject请求最大可支持的文件大小为5 GB，即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            JSONObject jasonCallback = new JSONObject();
            jasonCallback.put("callbackUrl", config.getCallback());
            jasonCallback.put("callbackBody",
                    "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
            jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
            String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
            String key = UUID.randomUUID().toString().replace("-","").toUpperCase();
            result.put("accessid", config.getKeyid());
            result.put("policy", encodedPolicy);
            result.put("signature", postSignature);
            result.put("key", dir+key);
            result.put("host", host);
            result.put("expire", String.valueOf(expireEndTime / 1000));
            result.put("callBack",base64CallbackBody);
            return result;
        } catch (Exception e) {
        } finally {
            ossClient.shutdown();
        }
        return result;
    }
}
