package com.anren.omplayer;

import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Nullable;

/**
 * Created by lcg on 2017/6/18.
 */
public class OMAudioPlayerModuleIjk extends ReactContextBaseJavaModule {

    private Integer nextPlayerId = 0;
    private Map players = new HashMap<Integer, OMAudioPlayerIjk>();

    public OMAudioPlayerModuleIjk(ReactApplicationContext reactContent){
        super(reactContent);
    }

    @Override
    public String getName() {
        return "OMAudioPlayerManagerIjk";
    }

    @Nullable
    @Override
    public Map<String, Object> getConstants() {
        final Map<String, Object> constants = new HashMap<>();
        constants.put(OMAudioEvent.EVENT_AUDIO_LOAD_START, OMAudioEvent.EVENT_AUDIO_LOAD_START);
        constants.put(OMAudioEvent.EVENT_AUDIO_LOAD, OMAudioEvent.EVENT_AUDIO_LOAD);
        constants.put(OMAudioEvent.EVENT_AUDIO_ERROR, OMAudioEvent.EVENT_AUDIO_ERROR);
        constants.put(OMAudioEvent.EVENT_AUDIO_PROGRESS, OMAudioEvent.EVENT_AUDIO_PROGRESS);
        constants.put(OMAudioEvent.EVENT_AUDIO_SEEK, OMAudioEvent.EVENT_AUDIO_SEEK);
        constants.put(OMAudioEvent.EVENT_AUDIO_END, OMAudioEvent.EVENT_AUDIO_END);
        constants.put(OMAudioEvent.EVENT_AUDIO_READY_FOR_PLAY, OMAudioEvent.EVENT_AUDIO_READY_FOR_PLAY);
        constants.put(OMAudioEvent.EVENT_AUDIO_STALLED, OMAudioEvent.EVENT_AUDIO_STALLED);
        constants.put(OMAudioEvent.EVENT_AUDIO_RESUME, OMAudioEvent.EVENT_AUDIO_RESUME);
        constants.put(OMAudioEvent.EVENT_AUDIO_RATE_CHANGE, OMAudioEvent.EVENT_AUDIO_RATE_CHANGE);
        constants.put(OMAudioEvent.EVENT_AUDIO_PLAYER_ERROR, OMAudioEvent.EVENT_AUDIO_PLAYER_ERROR);
        return constants;
    }

    private Integer getPlayerId(){
        return ++nextPlayerId;
    }

    private OMAudioPlayerIjk getPlayer(Integer playerId){
        OMAudioPlayerIjk player = (OMAudioPlayerIjk) players.get(playerId);

        return player;
    }

    private void setPlayer(Integer playerId, OMAudioPlayerIjk player){
        players.put(playerId, player);
    }

    public void sendEvent(String event, ReadableMap params){
        getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(event, params);
    }

    public ReactApplicationContext getContext(){
        return getReactApplicationContext();
    }

    @ReactMethod
    public void createAudioPlayer(Callback callback){
        try {
            Integer playerId = getPlayerId();
            OMAudioPlayerIjk player = new OMAudioPlayerIjk(playerId, this);
//            player.setAudioPlayerModule(this);
//            player.setAudioPlayerId(playerId);
            setPlayer(playerId,player);

            callback.invoke(null,playerId);
        }
        catch (Exception e){
            callback.invoke(e.getMessage());
        }
    }

    @ReactMethod
    public void releaseAudioPlayer(Integer playerId){
        try {
            OMAudioPlayerIjk player = getPlayer(playerId);
            if (player != null){
                player.stop();
            }

            players.remove(playerId);
        }
        catch (Exception e){
//            callback.invoke(e.getMessage());
        }
    }

    @ReactMethod
    public void setToken(String token, Integer playerId){
        OMAudioPlayerIjk player = getPlayer(playerId);
        if (player != null){
            player.setToken(token);
        }
        else {
            WritableMap params = new WritableNativeMap();
            params.putInt("id", playerId);
            sendEvent(OMAudioEvent.EVENT_AUDIO_PLAYER_ERROR, params);
        }
    }

    @ReactMethod
    public void setSrc(String src, Integer playerId){
        OMAudioPlayerIjk player = getPlayer(playerId);
        if (player != null){
            player.setSrc(src);
        }
        else {
            WritableMap params = new WritableNativeMap();
            params.putInt("id", playerId);
            sendEvent(OMAudioEvent.EVENT_AUDIO_PLAYER_ERROR, params);
        }
    }

    @ReactMethod
    public void setRepeat(boolean repeat, Integer playerId){
        OMAudioPlayerIjk player = getPlayer(playerId);
        if (player != null){
            player.setRepeat(repeat);
        }
        else {
            WritableMap params = new WritableNativeMap();
            params.putInt("id", playerId);
            sendEvent(OMAudioEvent.EVENT_AUDIO_PLAYER_ERROR, params);
        }
    }

    @ReactMethod
    public void setMuted(boolean muted, Integer playerId){
        OMAudioPlayerIjk player = getPlayer(playerId);
        if (player != null){
            player.setMuted(muted);
        }
        else {
            WritableMap params = new WritableNativeMap();
            params.putInt("id", playerId);
            sendEvent(OMAudioEvent.EVENT_AUDIO_PLAYER_ERROR, params);
        }
    }

    @ReactMethod
    public void setVolume(Float volume, Integer playerId){
        OMAudioPlayerIjk player = getPlayer(playerId);
        if (player != null){
            player.setVolume(volume);
        }
        else {
            WritableMap params = new WritableNativeMap();
            params.putInt("id", playerId);
            sendEvent(OMAudioEvent.EVENT_AUDIO_PLAYER_ERROR, params);
        }
    }

    @ReactMethod
    public void setRate(Float rate, Integer playerId){
        OMAudioPlayerIjk player = getPlayer(playerId);
        if (player != null){
            player.setRate(rate);
        }
        else {
            WritableMap params = new WritableNativeMap();
            params.putInt("id", playerId);
            sendEvent(OMAudioEvent.EVENT_AUDIO_PLAYER_ERROR, params);
        }
    }

    @ReactMethod
    public void seek(Integer seek, Integer playerId){
        OMAudioPlayerIjk player = getPlayer(playerId);
        if (player != null){
            player.seek(Math.round(seek * 1000.0f));
        }
        else {
            WritableMap params = new WritableNativeMap();
            params.putInt("id", playerId);
            sendEvent(OMAudioEvent.EVENT_AUDIO_PLAYER_ERROR, params);
        }
    }

    @ReactMethod
    public void play(Integer playerId){
        OMAudioPlayerIjk player = getPlayer(playerId);
        if (player != null){
            player.play();
        }
        else {
            WritableMap params = new WritableNativeMap();
            params.putInt("id", playerId);
            sendEvent(OMAudioEvent.EVENT_AUDIO_PLAYER_ERROR, params);
        }
    }

    @ReactMethod
    public void pause(Integer playerId){
        OMAudioPlayerIjk player = getPlayer(playerId);
        if (player != null){
            player.pause();
        }
        else {
            WritableMap params = new WritableNativeMap();
            params.putInt("id", playerId);
            sendEvent(OMAudioEvent.EVENT_AUDIO_PLAYER_ERROR, params);
        }
    }

    @ReactMethod
    public void stop(Integer playerId){
        OMAudioPlayerIjk player = getPlayer(playerId);
        if (player != null){
            player.stop();
        }
        else {
            WritableMap params = new WritableNativeMap();
            params.putInt("id", playerId);
            sendEvent(OMAudioEvent.EVENT_AUDIO_PLAYER_ERROR, params);
        }
    }
}
