import debug from "debug";
import { css, html, LitElement, PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { Literal, NamedNode } from "n3";
import { SubEvent } from "sub-events";
import { getTopGraph } from "../RdfdbSyncedGraph";
import { SyncedGraph } from "../SyncedGraph";
import { ControlValue, Effect } from "./Effect";
import { DeviceAttrRow } from "./Light9DeviceControl";
export { Slider } from "@material/mwc-slider";
export { Light9ColorPicker } from "../light9-color-picker";
export { Light9Listbox } from "./Light9Listbox";
const log = debug("settings.dev.attr");
type DataTypeNames = "scalar" | "color" | "choice";
const makeType = (d: DataTypeNames) => new NamedNode(`http://light9.bigasterisk.com/${d}`);
// UI for one device attr (of any type).
@customElement("light9-attr-control")
export class Light9AttrControl extends LitElement {
graph!: SyncedGraph;
static styles = [
css`
#colorControls {
display: flex;
align-items: center;
}
#colorControls > * {
margin: 0 3px;
}
:host {
}
mwc-slider {
width: 250px;
}
`,
];
@property() deviceAttrRow: DeviceAttrRow | null = null;
@state() dataType: DataTypeNames = "scalar";
@property() effect: Effect | null = null;
@property() enableChange: boolean = false;
@property() value: ControlValue | null = null; // e.g. color string
constructor() {
super();
getTopGraph().then((g) => {
this.graph = g;
if (this.deviceAttrRow === null) throw new Error();
});
}
connectedCallback(): void {
super.connectedCallback();
setTimeout(() => {
// only needed once per page layout
this.shadowRoot?.querySelector("mwc-slider")?.layout(/*skipUpdateUI=*/ false);
}, 1);
}
render() {
if (this.deviceAttrRow === null) throw new Error();
if (this.dataType == "scalar") {
const v = this.value || 0;
return html` `;
} else if ((this.dataType = "color")) {
const v = this.value || "#000";
return html`
`;
} else if (this.dataType == "choice") {
return html` `;
}
}
updated(changedProperties: PropertyValues) {
super.updated(changedProperties);
if (changedProperties.has("deviceAttrRow")) {
this.onDeviceAttrRowProperty();
}
if (changedProperties.has("effect")) {
this.onEffectProperty();
}
if (changedProperties.has("value")) {
this.onValueProperty();
}
}
private onValueProperty() {
if (this.deviceAttrRow === null) throw new Error();
if (!this.graph) {
log('ignoring value change- no graph yet')
return;
}
if (this.effect === null) {
this.value = null;
} else {
const p = this.effect.edit(
//
this.deviceAttrRow.device,
this.deviceAttrRow.uri,
this.value
);
if (!p.isEmpty()) {
log("Effect told us to graph.patch this:\n", p.dump());
this.graph.applyAndSendPatch(p);
}
}
}
private onEffectProperty() {
if (this.effect === null) {
log('no effect obj yet')
return;
}
// effect will read graph changes on its own, but emit an event when it does
this.effect.settingsChanged.subscribe(() => {
this.effectSettingsChanged();
});
this.effectSettingsChanged();
}
private effectSettingsChanged() {
// something in the settings graph is new
if (this.deviceAttrRow === null) throw new Error();
if (this.effect === null) throw new Error();
// log("graph->ui on ", this.deviceAttrRow.device, this.deviceAttrRow.uri);
const v = this.effect.currentValue(this.deviceAttrRow.device, this.deviceAttrRow.uri);
this.onGraphValueChanged(v);
}
private onDeviceAttrRowProperty() {
if (this.deviceAttrRow === null) throw new Error();
const d = this.deviceAttrRow.dataType;
if (d.equals(makeType("scalar"))) {
this.dataType = "scalar";
} else if (d.equals(makeType("color"))) {
this.dataType = "color";
} else if (d.equals(makeType("choice"))) {
this.dataType = "choice";
}
}
onValueInput(ev: CustomEvent) {
if (ev.detail === undefined) {
// not sure what this is, but it seems to be followed by good events
return;
}
// log(ev.type, ev.detail.value);
this.value = ev.detail.value;
// this.graphToControls.controlChanged(this.device, this.deviceAttrRow.uri, ev.detail.value);
}
onGraphValueChanged(v: ControlValue | null) {
if (this.deviceAttrRow === null) throw new Error();
// log("change: control must display", v, "for", this.deviceAttrRow.device.value, this.deviceAttrRow.uri.value);
// this.enableChange = false;
if (this.dataType == "scalar") {
if (v !== null) {
this.value = v;
} else {
this.value = 0;
}
} else if (this.dataType == "color") {
this.value = v;
}
}
goBlack() {
this.value = "#000000";
}
onChoice(value: any) {
// if (value != null) {
// value = this.graph.Uri(value);
// } else {
// value = null;
// }
}
onChange(value: any) {
// if (typeof value === "number" && isNaN(value)) {
// return;
// } // let onChoice do it
// //log('change: control tells graph', @deviceAttrRow.uri.value, value)
// if (value === undefined) {
// value = null;
// }
}
}