package com.yidianling.ydlcommon.custom.fm;

import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import com.yidianling.ydlcommon.core.base.BaseApplication;
import com.yidianling.common.tools.LogUtil;
import com.yidianling.ydlcommon.custom.course.CoursePlayer;
import com.yidianling.ydlcommon.custom.event.UpdatePlayStatusEvent;
import com.yidianling.ydlcommon.custom.notification.MusicPlayerService;
import de.greenrobot.event.EventBus;
import io.reactivex.Observable;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

/**
 * FM播放管理
 * Created by softrice on 2015/4/28.
 */
public class MyPlayer {
    private String url;
    private Context context;
    public MediaPlayer m_player;
    private static MyPlayer instance;
    private String title;
    private String cover;

    private Boolean isBusy = false;// 互斥访问

    private StateChangeListener listener;

    private static int fmId;
    public int time;
    public int allTime;

    Timer mTimer;
    private boolean isPlayWhenLoss;
    private boolean showNotification;

    public int getFmId() {
        return fmId;
    }


    public void setFmId(int fmId) {
        this.fmId = fmId;
    }

    public void setListener(StateChangeListener listener) {
        this.listener = listener;
    }

    boolean canNext = true;


    //判断play是否启动
    public static boolean isStart() {
        return instance != null;
    }

    static public MyPlayer getInstance() {
        if (instance == null) {
            instance = new MyPlayer(BaseApplication.Companion.getApp());
        }
        return instance;
    }

    private MyPlayer(Context context) {
        this.context = context;
        m_player = new MediaPlayer();
        initPlayer();
    }


    public MediaPlayer getMediaPlayer() {
        return m_player;
    }

    private void initPlayer() {
        m_player.setAudioStreamType(AudioManager.STREAM_MUSIC);
        m_player.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                LogUtil.d("Error on Listener, what: " + what + "extra: " + extra);
                return false;
            }
        });
        mTimer = new Timer(true);
        mTimer.schedule(new TimerTask() {

            @Override
            public void run() {
                if (m_player != null) {
                    try {
                        if (m_player.isPlaying()) {
                            if (listener != null) {
                                time = m_player.getCurrentPosition();
                                allTime = m_player.getDuration();
                                listener.update(m_player.getCurrentPosition(), m_player.getDuration());
                            }
                        }
                    } catch (IllegalStateException e) {
                        LogUtil.d("播放器状态非法");
                    }

                }
            }

        }, 0, 100);

        m_player.setOnBufferingUpdateListener((mp, percent) -> {
            //                if (listener != null)
            //                    listener.update(mp.getCurrentPosition(), mp.getDuration());
            //                LogUtil.d(percent + "");
        });
        m_player.setOnCompletionListener(mp -> {
            LogUtil.i("MediaPlayer Listener Completed");
            if (listener != null)
                listener.completion();
        });
        m_player.setOnPreparedListener(mp -> {
            LogUtil.i("MediaPlayer Prepared Listener");
            if (listener != null)
                listener.prepared();
            Observable.timer(300, TimeUnit.MILLISECONDS)
                    .subscribe(aLong -> {
                        if (showNotification) {
                            updateNotification();
                        }
                    });
        });
    }

    public void rePlay() {
        if (isBusy)
            return;
        if (m_player != null) {
            m_player.start();
        } else {
            LogUtil.i("m_player is null");
        }
        updateNotification();
    }

    /*
     * 播放新的音乐
     */
    public void play(final String url, boolean showNotification) {
        this.showNotification = showNotification;
        this.url = url;
        //RouterManager.INSTANCE.getCourseRouter().closePlayer();
        // 修改调用方式 by 豪瑞 2019/2/18
        if (CoursePlayer.INSTANCE.isPlaying()) {
            CoursePlayer.INSTANCE.onDestroy(BaseApplication.Companion.getApp());
        }
        if (isBusy)
            return;
        if (m_player != null) {
            m_player.reset();
            if (listener != null) {
                listener.cancel();
            }
        }
        isBusy = true;
        if (url == null)
            return;
        Runnable r = () -> {
            try {
                m_player.setDataSource(context, Uri.parse(url));
                m_player.prepare();
                LogUtil.i("Duration: " + m_player.getDuration());
                m_player.start();


                isBusy = false;
            } catch (Exception e) {
                LogUtil.i(e.getMessage());
            }
        };
        AudioManager audioManager = (AudioManager) BaseApplication.Companion.getApp().getSystemService(Context.AUDIO_SERVICE);
        if (audioManager != null) {
            audioManager.requestAudioFocus(focusChange -> {
                switch (focusChange) {
                    case AudioManager.AUDIOFOCUS_GAIN:
                        if (!isPlaying() && isPlayWhenLoss) {
                            pause(showNotification);
                            if (showNotification) {
                                EventBus.getDefault().post(new UpdatePlayStatusEvent());
                            }
                        }
                        break;
                    case AudioManager.AUDIOFOCUS_LOSS:
                        isPlayWhenLoss = isPlaying();
                        if (isPlaying()) {
                            pause(showNotification);
                            if (showNotification) {
                                EventBus.getDefault().post(new UpdatePlayStatusEvent());
                            }
                        }
                        break;
                    case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                        isPlayWhenLoss = isPlaying();
                        if (isPlaying()) {
                            pause(showNotification);
                            if (showNotification) {
                                EventBus.getDefault().post(new UpdatePlayStatusEvent());
                            }
                        }
                        break;
                    default:
                        break;
                }
            }, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
        }
        new Thread(r).start();
        if (showNotification) {
            updateNotification();
        }
    }

    private void updateNotification() {
        Intent intent = new Intent(BaseApplication.Companion.getApp(), MusicPlayerService.class);
        intent.putExtra("play_type", "fm");
        BaseApplication.Companion.getApp().startService(intent);
    }

    /*
     * 播放和暂停
     */
    public void pause(boolean updateNotification) {
        if (isBusy)
            return;
        if (m_player.isPlaying()) {// 正在播放
            m_player.pause();// 暂停
        } else {// 没有播放
            m_player.start();
        }
        if (updateNotification) {
            updateNotification();
        }
    }

    /**
     * 释放资源
     *
     * @return
     */
    public void releaseMedia() {
        if (m_player != null) {
            m_player.reset();
            m_player.release();
            m_player = null;
            instance = null;
        }
    }

    public Boolean isPlaying() {
        if (showNotification) {
            try {
                return m_player.isPlaying();
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }

        } else {
            return false;
        }
    }

    public void seekTo(int position) {
        m_player.seekTo(position);
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getCover() {
        return cover;
    }

    public void setCover(String cover) {
        this.cover = cover;
    }

    public interface StateChangeListener {
        void update(int time, int allTime);

        void completion();

        void prepared();

        void cancel();
    }


}
