package cn.i2edu.dubbing_lib.util;

import android.content.Context;


import com.coremedia.iso.boxes.Container;
import com.googlecode.mp4parser.FileDataSourceImpl;
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.AACTrackImpl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2016/11/24.
 */

public class Mp4ParserMixer {
    private VideoAudioMixListener mListener = null;
    private Context context;

    public Mp4ParserMixer(Context context) {
        this.context = context;
    }

    public interface VideoAudioMixListener {
        void mixSuccess();

        void mixFail(String reason);
    }

    public void setListener(VideoAudioMixListener listener) {
        mListener = listener;
    }

    /**
     * 合成音频和视频
     *
     * @param audioPath     原音频文件路径
     * @param vedioPath     原视频路径
     * @param mixedFilePath 合成后的文件路径
     */
//    public void mux(String audioPath, String vedioPath, String mixedFileName, String mixedFilePath) {
//        File mixDir = new File(mixedFilePath);
//        if (!mixDir.exists()) {
//            mixDir.mkdir();
//        }
//        try {
//            Movie countVideo = MovieCreator.build(vedioPath);
//            // 创建新的视频
//            Movie newMovie = new Movie();
//            // 创建新的音轨
//            AACTrackImpl aacTrack = new AACTrackImpl(new FileDataSourceImpl(audioPath));
//            List<Track> videoTrackList = new ArrayList<>();
//            // 获取原视频视频轨
//            for (Track t : countVideo.getTracks()) {
//                if (t.getHandler().equals("vide")) {
//                    videoTrackList.add(t);
//                }
//            }
//            // 在新视频文件中添加原视频的视频
//            for (int i = 0; i < videoTrackList.size(); i++) {
//                newMovie.addTrack(videoTrackList.get(i));
//            }
//            // 在新视频中添加音轨
//            newMovie.addTrack(aacTrack);
//            // 开始合成并且输出
//            {
//                Container out = new DefaultMp4Builder().build(newMovie);
////                FileOutputStream fos = new FileOutputStream(new File(mixDir.getAbsolutePath() + "/" + mixedFileName));
//                File file = new File(mixDir.getAbsolutePath() + "/" + mixedFileName);
//                RandomAccessFile fos = new RandomAccessFile(file,"rw");
//                out.writeContainer(fos.getChannel());
//                fos.close();
//            }
//            if (mListener != null) {
//                mListener.mixSuccess();
////                BufferOverflowException
//            }
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//            CustomBugReporter.reportError(VedioAudioMixer.class.getName(), "file not found exception", e);
//            if (mListener != null) {
//                mListener.mixFail(null);
//            }
//        } catch (IOException e) {
//            CustomBugReporter.reportError(VedioAudioMixer.class.getName(), "ioexception", e);
//            e.printStackTrace();
//            if (mListener != null) {
//                mListener.mixFail(null);
//            }
//            } catch (BufferOverflowException e){
//            CustomBugReporter.reportError(VedioAudioMixer.class.getName(), "合成音频和视频时出错",e);
//            e.printStackTrace();
//            if (mListener != null){
//                mListener.mixFail(context.getString(R.string.toast_run_out_of_memory));
//            }
//        }
//
//    }

    public void muxAudioAndVideo(String audioPath, String vedioPath, String mixedFilePath) {
        try {
            Movie countVideo = MovieCreator.build(vedioPath);
            // 创建新的视频
            Movie newMovie = new Movie();
            // 创建新的音轨
            AACTrackImpl aacTrack = new AACTrackImpl(new FileDataSourceImpl(audioPath));
            List<Track> videoTrackList = new ArrayList<>();
            // 获取原视频视频轨
            for (Track t : countVideo.getTracks()) {
                if (t.getHandler().equals("vide")) {
                    videoTrackList.add(t);
                }
            }
            // 在新视频文件中添加原视频的视频
            for (int i = 0; i < videoTrackList.size(); i++) {
                newMovie.addTrack(videoTrackList.get(i));
            }
            // 在新视频中添加音轨
            newMovie.addTrack(aacTrack);
            // 开始合成并且输出
            {
                Container out = new DefaultMp4Builder().build(newMovie);
                FileOutputStream fos = new FileOutputStream(new File(mixedFilePath));
                BufferedWritableFileByteChannel byteBufferByteChannel = new BufferedWritableFileByteChannel(fos);
                out.writeContainer(byteBufferByteChannel);
                byteBufferByteChannel.close();
                fos.close();
            }
            if (mListener != null) {
                mListener.mixSuccess();
//                BufferOverflowException
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
//            CustomBugReporter.reportError(VedioAudioMixer.class.getName(), "file not found exception", e);
            if (mListener != null) {
                mListener.mixFail(null);
            }
        } catch (IOException e) {
//            CustomBugReporter.reportError(VedioAudioMixer.class.getName(), "ioexception", e);
            e.printStackTrace();
            if (mListener != null) {
                mListener.mixFail(null);
            }
        } catch (BufferOverflowException e){
//            CustomBugReporter.reportError(VedioAudioMixer.class.getName(), "合成音频和视频时出错",e);
            e.printStackTrace();
            if (mListener != null){
                mListener.mixFail("内存不足，请清理内存后重试！");
            }
        }

    }

    private static class BufferedWritableFileByteChannel implements WritableByteChannel {
        private static final int BUFFER_CAPACITY = 1000000;

        private boolean isOpen = true;
        private final OutputStream outputStream;
        private final ByteBuffer byteBuffer;
        private final byte[] rawBuffer = new byte[BUFFER_CAPACITY];

        private BufferedWritableFileByteChannel(OutputStream outputStream) {
            this.outputStream = outputStream;
            this.byteBuffer = ByteBuffer.wrap(rawBuffer);
        }

        @Override
        public int write(ByteBuffer inputBuffer) {
            int inputBytes = inputBuffer.remaining();
            if (inputBytes > byteBuffer.remaining()) {
                dumpToFile();
                byteBuffer.clear();

                if (inputBytes > byteBuffer.remaining()) {
                    throw new BufferOverflowException();
                }
            }

            byteBuffer.put(inputBuffer);

            return inputBytes;
        }

        @Override
        public boolean isOpen() {
            return isOpen;
        }

        @Override
        public void close() {
            dumpToFile();
            isOpen = false;
        }
        private void dumpToFile() {
            try {
                outputStream.write(rawBuffer, 0, byteBuffer.position());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

}