using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Core;
namespace PepperDash.Essentials.Core
{
///
/// An incrementer that can use the values of some other object/primitive value to do its thing.
/// It uses an Action to set the value and a Func to get the value from whatever this is
/// attached to.
///
public class ActionIncrementer
{
public int ChangeAmount { get; set; }
public int MaxValue { get; set; }
public int MinValue { get; set; }
public uint RepeatDelay { get; set; }
public uint RepeatTime { get; set; }
Action SetAction;
Func GetFunc;
CTimer Timer;
///
///
///
///
///
///
///
///
/// Action that will be called when this needs to set the destination value
/// Func that is called to get the current value
public ActionIncrementer(int changeAmount, int minValue, int maxValue, uint repeatDelay, uint repeatTime, Action setAction, Func getFunc)
{
SetAction = setAction;
GetFunc = getFunc;
ChangeAmount = changeAmount;
MaxValue = maxValue;
MinValue = minValue;
RepeatDelay = repeatDelay;
RepeatTime = repeatTime;
}
///
/// Starts incrementing cycle
///
public void StartUp()
{
if (Timer != null) return;
Go(ChangeAmount);
}
///
/// Starts decrementing cycle
///
public void StartDown()
{
if (Timer != null) return;
Go(-ChangeAmount);
}
///
/// Stops the repeat
///
public void Stop()
{
if (Timer != null)
Timer.Stop();
Timer = null;
}
///
/// Helper that does the work of setting new level, and starting repeat loop, checking against bounds first.
///
///
void Go(int change)
{
int currentLevel = GetFunc();
// Fire once then pause
int newLevel = currentLevel + change;
bool atLimit = CheckLevel(newLevel, out newLevel);
SetAction(newLevel);
if (atLimit) // Don't go past end
Stop();
else if (Timer == null) // Only enter the timer if it's not already running
Timer = new CTimer(o => { Go(change); }, null, RepeatDelay, RepeatTime);
}
///
/// Helper to check a new level against min/max. Returns revised level if new level
/// will go out of bounds
///
/// The level to check against bounds
/// Revised level if bounds are exceeded. Min or max
/// true if new level is at or past bounds
bool CheckLevel(int levelIn, out int levelOut)
{
bool isAtLimit = false;
if (levelIn > MaxValue)
{
levelOut = MaxValue;
isAtLimit = true;
}
else if (levelIn < MinValue)
{
levelOut = MinValue;
isAtLimit = true;
}
else
levelOut = levelIn;
return isAtLimit;
}
}
}