package com.kuxhausen.huemore.state;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import android.support.annotation.Size;
import com.kuxhausen.huemore.utils.DeferredLog;
import java.util.Arrays;
public class BulbState {
public enum Alert {
@SerializedName("none")
NONE,
@SerializedName("select")
FLASH_ONCE,
@SerializedName("lselect")
FLASH_30SEC
}
public enum Effect {
@SerializedName("none")
NONE,
@SerializedName("colorloop")
COLORLOOP
}
public final static int TRANSITION_TIME_DEFAULT = 4, TRANSITION_TIME_NONE = 0,
TRANSITION_TIME_BRIGHTNESS_BAR = 2;
/**
* On/Off state of the light. On=true, Off=false
*/
private Boolean on;
/**
* The brightness value to set the light to. Brightness is a scale from 0 (the minimum the light
* is capable of) to 255 (the maximum). Note: a brightness of 0 is not off.
*/
private Integer bri;
/**
* The x and y coordinates of a color in CIE color space. The first entry is the x coordinate and
* the second entry is the y coordinate. Both x and y must be between 0 and 1. If the specified
* coordinates are not in the CIE color space, the closest color to the coordinates will be
* chosen.
*/
private float[] xy;
/**
* The Mired Color temperature of the light. 2012 connected lights are capable of 153 (6500K) to
* 500 (2000K).
*/
private Integer ct;
/**
* The alert effect, is a temporary change to the bulb�s state, and has one of the following
* values: �none� � The light is not performing an alert effect. �select� � The light is
* performing one breathe cycle. �lselect� � The light is performing breathe cycles for 30 seconds
* or until an "alert": "none" command is received.
*/
private Alert alert;
/**
* The dynamic effect of the light, can either be "none" or "colorloop"
*/
private Effect effect;
/**
* The duration of the transition from the light�s current state to the new state. This is given
* as a multiple of 100ms and defaults to 4 (400ms). For example, setting transistiontime:10 will
* make the transition last 1 second.
*/
private Integer transitiontime;
// For debugging memory leaks
private static int mCountCreated;
public BulbState() {
mCountCreated++;
DeferredLog.d("Svelt", "BulbState initialization count %d", mCountCreated);
}
public BulbState(String creationReason) {
this();
DeferredLog.d("Svelt", creationReason);
}
/**
* Must ensure uniqueness for HueUrlEncoder
*/
@Override
public String toString() {
String result = "";
if (on != null) {
result += "on:" + (on ? "true" : "false") + " ";
}
if (bri != null) {
result += "bri:" + bri + " ";
}
if (xy != null) {
result += "xy:" + xy[0] + " " + xy[1] + " ";
}
if (ct != null) {
result += "ct:" + ct + " ";
}
if (alert != null) {
result += "alert:" + alert + " ";
}
if (effect != null) {
result += "effect:" + effect + " ";
}
if (transitiontime != null) {
result += "transitiontime:" + transitiontime + " ";
}
return result;
}
/**
* when in doubt, override, only allow 1 of three color modes *
*/
public void merge(BulbState other) {
on = (other.on != null) ? other.on : on;
bri = (other.bri != null) ? other.bri : bri;
alert = (other.alert != null) ? other.alert : alert;
effect = (other.effect != null) ? other.effect : effect;
transitiontime = (other.transitiontime != null) ? other.transitiontime : transitiontime;
if (other.xy != null) {
xy = other.xy;
ct = null;
} else if (other.ct != null) {
xy = null;
ct = other.ct;
}
}
/**
* return a BulbState with the values of o when the differ from this object
*/
public BulbState delta(BulbState o) {
BulbState delta = null;
if (o.on != null && (on == null || !on.equals(o.on))) {
if(delta == null) {
delta = new BulbState("delta");
}
delta.on = o.on;
}
if (o.bri != null && (bri == null || !bri.equals(o.bri))) {
if(delta == null) {
delta = new BulbState("delta");
}
delta.bri = o.bri;
}
if (o.alert != null && (alert == null || !alert.equals(o.alert))) {
if(delta == null) {
delta = new BulbState("delta");
}
delta.alert = o.alert;
}
if (o.effect != null && (effect == null || !effect.equals(o.effect))) {
if(delta == null) {
delta = new BulbState("delta");
}
delta.effect = o.effect;
}
if (o.transitiontime != null
&& (transitiontime == null || !transitiontime.equals(o.transitiontime))) {
if(delta == null) {
delta = new BulbState("delta");
}
delta.transitiontime = o.transitiontime;
}
if (o.xy != null && (xy == null || !(xy[0]==(o.xy[0]) && xy[1]==(o.xy[1])))) {
if(delta == null) {
delta = new BulbState("delta");
}
delta.xy = o.xy;
} else if (o.ct != null && (ct == null || !ct.equals(o.ct))) {
if(delta == null) {
delta = new BulbState("delta");
}
delta.ct = o.ct;
}
return delta;
}
/**
* update confirmed with whatever the nontransient result of that change state is
*/
public static void confirmChange(BulbState confirmed, BulbState change) {
if (change.on != null) {
confirmed.on = change.on;
}
if (change.bri != null) {
confirmed.bri = change.bri;
}
// ignore alert for now
// TODO deal with alert
if (change.alert != null) {
confirmed.alert = Alert.NONE;
}
if (change.effect != null) {
confirmed.effect = change.effect;
}
// ignore transitiontime for now
// TODO deal with transitiontime
if (change.transitiontime != null) {
confirmed.transitiontime = 4;
}
// TODO convert between colormoods instead of filling nulls
if (change.xy != null) {
confirmed.xy = change.xy;
confirmed.ct = null;
} else if (change.ct != null) {
confirmed.xy = null;
confirmed.ct = change.ct;
}
}
public BulbState clone() {
Gson gson = new Gson();
try {
return gson.fromJson(gson.toJson(this), BulbState.class);
} catch (Exception e) {
return new BulbState("clone");
}
}
@Override
// TODO Override hashCode too or rename to matches() and update callers
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof BulbState)) {
throw new IllegalArgumentException();
}
BulbState other = (BulbState) obj;
if (this.getOn() == null ^ other.getOn() == null) {
return false;
} else if (this.getOn() != null && !this.getOn().equals(other.getOn())) {
return false;
}
if (this.get255Bri() == null ^ other.get255Bri() == null) {
return false;
} else if (this.get255Bri() != null && !this.get255Bri().equals(other.get255Bri())) {
return false;
}
if (this.getTransitionTime() == null ^ other.getTransitionTime() == null) {
return false;
} else if (this.getTransitionTime() != null
&& !this.getTransitionTime().equals(other.getTransitionTime())) {
return false;
}
if (this.getAlert() == null ^ other.getAlert() == null) {
return false;
} else if (this.getAlert() != null && !this.getAlert().equals(other.getAlert())) {
return false;
}
if (this.getEffect() == null ^ other.getEffect() == null) {
return false;
} else if (this.getEffect() != null && !this.getEffect().equals(other.getEffect())) {
return false;
}
if (this.getMiredCT() == null ^ other.getMiredCT() == null) {
return false;
} else if (this.getMiredCT() != null && !this.getMiredCT().equals(other.getMiredCT())) {
return false;
}
if (this.xy == null ^ other.xy == null) {
return false;
} else if (this.xy != null && !Arrays.equals(this.xy, other.xy)) {
return false;
}
return true;
}
public boolean isEmpty() {
return (on == null && bri == null && xy == null && ct == null
&& alert == null && effect == null && transitiontime == null);
}
public boolean hasOn() {
return on != null;
}
public Boolean getOn() {
return on;
}
public void setOn(Boolean newOn) {
on = newOn;
}
public boolean hasBri() {
return bri != null;
}
public Integer getPercentBri() {
if (bri == null) {
return null;
} else {
return Math.max(1, Math.min(255, (int) Math.round(bri / 2.55)));
}
}
public void setPercentBri(Integer brightness) {
if (brightness == null) {
bri = null;
} else {
bri = Math.max(1, Math.min(255, (int) (brightness * 2.55)));
}
}
public Integer get255Bri() {
return bri;
}
public void set255Bri(Integer brightness) {
if (brightness == null) {
bri = null;
} else {
bri = Math.max(1, Math.min(255, brightness));
}
}
public boolean hasCT() {
return ct != null;
}
public Integer getMiredCT() {
return ct;
}
public void setMiredCT(Integer newCT) {
if (newCT == null) {
ct = null;
} else {
ct = Math.max(1, newCT);
}
}
public Integer getKelvinCT() {
if (ct == null) {
return null;
} else if (ct == 0) {
return 1000000;
} else {
return (1000000 / ct);
}
}
public void setKelvinCT(Integer newCT) {
if (newCT == null) {
ct = null;
} else {
ct = Math.max(1, (1000000 / Math.max(1, newCT)));
}
}
public boolean hasXY() {
return getXY() != null;
}
public
@Size(2)
float[] getXY() {
if (xy == null || xy.length != 2) {
return null;
} else {
return xy;
}
}
public void setXY(@Size(2) float[] newXY) {
xy = newXY;
}
public boolean hasEffect() {
return effect != null;
}
public Effect getEffect() {
return effect;
}
public void setEffect(Effect ef) {
effect = ef;
}
public boolean hasAlert() {
return alert != null;
}
public Alert getAlert() {
return alert;
}
public void setAlert(Alert a) {
alert = a;
}
public boolean hasTransitionTime() {
return transitiontime != null;
}
public Integer getTransitionTime() {
return transitiontime;
}
public void setTransitionTime(Integer timeInDeciSeconds) {
if (timeInDeciSeconds == null) {
transitiontime = null;
} else {
transitiontime = Math.max(0, timeInDeciSeconds);
}
}
public static BulbState merge(BulbState priority, BulbState secondary) {
BulbState result = secondary.clone();
result.merge(priority);
return result;
}
}