using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SmaHmaCrossoverAlert : Indicator
    {
        #region Parameters

        [Parameter("SMA Period", DefaultValue = 200, MinValue = 1)]
        public int SmaPeriod { get; set; }

        [Parameter("HMA Period", DefaultValue = 250, MinValue = 1)]
        public int HmaPeriod { get; set; }

        [Parameter("Sound File Path", DefaultValue = @"C:\Windows\Media\Alarm05.wav")]
        public string SoundFilePath { get; set; }

        [Parameter("Source")]
        public DataSeries Source { get; set; }

        #endregion

        #region Outputs

        [Output("SMA", LineColor = "#FF01FF01", PlotType = PlotType.Line, Thickness = 2)]
        public IndicatorDataSeries SmaResult { get; set; }

        [Output("HMA", LineColor = "#FFFF6666", PlotType = PlotType.Line, Thickness = 2)]
        public IndicatorDataSeries HmaResult { get; set; }

        #endregion

        #region Fields

        private SimpleMovingAverage _sma;
        private HullMovingAverage _hma;
        private int _lastAlertBarIndex;

        #endregion

        protected override void Initialize()
        {
            _sma = Indicators.SimpleMovingAverage(Source, SmaPeriod);
            _hma = Indicators.HullMovingAverage(Source, HmaPeriod);
            _lastAlertBarIndex = -1;
        }

        public override void Calculate(int index)
        {
            // Update indicator values
            SmaResult[index] = _sma.Result[index];
            HmaResult[index] = _hma.Result[index];

            // Ensure sufficient data exists
            if ((index <= SmaPeriod) || (index <= HmaPeriod))
            {
                return;
            }

            // Processing alerts only for the last bar (real-time) to prevent playing sounds during backfill
            if (!IsLastBar)
            {
                return;
            }

            // Prevent multiple alerts on the same bar
            if (index == _lastAlertBarIndex)
            {
                return;
            }

            double smaCurr = _sma.Result[index];
            double smaPrev = _sma.Result[index - 1];
            double hmaCurr = _hma.Result[index];
            double hmaPrev = _hma.Result[index - 1];

            // Condition 1: SMA Slope
            bool isSmaRising = smaCurr > smaPrev;
            bool isSmaFalling = smaCurr < smaPrev;

            // Condition 2: Crossover
            // CrossUp: Previous HMA was below/equal SMA, Current HMA is above SMA
            bool isCrossUp = (hmaPrev <= smaPrev) && (hmaCurr > smaCurr);
            
            // CrossDown: Previous HMA was above/equal SMA, Current HMA is below SMA
            bool isCrossDown = (hmaPrev >= smaPrev) && (hmaCurr < smaCurr);

            // Signal Evaluation
            if ((isSmaRising) && (isCrossUp))
            {
                PlayAlert(index);
            }
            else if ((isSmaFalling) && (isCrossDown))
            {
                PlayAlert(index);
            }
        }

        private void PlayAlert(int index)
        {
            _lastAlertBarIndex = index;
            
            // Try/Catch block to prevent indicator crash if file is missing
            try
            {
                Notifications.PlaySound(SoundFilePath);
            }
            catch (Exception ex)
            {
                Print("Error playing sound: {0}", ex.Message);
            }
        }
    }
}