package com.navinfo.outdoor.util;

import android.content.Context;
import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.util.Log;
import android.widget.ImageView;

import androidx.annotation.NonNull;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
import com.bumptech.glide.load.resource.bitmap.VideoDecoder;
import com.bumptech.glide.request.RequestOptions;
import com.coremedia.iso.boxes.Container;
import com.github.lazylibrary.util.FileUtils;
import com.github.lazylibrary.util.StringUtils;
import com.googlecode.mp4parser.authoring.Movie;
import com.googlecode.mp4parser.authoring.Track;
import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder;
import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator;
import com.googlecode.mp4parser.authoring.tracks.AppendTrack;
import com.navinfo.outdoor.api.Constant;
import com.tencent.tencentmap.mapsdk.maps.model.LatLng;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * Author: AlanWang4523.
 * Date: 19/4/15 01:46.
 * Mail: alanwang4523@gmail.com
 */
public class AWMp4ParserHelper {
    private static AWMp4ParserHelper instance;
    private static SimpleDateFormat simpleDateFormat;

    public static AWMp4ParserHelper getInstance() {
        if (instance == null) {
            instance = new AWMp4ParserHelper();
            simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        }
        return instance;
    }

    private final static String PREFIX_VIDEO_HANDLER = "vide";
    private final static String PREFIX_AUDIO_HANDLER = "soun";
    /**
     * 合并视频
     * @param inputVideos
     * @param outputPath
     * @throws IOException
     */
    public static void mergeVideos(List<String> inputVideos, String outputPath) throws IOException {
        List<Movie> inputMovies = new ArrayList<>();
        for (String input : inputVideos) {
            inputMovies.add(MovieCreator.build(input));
        }

        List<Track> videoTracks = new LinkedList<>();
        List<Track> audioTracks = new LinkedList<>();

        for (Movie m : inputMovies) {
            for (Track t : m.getTracks()) {
                if (PREFIX_AUDIO_HANDLER.equals(t.getHandler())) {
                    audioTracks.add(t);
                }
                if (PREFIX_VIDEO_HANDLER.equals(t.getHandler())) {
                    videoTracks.add(t);
                }
            }
        }

        Movie outputMovie = new Movie();
        if (audioTracks.size() > 0) {
            outputMovie.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()])));
        }
        if (videoTracks.size() > 0) {
            outputMovie.addTrack(new AppendTrack(videoTracks.toArray(new Track[videoTracks.size()])));
        }

        Container out = new DefaultMp4Builder().build(outputMovie);

        FileChannel fc = new RandomAccessFile(outputPath, "rw").getChannel();
        out.writeContainer(fc);
        fc.close();
    }

    /**
     * 获取mp4视频播放时长
     * */
    /**
     * 返回视频播放总时长
     * @param vedioFile
     * @return
     */
    public long getVedioTotalTime(File vedioFile){
        if (!vedioFile.exists()){
            Log.e("getVedioTotalTime","视频文件不存在");
            return 0;
        }
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        retriever.setDataSource(vedioFile.getAbsolutePath());
        String timeString =  retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        long time = Long.valueOf(timeString);
        return time;
    }

    /**
     * 获取网络视频第一帧
     *
     * @param videoUrl
     * @return
     */
    public void loadFirst(String videoUrl, @NonNull ImageView cover) {
        Bitmap bitmap = null;
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            //根据url获取缩略图
            retriever.setDataSource(videoUrl, new HashMap());
            //获得第一帧图片
            bitmap = retriever.getFrameAtTime();
        } catch (IllegalArgumentException e) {
            //e.printStackTrace();
            Log.e("zhu", e.toString());
        } finally {
            retriever.release();
        }
        if (bitmap != null) {
            cover.setImageBitmap(bitmap);
        }
    }

    /**
     *   context 上下文
     *   uri 视频地址
     *   imageView 设置image
     *   frameTimeMicros 获取某一时间帧
     */
    public void loadFirstWithGlide(final Context context, String uri, ImageView imageView, long frameTimeMicros) {
        RequestOptions requestOptions = RequestOptions.frameOf(frameTimeMicros);
        requestOptions.set(VideoDecoder.FRAME_OPTION, MediaMetadataRetriever.OPTION_CLOSEST);
        requestOptions.transform(new BitmapTransformation() {
            @Override
            protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
                return toTransform;
            }

            @Override
            public void updateDiskCacheKey(MessageDigest messageDigest) {
                try {
                    messageDigest.update((context.getPackageName() + "RotateTransform").getBytes("utf-8"));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        Glide.with(context).load(uri).apply(requestOptions).into(imageView);
    }

    /**
     * 获取本地视频的第一帧
     *
     * @param localPath
     * @return
     */
    public Bitmap getLocalVideoBitmap(String localPath) {
        Bitmap bitmap = null;
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            //根据文件路径获取缩略图
            retriever.setDataSource(localPath);
            //获得第一帧图片
            bitmap = retriever.getFrameAtTime();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } finally {
            retriever.release();
        }
        return bitmap;
    }

    /**
     * 生成mp4文件拍摄的生成路径
     * */
    public File obtainMp4FilePath(String uuid, Object tag) {
        if (tag == null) {
            return new File(Constant.PICTURE_FOLDER+"/"+uuid+"-0.mp4");
        }
        List<File> fileList = (List<File>) tag;
        if (fileList == null || fileList.isEmpty()) {
            return new File(Constant.PICTURE_FOLDER+"/"+uuid+"-0.mp4");
        }
        int maxIndex = 0;
        for (int i = 0; i < fileList.size(); i++) {
            File file = fileList.get(i);
            if (file!=null) {
                String[] fileSplite = file.getName().replace(".mp4", "").split("-");
                if (fileSplite!=null&&fileSplite.length>0&&fileSplite[fileSplite.length-1]!=null) {
                    int index = Integer.parseInt(fileSplite[fileSplite.length-1]);
                    if (index>=maxIndex) {
                        maxIndex = index;
                    }
                }
            }
        }
        return new File(Constant.PICTURE_FOLDER+"/"+uuid+"-"+(maxIndex+1)+".mp4");
    }

    /**
     * 根据文件夹路径生成最新的视频文件路径
     * */
    public File obtainMp4FilePath(String folderPath) {
        if (folderPath == null) {
            return null;
        }
        File folderFile = new File(folderPath);
        if (!folderFile.exists()) {
            folderFile.mkdirs();
        }
        File[] fileList = folderFile.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                if (pathname.getName().endsWith(".mp4")){
                    return true;
                }
                return false;
            }
        });
        if (fileList == null || fileList.length==0) {
            return new File(folderPath+"/0.mp4");
        }
        int maxIndex = 0;
        for (int i = 0; i < fileList.length; i++) {
            File file = fileList[i];
            if (file!=null) {
                int index = Integer.parseInt(file.getName().replace(".mp4", ""));
                if (index>=maxIndex) {
                    maxIndex = index;
                }
            }
        }
        return new File(folderPath+"/"+(maxIndex+1)+".mp4");
    }

    /**
     * 根据提供的uuid，获取指定目录下所有的视频文件
     * */
    public List<File> getVideoFileListByUUID(String uuid) {
        List<File> videoFileList = new ArrayList<>();
        if (StringUtils.isEmpty(uuid)) {
            return videoFileList;
        }
        File folderFile = new File(Constant.PICTURE_FOLDER+"/"+uuid+"/");
        if (!folderFile.exists()) {
            folderFile.mkdirs();
            return videoFileList;
        }
        for (File videoFile: folderFile.listFiles()) {
            videoFileList.add(videoFile);
        }
        return videoFileList;
    }

    public String getVideoFileListStr(List<File> videoFileList) {
        StringBuilder resultStrBuilder = new StringBuilder("");
        if (videoFileList == null || videoFileList.size()<=0){
            return resultStrBuilder.toString();
        }

        for (int i = 0; i < videoFileList.size(); i++) {
            File f = videoFileList.get(i);
            resultStrBuilder.append(f.getAbsolutePath());
            if (i < videoFileList.size() -1) {
                resultStrBuilder.append(",");
            }
        }
        return resultStrBuilder.toString();
    }

    /**
     * 根据视频文件列表，获取到对应的轨迹数据
     * */
    public List<LatLng> getLineStringByVideoFileList(List<File> videoFileList) {
        List<LatLng> latLngs = new ArrayList<>();
        if (videoFileList == null || videoFileList.isEmpty()) {
            return latLngs;
        }

        for (int m = 0; m < videoFileList.size(); m++) {
            File videoFile = videoFileList.get(m);

            String path = videoFile.getPath() + ".txt";
            List<String> strings = FileUtils.readFileToList(path, "utf-8");
            if (strings!=null) {
                for (int i = 0; i < strings.size(); i++) {
                    String[] split = strings.get(i).split(",");
                    LatLng latLng = new LatLng();
                    latLng.setLatitude(Double.valueOf(split[2]));
                    latLng.setLongitude(Double.valueOf(split[3]));
                    latLngs.add(latLng);
                }
                if (strings.size() == 1) {
                    LatLng latLng = latLngs.get(0);
                    latLngs.add(latLng);
                }
            }
        }
        return latLngs;
    }
}
