import { Slot } from "ic10emu_wasm";
import { html, css, HTMLTemplateResult } from "lit";
import { customElement, state } from "lit/decorators.js";
import { BaseElement, defaultCss } from "../components";
import { VMBaseDevice } from "./base_device";
import "@shoelace-style/shoelace/dist/components/card/card.js";
import "@shoelace-style/shoelace/dist/components/icon/icon.js";
import "@shoelace-style/shoelace/dist/components/tooltip/tooltip.js";
import "@shoelace-style/shoelace/dist/components/input/input.js";
import "@shoelace-style/shoelace/dist/components/details/details.js";
import "@shoelace-style/shoelace/dist/components/tab/tab.js";
import "@shoelace-style/shoelace/dist/components/tab-panel/tab-panel.js";
import "@shoelace-style/shoelace/dist/components/tab-group/tab-group.js";
import "@shoelace-style/shoelace/dist/components/copy-button/copy-button.js";
import "@shoelace-style/shoelace/dist/components/select/select.js";
import "@shoelace-style/shoelace/dist/components/badge/badge.js";
import "@shoelace-style/shoelace/dist/components/option/option.js";
import SlInput from "@shoelace-style/shoelace/dist/components/input/input.js";
import { parseNumber, structuralEqual } from "../utils";
import SlSelect from "@shoelace-style/shoelace/dist/components/select/select.js";
@customElement("vm-device-card")
export class VMDeviceCard extends VMBaseDevice {
image_err: boolean;
static styles = [
...defaultCss,
css`
:host {
display: block;
box-sizing: border-box;
}
.card {
width: 100%;
box-sizing: border-box;
}
.image {
width: 4rem;
height: 4rem;
}
.header {
display: flex;
flex-direction: row;
}
.header-name {
display: flex;
flex-direction: row;
width: 100%;
flex-grow: 1;
align-items: center;
flex-wrap: wrap;
}
// .device-name {
// box-sizing: border-box;
// width: 8rem;
// }
// .device-name-hash {
// box-sizing: border-box;
// width: 5rem;
// }
sl-divider {
--spacing: 0.25rem;
}
sl-button[variant="success"] {
/* Changes the success theme color to purple using primitives */
--sl-color-success-600: var(--sl-color-purple-700);
}
sl-button[variant="primary"] {
/* Changes the success theme color to purple using primitives */
--sl-color-primary-600: var(--sl-color-cyan-600);
}
sl-button[variant="warning"] {
/* Changes the success theme color to purple using primitives */
--sl-color-warning-600: var(--sl-color-amber-600);
}
sl-tab-group {
margin-left: 1rem;
margin-right: 1rem;
--indicator-color: var(--sl-color-purple-600);
--sl-color-primary-600: var(--sl-color-purple-600);
}
`,
];
onImageErr(e: Event) {
this.image_err = true;
console.log("Image load error", e);
}
renderHeader(): HTMLTemplateResult {
const activeIc = window.VM?.activeIC;
const badges: HTMLTemplateResult[] = [];
if (this.deviceID == activeIc?.id) {
badges.push(html`db`);
}
activeIc?.pins?.forEach((id, index) => {
if (this.deviceID == id) {
badges.push(html``);
}
}, this);
return html`
`;
}
renderFields(): HTMLTemplateResult {
const fields = Array.from(this.fields);
return html`
${fields.map(([name, field], _index, _fields) => {
return html`
${name}
${field.field_type}
`;
})}
`;
}
renderSlot(slot: Slot, slotIndex: number): HTMLTemplateResult {
const fields = Array.from(slot.fields);
return html`
${fields.map(
([name, field], _index, _fields) => html`
${name}
${field.field_type}
`,
)}
`;
}
renderSlots(): HTMLTemplateResult {
return html`
${this.slots.map((slot, index, _slots) => this.renderSlot(slot, index))}
`;
}
renderReagents(): HTMLTemplateResult {
return html``;
}
renderNetworks(): HTMLTemplateResult {
const vmNetworks = window.VM!.networks;
return html`
${this.connections.map((connection, index, _conns) => {
const conn =
typeof connection === "object" ? connection.CableNetwork : null;
return html`
Connection:${index}
${vmNetworks.map(
(net) =>
html`Network ${net}`,
)}
`;
})}
`;
}
renderPins(): HTMLTemplateResult {
const pins = this.pins;
const visibleDevices = window.VM!.visibleDevices(this.deviceID);
return html`
${pins?.map(
(pin, index) =>
html`
d${index}
${visibleDevices.map(
(device, _index) =>
html`
Device ${device.id} : ${device.name ?? device.prefabName}
`,
)}
`,
)}
`;
}
protected render(): HTMLTemplateResult {
return html`
Fields
Slots
Reagents
Networks
Pins
${this.renderFields()}
${this.renderSlots()}
${this.renderReagents()}
${this.renderNetworks()}
${this.renderPins()}
`;
}
_handleChangeName(e: CustomEvent) {
const input = e.target as SlInput;
this.device.setName(input.value);
this.updateDevice();
}
_handleChangeField(e: CustomEvent) {
const input = e.target as SlInput;
const field = input.getAttribute("key")!;
const val = parseNumber(input.value);
this.device.setField(field, val);
this.updateDevice();
}
_handleChangeSlotField(e: CustomEvent) {
const input = e.target as SlInput;
const slot = parseInt(input.getAttribute("slotIndex")!);
const field = input.getAttribute("key")!;
const val = parseNumber(input.value);
this.device.setSlotField(slot, field, val);
this.updateDevice();
}
_handleChangeConnection(e: CustomEvent) {
const select = e.target as SlSelect;
const conn = parseInt(select.getAttribute("key")!);
const last = this.device.connections[conn];
const val = select.value ? parseInt(select.value as string) : undefined;
if (typeof last === "object" && typeof last.CableNetwork === "number") {
// is there no other connection to the previous network?
if (
!this.device.connections.some((other_conn, index) => {
structuralEqual(last, other_conn) && index !== conn;
})
) {
this.device.removeDeviceFromNetwork(last.CableNetwork);
}
}
if (typeof val !== "undefined") {
this.device.addDeviceToNetwork(conn, val);
} else {
this.device.setConnection(conn, val);
}
this.updateDevice();
}
_handleChangePin(e: CustomEvent) {
const select = e.target as SlSelect;
const pin = parseInt(select.getAttribute("key")!);
const val = select.value ? parseInt(select.value as string) : undefined;
this.device.setPin(pin, val);
this.updateDevice();
}
}
@customElement("vm-device-list")
export class VMDeviceList extends BaseElement {
@state() accessor devices: number[];
constructor() {
super();
this.devices = window.VM!.deviceIds;
}
connectedCallback(): void {
const root = super.connectedCallback();
window.VM?.addEventListener(
"vm-devices-update",
this._handleDevicesUpdate.bind(this),
);
return root;
}
_handleDevicesUpdate(e: CustomEvent) {
const ids = e.detail;
if (!structuralEqual(this.devices, ids)) {
this.devices = ids;
}
}
protected render(): HTMLTemplateResult {
return html`
${this.devices.map(
(id, _index, _ids) =>
html``,
)}
`;
}
}