import { nothing } from "lit/html.js";
import { directive } from "lit/directive.js";
import { AsyncDirective } from "lit/async-directive.js";
class SpreadPropsDirective extends AsyncDirective {
  constructor() {
    super(...arguments);
    this.prevData = {};
  }
  render(_spreadData) {
    return nothing;
  }
  update(part, [spreadData]) {
    var _a;
    if (this.element !== part.element) {
      this.element = part.element;
    }
    this.host = ((_a = part.options) === null || _a === void 0 ? void 0 : _a.host) || this.element;
    this.apply(spreadData);
    this.groom(spreadData);
    this.prevData = { ...spreadData };
  }
  apply(data) {
    if (!data)
      return;
    const { prevData, element } = this;
    for (const key in data) {
      const value = data[key];
      if (value === prevData[key]) {
        continue;
      }
      element[key] = value;
    }
  }
  groom(data) {
    const { prevData, element } = this;
    if (!prevData)
      return;
    for (const key in prevData) {
      if (!data || !(key in data) && element[key] === prevData[key]) {
        element[key] = void 0;
      }
    }
  }
}
directive(SpreadPropsDirective);
class SpreadEventsDirective extends SpreadPropsDirective {
  constructor() {
    super(...arguments);
    this.eventData = {};
  }
  apply(data) {
    if (!data)
      return;
    for (const key in data) {
      const value = data[key];
      if (value === this.eventData[key]) {
        continue;
      }
      this.applyEvent(key, value);
    }
  }
  applyEvent(eventName, eventValue) {
    const { prevData, element } = this;
    this.eventData[eventName] = eventValue;
    const prevHandler = prevData[eventName];
    if (prevHandler) {
      element.removeEventListener(eventName, this, eventValue);
    }
    element.addEventListener(eventName, this, eventValue);
  }
  groom(data) {
    const { prevData, element } = this;
    if (!prevData)
      return;
    for (const key in prevData) {
      if (!data || !(key in data) && element[key] === prevData[key]) {
        this.groomEvent(key, prevData[key]);
      }
    }
  }
  groomEvent(eventName, eventValue) {
    const { element } = this;
    delete this.eventData[eventName];
    element.removeEventListener(eventName, this, eventValue);
  }
  handleEvent(event) {
    const value = this.eventData[event.type];
    if (typeof value === "function") {
      value.call(this.host, event);
    } else {
      value.handleEvent(event);
    }
  }
  disconnected() {
    const { eventData, element } = this;
    for (const key in eventData) {
      const name = key.slice(1);
      const value = eventData[key];
      element.removeEventListener(name, this, value);
    }
  }
  reconnected() {
    const { eventData, element } = this;
    for (const key in eventData) {
      const name = key.slice(1);
      const value = eventData[key];
      element.addEventListener(name, this, value);
    }
  }
}
directive(SpreadEventsDirective);
class SpreadDirective extends SpreadEventsDirective {
  apply(data) {
    if (!data)
      return;
    const { prevData, element } = this;
    for (const key in data) {
      const value = data[key];
      if (value === prevData[key]) {
        continue;
      }
      const name = key.slice(1);
      switch (key[0]) {
        case "@":
          this.eventData[name] = value;
          this.applyEvent(name, value);
          break;
        case ".":
          element[name] = value;
          break;
        case "?":
          if (value) {
            element.setAttribute(name, "");
          } else {
            element.removeAttribute(name);
          }
          break;
        default:
          if (value != null) {
            element.setAttribute(key, String(value));
          } else {
            element.removeAttribute(key);
          }
          break;
      }
    }
  }
  groom(data) {
    const { prevData, element } = this;
    if (!prevData)
      return;
    for (const key in prevData) {
      const name = key.slice(1);
      if (!data || !(key in data) && element[name] === prevData[key]) {
        switch (key[0]) {
          case "@":
            this.groomEvent(name, prevData[key]);
            break;
          case ".":
            element[name] = void 0;
            break;
          case "?":
            element.removeAttribute(name);
            break;
          default:
            element.removeAttribute(key);
            break;
        }
      }
    }
  }
}
const spread = directive(SpreadDirective);
export {
  SpreadDirective,
  SpreadEventsDirective,
  SpreadPropsDirective,
  spread
};
//# sourceMappingURL=spread.js.map
