const Player = require('./clsPlayer').clsPlayer;

const inputPlayer = class inputPlayer {
  constructor({ utils, config, musicVolume = 100, decodeOnly = false, logger } = {  }) {
    this.utils = utils;
    this.config = config;
    this.musicVolume = musicVolume;
    this.mixerVolume = musicVolume;
    this.decodeOnly = decodeOnly;
    this.logger = logger;
    this.channel = 0;
    this.inputChannel = 0;
    this.player = new Player({config, utils});
    this.isPlaying = false;
    this.addChannelFlags = this.player.mixerAttributes.BASS_MIXER_BUFFER;
    this.events = {
      startedPlaying: 'startedPlaying',
      stoppedPlaying: 'stoppedPlaying'
    };

    //let inputFlags = this.player.bassAttributes.BASS_SAMPLE_FLOAT;
    let speaker = this.player.bassAttributes.BASS_SAMPLE_DEFAULT;
    let channelCount = 2;
    if(this.config.MultiOutput.isEnabled) {
      switch (parseInt(this.config.MultiOutput.Channel)) {
        case 1:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_FRONT;
          break;
        case 2:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_REAR;
          break;
        case 3:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_CENLFE;
          channelCount = 1;
          break;
        case 4:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_REAR2;
          break;
        case 5:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_LEFT;
          channelCount = 1;
          this.addChannelFlags = this.player.mixerAttributes.BASS_MIXER_DOWNMIX | this.player.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 6:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_RIGHT;
          channelCount = 1;
          this.addChannelFlags = this.player.mixerAttributes.BASS_MIXER_DOWNMIX | this.player.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 7:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_FRONTLEFT;
          channelCount = 1;
          this.addChannelFlags = this.player.mixerAttributes.BASS_MIXER_DOWNMIX | this.player.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 8:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_FRONTRIGHT;
          channelCount = 1;
          this.addChannelFlags = this.player.mixerAttributes.BASS_MIXER_DOWNMIX | this.player.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 9:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_REARLEFT;
          channelCount = 1;
          this.addChannelFlags = this.player.mixerAttributes.BASS_MIXER_DOWNMIX | this.player.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 10:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_REARRIGHT;
          channelCount = 1;
          this.addChannelFlags = this.player.mixerAttributes.BASS_MIXER_DOWNMIX | this.player.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 11:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_CENTER;
          channelCount = 1;
          this.addChannelFlags = this.player.mixerAttributes.BASS_MIXER_DOWNMIX | this.player.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 12:
          speaker = this.player.BASS_SPEAKER_LFE;
          channelCount = 1;
          this.addChannelFlags = this.player.mixerAttributes.BASS_MIXER_DOWNMIX | this.player.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 13:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_REAR2LEFT;
          channelCount = 1;
          this.addChannelFlags = this.player.mixerAttributes.BASS_MIXER_DOWNMIX | this.player.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 14:
          speaker = this.player.speakerAttributes.BASS_SPEAKER_REAR2RIGHT;
          channelCount = 1;
          this.addChannelFlags = this.player.mixerAttributes.BASS_MIXER_DOWNMIX | this.player.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        default:
          channelCount = 2;
          break;
      }
    }
    this.player.initSoundCard(this.config.Settings.soundCard, this.player.bassAttributes.BASS_DEVICE_STEREO);
    if(this.decodeOnly) speaker = this.player.bassAttributes.BASS_STREAM_DECODE;
    this.speaker = speaker;
    this.channelCount = channelCount;
    this.mixer = this.player.createMixer(channelCount, speaker);
    this.player.setVolume(this.mixer, this.mixerVolume);
  }

  init() {
      const initResult = this.player.initRecDev(this.config.InputPlayer.recordingCard);
      if(initResult) {
        this._readyIO();
        return true;
      } else {
        this.isPlaying = false;
        return false;
      }
  }

  _readyIO() {
    this.channel = this.player.createRecordPlayingChannel(this.channelCount, this.speaker);
    if(!this.channel) {
      let error = this.player.getError();
      this.logger.InputPlayer(`Can't create output channel, err: ${error} `);
      this.isPlaying = false;
      return;
    }

    this.inputChannel = this.player.recordStart(this.channel);
    if(!this.inputChannel) {
      let error = this.player.getError();
      this.logger.InputPlayer(`Can't create input channel, err: ${error} `);
      this.isPlaying = false;
      return;
    }
    this.logger.InputPlayer(`input and output channels are ready to play`);
    this._play();
  }

  _play() {
    this.logger.InputPlayer(`Starting input play`);
    this.player.playChannel(this.inputChannel);
    if(!this.decodeOnly){
      this.player.playChannel(this.channel);
    }
    this.player.addChannelToMixer(this.channel, this.speaker);
    this.isPlaying = true;
    this.emit(this.events.startedPlaying);
    this.logger.InputPlayer(`Play success!`);
  }

  stop() {
    this.logger.InputPlayer(`Stopping input player...`);
    try {
        const streamFree = this.player.streamFree(this.channel);
        const recordFree = this.player.recordFree(this.inputChannel);
        if(streamFree && recordFree) {
          this.logger.InputPlayer(`Input & Output channels freed successfully`);
          this.channel = 0;
          this.inputChannel = 0;
          this.isPlaying = false;
          this.emit(this.events.stoppedPlaying);
        }
    } catch (e) {
      this.logger.InputPlayer(`Error freeing i/o channels, err: ${e}`);
    }
  }
};

const util = require('util');
const EventEmitter = require('events').EventEmitter;
util.inherits(inputPlayer, EventEmitter);
module.exports = inputPlayer;
