package com.bcxin.identify.util.codes;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.bcxin.identify.util.file.obs.OBSUtil;
import com.bcxin.identify.util.sys.ConfigUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 * <b> 腾讯m3u8格式文件转mp4存到华为云服务器 </b>
 * @author ZXF
 * @create 2020/07/07 0007 15:19
 * @version
 * @注意事项 </b>
 */
public class M3u8ToMp4 {

    /**
     * 默认文件上传路径
     */
    private final static String DEFAULT_UPLOAD_DIR = "upload";

    private final static String DEFAULT_TEMP_DIR = "temp";

    private final static String QRCODE_DIR = "qrcode";

    /**
     * <b> 通过m3u8文件地址生成mp4文件地址 </b>
     * @param m3u8Url 要转的文件地址
     * @param platform 当前环境
     * @author ZXF
     * @create 2020/07/07 0007 15:04
     * @version
     * @注意事项 </b>
     */
    public static String getMp4ByM3u8(String m3u8Url, String platform) {
        //通过m3u8文件获取完整的ts文件地址
        Map<String,String> map = readFileContent(m3u8Url);
        if(map == null){
            return "";
        }
        //读取ts文件流转换成mp4文件存储到华为云服务器
        return saveMp4ByTs(map.get("fileName"),map.get("tsUrl"),platform,map.get("pm"));
    }

