//>>> _using
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpDX;
using SharpDX.Direct3D11;
using SharpDX.Windows;
//<<< _using
using Framefield.Core;
using System.IO;
using Un4seen.Bass;


namespace Framefield.Core.ID73345c16_c26f_41ae_a92e_997274a6b94a
{
    public class Class_LoadSound : OperatorPart.Function, Framefield.Core.OperatorPartTraits.ITimeAccessor
    {
        //>>> _inputids
        private enum InputId
        {
            FilePath = 0,
            PlaySpeed = 1,
            Time = 2,
            Volume = 3
        }
        //<<< _inputids 

        public override void Dispose() {
            StopPlaying();
        }

        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx) {
            //>>> _params
            var FilePath = inputs[(int)InputId.FilePath].Eval(context).Text;
            var PlaySpeed = inputs[(int)InputId.PlaySpeed].Eval(context).Value;
            var Time = inputs[(int)InputId.Time].Eval(context).Value;
            var Volume = inputs[(int)InputId.Volume].Eval(context).Value;
            //<<< _params

            if (!IsSoundInitialized())
                return context;

            if (File.Exists(FilePath) && _fileName != FilePath) {
                StopPlaying();

                _fileName = FilePath;
                _stream = Bass.BASS_StreamCreateFile(_fileName, 0, 0, BASSFlag.BASS_STREAM_PRESCAN);
                _channelInfo = Bass.BASS_ChannelGetInfo(_stream);
                _lastPlaySpeed = -9999999.0f;
                _lastTime = -9999999.0f;
                _lastVolume = -9999999.0f;
                Logger.Debug(this,"opened sound: {0}", _fileName);
            }

            if (_stream == 0) {
                context.Value = -1.0f;
                return context;
            }


            if (_lastPlaySpeed != PlaySpeed) {
                _lastPlaySpeed = PlaySpeed;
                if (Math.Abs(PlaySpeed) < 0.01)
                    Bass.BASS_ChannelPause(_stream);
                else {
                    if (!IsPlaying()) {
                        Bass.BASS_ChannelPlay(_stream, false);
                        _lastTime = -9999999.0f;
                        _lastVolume = -9999999.0f;
                    }

                    Bass.BASS_ChannelSetAttribute(_stream, BASSAttribute.BASS_ATTRIB_FREQ, _channelInfo.freq*PlaySpeed);
                }
            }

            if (_lastTime != Time) {
                Bass.BASS_ChannelSetPosition(_stream, Time);
                _lastTime = Time;
            }

            if (_lastVolume != Volume) {
                Bass.BASS_ChannelSetAttribute(_stream, BASSAttribute.BASS_ATTRIB_VOL, Volume);
                _lastVolume = Volume;
            }

            context.Value = (float)Bass.BASS_ChannelBytes2Seconds(_stream, Bass.BASS_ChannelGetPosition(_stream, BASSMode.BASS_POS_BYTES));
            return context;
        }
        
        private void StopPlaying() {
            if (_stream != 0) {
                Bass.BASS_ChannelPause(_stream);
                Bass.BASS_ChannelStop(_stream);
                Bass.BASS_StreamFree(_stream);
                Logger.Debug(this,"closed sound: {0}", _fileName);
            }
        }

        private bool IsSoundInitialized() {
            return Bass.BASS_GetInfo() != null;
        }
        
        private bool IsPlaying() {
            return Bass.BASS_ChannelIsActive(_stream) == Un4seen.Bass.BASSActive.BASS_ACTIVE_PLAYING;
        }

        string _fileName;
        int _stream;
        BASS_CHANNELINFO _channelInfo;
        float _lastPlaySpeed;
        float _lastTime;
        float _lastVolume;
    }
}

