package com.kuxhausen.huemore.net;
import com.kuxhausen.huemore.state.BulbState;
import java.util.List;
public class BrightnessManager {
private BrightnessPolicy mPolicy;
/**
* 1 - 100
*/
private Integer mVolumeBri;
private List<NetworkBulb> mBulbs;
public BrightnessManager(List<NetworkBulb> bulbs) {
if (bulbs == null) {
throw new IllegalArgumentException();
}
mBulbs = bulbs;
mPolicy = BrightnessPolicy.DIRECT_BRI;
}
public void setPolicy(BrightnessPolicy policy) {
if (policy == null) {
throw new IllegalArgumentException();
}
mPolicy = policy;
if (mPolicy == BrightnessPolicy.DIRECT_BRI) {
mVolumeBri = null;
}
}
public BrightnessPolicy getPolicy() {
return mPolicy;
}
public BulbState getState(NetworkBulb netBulb, NetworkBulb.GetStateConfidence confidence) {
if (netBulb == null || !mBulbs.contains(netBulb) || confidence == null) {
throw new IllegalArgumentException();
}
BulbState adjusted = netBulb.getState(confidence).clone();
if (mPolicy == BrightnessPolicy.VOLUME_BRI && adjusted.get255Bri() != null) {
Integer volume = mVolumeBri;
if (volume == null) {
volume = getAveragePercentBrightness(mBulbs, NetworkBulb.GetStateConfidence.KNOWN);
}
adjusted.set255Bri(((int) Math.round(adjusted.get255Bri() * 100.0) / volume));
}
return adjusted;
}
public void setState(NetworkBulb netBulb, BulbState targetState) {
if (netBulb == null || targetState == null || !mBulbs.contains(netBulb)) {
throw new IllegalArgumentException(
(netBulb == null) + "," + (targetState == null) + "," + (!mBulbs.contains(netBulb)));
}
BulbState adjusted = targetState.clone();
//in volume bri mode, new color with unspecified bri is assumed to at 100% of current volume
if (mPolicy == BrightnessPolicy.VOLUME_BRI && adjusted.get255Bri() == null && (
adjusted.getMiredCT() != null || adjusted.hasXY())) {
adjusted.set255Bri(255);
}
if (mPolicy == BrightnessPolicy.VOLUME_BRI && adjusted.get255Bri() != null) {
if (mVolumeBri == null) {
//calculate existing volume bri as average bri
mVolumeBri = getAveragePercentBrightness(mBulbs, NetworkBulb.GetStateConfidence.KNOWN);
}
adjusted.set255Bri((int) Math.round((mVolumeBri * adjusted.get255Bri()) / 100.0));
}
netBulb.setState(adjusted);
}
/**
* Does not update lights, only valid in volume mode
* @param newVolume ranges from 1 to 100
*/
public void setVolumeWithoutUpdate(int newVolume) {
if (mPolicy != BrightnessPolicy.VOLUME_BRI) {
throw new IllegalStateException();
}
mVolumeBri = newVolume;
}
/**
* @param brightness ranges from 1 to 100
*/
public void setBrightness(int brightness) {
int newBrightness = Math.max(1, Math.min(100, brightness));
if (mPolicy == BrightnessPolicy.VOLUME_BRI) {
if (mVolumeBri == null) {
//calculate existing volume bri as average brightness
mVolumeBri = getAveragePercentBrightness(mBulbs, NetworkBulb.GetStateConfidence.KNOWN);
}
int oldVolume = mVolumeBri;
int newVolume = newBrightness;
for (NetworkBulb bulb : mBulbs) {
Integer
oldPhysicalBri =
bulb.getState(NetworkBulb.GetStateConfidence.KNOWN).getPercentBri();
if (oldPhysicalBri == null) {
oldPhysicalBri = oldVolume;
}
oldPhysicalBri = Math.min(oldPhysicalBri, oldVolume);
int newPhysicalBri = (oldPhysicalBri * newVolume) / oldVolume;
BulbState bs = new BulbState();
bs.setPercentBri(newPhysicalBri);
bs.setTransitionTime(BulbState.TRANSITION_TIME_BRIGHTNESS_BAR);
bulb.setState(bs);
}
mVolumeBri = newVolume;
} else {
BulbState bs = new BulbState();
bs.setPercentBri(newBrightness);
bs.setTransitionTime(BulbState.TRANSITION_TIME_BRIGHTNESS_BAR);
for (NetworkBulb bulb : mBulbs) {
bulb.setState(bs);
}
}
}
/**
* @return brightness ranging from 1 to 100
*/
public int getBrightness() {
if (mPolicy == BrightnessPolicy.VOLUME_BRI) {
if (mVolumeBri == null) {
//calculate existing volume bri as average brightness
return getAveragePercentBrightness(mBulbs, NetworkBulb.GetStateConfidence.KNOWN);
} else {
return mVolumeBri;
}
} else {
return getAveragePercentBrightness(mBulbs, NetworkBulb.GetStateConfidence.GUESS);
}
}
//calculate the largest brightness among the group, returning 1 if no bulbs are sufficiently confident of brightness
private static int getLargestPercentBrightness(List<NetworkBulb> list) {
if (list == null) {
throw new IllegalArgumentException();
}
int briMax = 1;
for (NetworkBulb bulb : list) {
Integer physicalBri = bulb.getState(NetworkBulb.GetStateConfidence.KNOWN).getPercentBri();
if (physicalBri != null && physicalBri > briMax) {
briMax = physicalBri;
}
}
return briMax;
}
//calculate the average brightness among the group, returning 1 if no bulbs are sufficiently confident of brightness
private static int getAveragePercentBrightness(List<NetworkBulb> list,
NetworkBulb.GetStateConfidence confidence) {
if (list == null) {
throw new IllegalArgumentException();
}
int briSum = 0;
int briNum = 0;
for (NetworkBulb bulb : list) {
Integer physicalBri = bulb.getState(confidence).getPercentBri();
if (physicalBri != null) {
briSum += physicalBri;
briNum++;
}
}
if (briNum == 0) {
return 1;
}
return briSum / briNum;
}
public enum BrightnessPolicy {
DIRECT_BRI, VOLUME_BRI
}
}