    public static Map<String,String> readFileContent(String url) {
        InputStream inStream = null;
        BufferedReader reader = null;
        String flo = "";
        String pm = "1280x720";
        List<String> list = Lists.newArrayList();
        try {
            URL u = new URL(url);
            HttpURLConnection conn = (HttpURLConnection)u.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5 * 1000);
            inStream = conn.getInputStream();//通过输入流获取图片数据
            reader = new BufferedReader(new InputStreamReader(inStream));
            String tempStr = "";
            int sign = 0;
            while ((tempStr = reader.readLine()) != null) {
                if(tempStr.contains("#EXT-X-ENDLIST")){
                    break;
                }
                if(sign == 1){
                    sign = 0;
                    if(StringUtils.isEmpty(flo)){
                        flo = tempStr.split(".ts")[0]+".ts";
                        pm = tempStr.split("&resolution=")[1];
                        list.add(flo);
                    }else{
                        if(!tempStr.contains(flo)){
                            flo = tempStr.split(".ts")[0]+".ts";
                            list.add(flo);
                        }
                    }
                }
                if(tempStr.contains("EXTINF:")){
                    sign = 1;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inStream != null) {
                try {
                    inStream.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
        if(list.size()>0){
            String ts = url.replace("playlist.m3u8","");
            String tsLinux = mergeStream(ts,list);
            if(StringUtils.isNotEmpty(ts)){
                Map<String,String> map = Maps.newHashMap();
                System.out.println("============================tsLinux:"+tsLinux);
                System.out.println("============================fileName:"+flo);
                map.put("fileName",flo);
                map.put("tsUrl",tsLinux);
                map.put("pm",pm);
                return map;
            }
        }
        return null;
    }

    public static String saveMp4ByTs(String fileName, String fileUrl,String platform,String pm){
        if (StringUtils.isNotEmpty(fileUrl)) {
            fileName = fileName.replace(".ts",".mp4");
            System.out.println("============================fileName:"+fileName);
            //ffmpeg转h264，耗服务性能高，目前不采用，如果要使用解开下列注释new File(fileUrl)改成new File(outFile)
            String outFile = ConfigUtil.getValue("DEFAULT_UPLOAD_LINUX")+fileName;
            transfer(fileUrl,outFile,pm);
            try(InputStream inStream = new FileInputStream(new File(outFile))) {
                /* 生成目录 */
                String directoryName = DEFAULT_UPLOAD_DIR + "/" + DateUtil.today() + "/";
                String ossKey = DEFAULT_UPLOAD_DIR + "/" + DateUtil.today() + "/" + fileName;
                OBSUtil obsUtil = new OBSUtil(platform);
		        /* 利用jdk7的特性，执行完后自动关闭流对象 */
                return obsUtil.put(directoryName, ossKey, inStream);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if(StringUtils.isNotEmpty(fileUrl)){
                    FileUtil.clean(fileUrl);
                }
                if(StringUtils.isNotEmpty(outFile)){
                    FileUtil.clean(outFile);
                }
            }
        }
        return "";
    }

    private static String mergeStream(String headUrl, List<String> list){
        try {
            ArrayList<InputStream> c = new ArrayList<InputStream>();
            for (String flo : list) {
                URL u = new URL(headUrl+flo);
                HttpURLConnection conn = (HttpURLConnection)u.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5 * 1000);
                c.add(conn.getInputStream());
            }
            Enumeration<InputStream> e = Collections.enumeration(c);
            SequenceInputStream sis = new SequenceInputStream(e);
            String fileName = UUID.randomUUID().toString()+".ts";
            String path = ConfigUtil.getValue("DEFAULT_UPLOAD_LINUX")+fileName;
            System.out.println("=============11=============fileName:"+fileName);
            isFile(sis,ConfigUtil.getValue("DEFAULT_UPLOAD_LINUX"),fileName);
            return path;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * <b>
     *     inStream流文件写入，专门帮助为输入流形式的文件读写操作
     * </b>
     * @param inStream 文件读到的流（可以是由HttpURLConnection访问某个第三方地址获取到流）
     * @param path 保存文件的路径（/data/upload/blb/policy/）
     * @param fileName 文件命名（123.pdf）
     * @author ZXF
     * @create 2018/06/08 0008 14:14
     * @version
     * @注意事项 </b>
     */
    public static void isFile(InputStream inStream, String path, String fileName){
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            bis = new BufferedInputStream(inStream);
            File fileP = new File(path);
            if (!fileP.exists()) {
                fileP.mkdirs();
            }
            File file = new File(path + fileName);
            bos = new BufferedOutputStream(new FileOutputStream(file, true));
            byte[] buff = new byte[2048];
            int bytesRead;
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);
            }
            bos.write("\r\n".getBytes());
            bos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    public static void transfer(String infile,String outfile,String pm) {
        String videoCommend = ConfigUtil.getValue("DEFAULT_FFMPEG_LINUX") + " -i " + infile + " -vcodec libx264 -r 29.97 -b 768k -ar 24000 -ab 64k -s "+pm+" "
                + outfile;
        System.out.println("============================videoCommend:"+videoCommend);
        try {
            Runtime rt = Runtime.getRuntime();
            Process proc = rt.exec(videoCommend);
            InputStream stderr = proc.getErrorStream();
            InputStreamReader isr = new InputStreamReader(stderr);
            BufferedReader br = new BufferedReader(isr);
            String line;

            while ( (line = br.readLine()) != null){
                System.out.println(line);
            }

            int exitVal = proc.waitFor();
            System.out.println("Process exitValue: " + exitVal);
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

    public static void main(String[] args) {
//        String a = "https://bcxin-saas-test.obs.cn-north-1.myhuaweicloud.com:443/upload%2F2020-07-13%2F2085405861_374673048_1.mp4";
//        String b = "https://bcxin-saas-test.obs.cn-north-1.myhuaweicloud.com:443/upload%2F2020-07-13%2F2085405861_374673048_2.mp4";
//        String a = "E:\\ase\\1478504368_1879725062_ts.ts";
//        String b = "E:\\ase\\1478504368_1879725062_2.mp4";
//        transfer(a,b);
//        String videoCommend = "ffmpeg -i " + "https://bcxin-saas-test.obs.cn-north-1.myhuaweicloud.com:443/upload/2020-07-14/2051161097_28681400_1.mp4" + " -vcodec libx264 -r 29.97 -b 768k -ar 24000 -ab 64k -s 1280x720 "
//                + "https://bcxin-saas-test.obs.cn-north-1.myhuaweicloud.com:443/upload/2020-07-14/"+ UUID.randomUUID().toString()+".mp4";
//        System.out.println(videoCommend);
        String a = "http://1258404658.vod2.myqcloud.com/1d941a6dvodcq1258404658/88ca39f43701925922105006416/playlist.m3u8";
        String url = getMp4ByM3u8(a,"IDENTIFY-TEST");
        System.out.println(url);
    }
}
