const util = require('util');
const EventEmitter = require('events').EventEmitter;
require('linqjs');
let Player = require('./clsPlayer').clsPlayer;
let _ = require('lodash');
// let rootPath = process.cwd();
// let path = require('path');
// let moment = require('moment');
//const Logger = require('../logs/clsLogger').clsLogger;
const masterMixer = class masterMixer {
  constructor({ moment, utils, config, logger } = {}) {

    this.moment = moment;
    this.utils = utils;
    this.config = config;
    this.logger = logger;
    this.playerEvents = {
      stateChanged: 'stateChanged',
      positionChange: 'positionChange',
      fileChanged: 'fileChanged',
      playlistFinished: 'playlistFinished',
      fadeInStarted: 'fadeInStarted',
      fadeOutStarted: 'fadeOutStarted',
      vumeter: 'vumeter',
      Error: 'error'
    };
    this.volume = 100;

    this.players = {
      thirdParty: 0,
        dj: 0,
        stream: 0,
        schedule: 0,
        announce: 0
    };


    let mMixer = new Player();

    this._mMixer = mMixer;
    let devices = this._mMixer.getDevices();
    let enabledDevices = _.find(devices, (c) => { if (c != null)return c.enabled == true; });
    if(!enabledDevices){
      process.exit(4);
    }
    this.logger.System('------------------------------------------------');
      this.logger.System('         sound cards:');
    devices.forEach((c) => {
      if (c != null) this.logger.System(`${c.index}-${c.name} ${c.IsDefault ? '(default)' : ''}, active:${c.enabled}`);
    });
      this.logger.System('------------------------------------------------');

    mMixer.initSoundCard(this.config.Settings.soundCard, mMixer.basslib.BASS_DEVICE_SPEAKERS);
    this.loadPlugins();
    //get multi output settings from config

    //default settings
    let mixerFlags = mMixer.bassAttributes.BASS_SAMPLE_FLOAT;
    let speaker = mMixer.bassAttributes.BASS_SAMPLE_DEFAULT;
    let channelCount = 2;
    this.addChannelFlags = mMixer.mixerAttributes.BASS_MIXER_BUFFER;
    //check config  mono out and which channel
    if (this.config.MultiOutput.isEnabled) {
      switch(parseInt(this.config.MultiOutput.Channel)) {
        case 1:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_FRONT;
          break;
        case 2:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_REAR;
          break;
        case 3:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_CENLFE;
          channelCount = 1;
          break;
        case 4:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_REAR2;
          break;
        case 5:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_LEFT;
          channelCount = 1;
          this.addChannelFlags = mMixer.mixerAttributes.BASS_MIXER_DOWNMIX | mMixer.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 6:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_RIGHT;
          channelCount = 1;
          this.addChannelFlags = mMixer.mixerAttributes.BASS_MIXER_DOWNMIX | mMixer.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 7:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_FRONTLEFT;
          channelCount = 1;
          this.addChannelFlags = mMixer.mixerAttributes.BASS_MIXER_DOWNMIX | mMixer.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 8:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_FRONTRIGHT;
          channelCount = 1;
          this.addChannelFlags = mMixer.mixerAttributes.BASS_MIXER_DOWNMIX | mMixer.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 9:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_REARLEFT;
          channelCount = 1;
          this.addChannelFlags = mMixer.mixerAttributes.BASS_MIXER_DOWNMIX | mMixer.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 10:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_REARRIGHT;
          channelCount = 1;
          this.addChannelFlags = mMixer.mixerAttributes.BASS_MIXER_DOWNMIX | mMixer.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 11:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_CENTER;
          channelCount = 1;
          this.addChannelFlags = mMixer.mixerAttributes.BASS_MIXER_DOWNMIX | mMixer.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 12:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_LFE;
          channelCount = 1;
          this.addChannelFlags = mMixer.mixerAttributes.BASS_MIXER_DOWNMIX | mMixer.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 13:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_REAR2LEFT;
          channelCount = 1;
          this.addChannelFlags = mMixer.mixerAttributes.BASS_MIXER_DOWNMIX | mMixer.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        case 14:
          speaker = mMixer.speakerAttributes.BASS_SPEAKER_REAR2RIGHT;
          channelCount = 1;
          this.addChannelFlags = mMixer.mixerAttributes.BASS_MIXER_DOWNMIX | mMixer.mixerAttributes.BASS_MIXER_BUFFER;
          break;
        default:
          channelCount = 2;
          break;
      }
    }

    //create the mixer
    //BASS_MIXER_NONSTOP avoids dropping from icecast server if nothing is playing
    let mixer = mMixer.createMixer(channelCount, speaker | mMixer.mixerAttributes.BASS_MIXER_NONSTOP);
    this.mixer = mixer;
    mMixer.setVolume(mixer, 100);
    mMixer.PlayMixer();
    setInterval(() => {
      let vu = mMixer.getVumeter(mixer);
      this.emit(this.playerEvents.vumeter, vu.left, vu.right);
    }, 250);
  }

  addChannelToMixer(channelToAdd) {
    let result = this._mMixer.addChannelToMixer(channelToAdd, this.addChannelFlags);
    let err = this._mMixer.getError();
    return result;
  }

  setVolume(channel, newVolume) {
    this._mMixer.setVolume(channel, newVolume);
  }

  setMasterVolume(newVolume) {
    this._mMixer.setVolume(this.mixer, newVolume);
    this.volume = newVolume;
  }

  getMasterVolume() {
    return this._mMixer.getVolume(this.mixer);
  }

  getVolume(mixer) {
    return this._mMixer.getVolume(mixer);
  }

  setFadeOut(channel, fadeDur) {
    this.emit(this.playerEvents.fadeOutStarted, channel, fadeDur);
    this._mMixer.setFadeOutForAnnounce(channel, fadeDur);
  }

  setFadeIn(channel, fadeDur) {
    this.emit(this.playerEvents.fadeInStarted, channel, fadeDur);
    this._mMixer.setFadeInForAnnounce(channel, fadeDur);
  }

  getVu(mixer) {
    return this._mMixer.getVumeter(mixer);
  }

    loadPlugins() {
        let q = this.config.Plugins;
        let q1 = Object.keys(q).where(c => q[c] === '1');
        if(q1.length > 0) {
            q1.forEach((c) => {
                c = c.toLowerCase();
                let q = this._mMixer.loadPlugin(c);
            });
        }
    }
};

util.inherits(masterMixer, EventEmitter);
module.exports = masterMixer;