import { html, nothing } from 'lit';
import { query, state, property } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { DateTime } from 'luxon';
import { boolean } from '../../internal/boolean.mjs';
import { parseDuration, floorDateTime, ceilDateTime } from '../../internal/datetime.mjs';
import FlowRdfElement from '../../internal/flow-ui-rdf-element.mjs';
import { isStringFull } from '../../internal/type-checks.mjs';
import { watch } from '../../internal/watch.mjs';
import { Ticker } from './ticker.mjs';
import styles from './timer.styles.mjs';
import { debounce } from '@emuanalytics/flow-rdf-core/utils';

var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
  var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
  for (var i = decorators.length - 1, decorator; i >= 0; i--)
    if (decorator = decorators[i])
      result = (kind ? decorator(target, key, result) : decorator(result)) || result;
  if (kind && result)
    __defProp(target, key, result);
  return result;
};
const STEP_DEBOUNCE_TIME = 300;
class FlowUiTimer extends FlowRdfElement {
  constructor() {
    super(...arguments);
    this._displayDateTime = DateTime.now();
    this.running = false;
    this.dateFormat = "DD";
    this.dayFormat = "ccc";
    this.timeFormat = "TT";
    this.zoneFormat = "ZZZZ";
    this.majorStep = "1 minute";
    this.minorStep = "5 seconds";
    this.updateInterval = "5 seconds";
    this.hideZone = false;
    this.placement = "bottom-start";
    this.debouncedEmitChange = debounce(
      () => {
        this.emit("flow-ui-input");
        this.emit("flow-ui-change");
      },
      STEP_DEBOUNCE_TIME,
      { leading: true, trailing: true, context: this }
    );
  }
  connectedCallback() {
    super.connectedCallback();
    this.hideZone = boolean(this.hideZone, true);
    this.running = boolean(this.running, true);
    this.ticker = new Ticker({ second: 5 }, "Europe/London");
    this.tickerSubscription = this.ticker.subscribe((dateTime, tickType) => {
      if (tickType === "major") {
        this.value = dateTime;
        this.emit("flow-ui-change");
      } else {
        this.setDisplayDateTime(dateTime);
      }
    });
    this.updateRunning();
  }
  disconnectedCallback() {
    super.disconnectedCallback();
    this.tickerSubscription.unsubscribe();
    this.ticker.stop();
  }
  updateDisplayValue() {
    this.setDisplayDateTime(this.value);
  }
  updateParsedSteps() {
    this.minorStepDuration = parseDuration(this.minorStep) ?? { second: 5 };
    this.majorStepDuration = parseDuration(this.majorStep) ?? { minute: 1 };
  }
  updateUpdateInterval() {
    const updateIntervalDuration = parseDuration(this.updateInterval) ?? { second: 5 };
    this.ticker.setTickInterval(updateIntervalDuration);
  }
  updateRunning() {
    if (this.running) {
      this.ticker.start();
    } else {
      this.ticker.stop();
    }
  }
  setDisplayDateTime(dateTime) {
    const zone = isStringFull(this.timezone) ? this.timezone : void 0;
    const locale = isStringFull(this.locale) ? this.locale : void 0;
    this._displayDateTime = DateTime.fromISO(dateTime, { zone, locale });
  }
  handleDateTimeKeyDown(event) {
    if (event.key === "Enter") ;
    event.stopPropagation();
  }
  handleCalendarChange(event) {
    event.stopPropagation();
    const zone = isStringFull(this.timezone) ? this.timezone : void 0;
    const locale = isStringFull(this.locale) ? this.locale : void 0;
    const calendarDateTime = DateTime.fromISO(this.calendar.value, { zone, locale });
    if (!this._displayDateTime.startOf("day").equals(calendarDateTime.startOf("day"))) {
      this.dropdown.hide();
    }
    this.value = this.calendar.value;
    this.emit("flow-ui-input");
    this.emit("flow-ui-change");
  }
  handlePlayPauseClicked() {
    this.running = !this.running;
  }
  handleStepClicked(ev, direction) {
    ev.stopPropagation();
    this.running = false;
    let dateTime;
    const majorStepUnit = Object.keys(this.majorStepDuration)[0];
    const minorStepUnit = Object.keys(this.minorStepDuration)[0];
    const majorStepValue = this.majorStepDuration[majorStepUnit];
    const minorStepValue = this.minorStepDuration[minorStepUnit];
    switch (direction) {
      case "fast-back":
        dateTime = ceilDateTime(this._displayDateTime.minus(this.majorStepDuration), majorStepUnit, majorStepValue);
        break;
      case "back":
        dateTime = ceilDateTime(this._displayDateTime.minus(this.minorStepDuration), minorStepUnit, minorStepValue);
        break;
      case "forward":
        dateTime = floorDateTime(this._displayDateTime.plus(this.minorStepDuration), minorStepUnit, minorStepValue);
        break;
      case "fast-forward":
        dateTime = floorDateTime(this._displayDateTime.plus(this.majorStepDuration), majorStepUnit, majorStepValue);
        break;
      default:
        dateTime = this._displayDateTime;
    }
    this.value = dateTime.toISO() ?? "";
    this.setDisplayDateTime(this.value);
    this.debouncedEmitChange();
  }
  formattedDisplayDateTime(format, uppercase = false) {
    const formatted = this._displayDateTime.isValid ? this._displayDateTime.toFormat(format) : "--";
    return uppercase ? formatted.toUpperCase() : formatted;
  }
  render() {
    return html`
      <div
        part="base"
        class=${classMap({
      timer: true
    })}
      >
        <flow-ui-dropdown
          class="timer__dropdown"
          placement=${this.placement}
          distance="8"
          strategy="fixed"
          flip
          shift
          sync="width"
          auto-size="height"
          @flow-ui-show=${() => {
      this.running = false;
    }}
        >
          <div slot="trigger" class="timer__date-time-container" @keydown=${this.handleDateTimeKeyDown}>
            <flow-ui-icon library="system" name="calendar" tabindex="0"></flow-ui-icon>
            <div class="timer__date-container">
              <span class="timer__day">${this.formattedDisplayDateTime(this.dayFormat, true)}</span>
              <span class="timer__date">${this.formattedDisplayDateTime(this.dateFormat)}</span>
            </div>
            <flow-ui-icon library="system" name="clock" tabindex="0"></flow-ui-icon>
            <div class="timer__time-container">
              <span class="timer__time">${this.formattedDisplayDateTime(this.timeFormat)}</span>

              ${// Note that flow-ui-show event was causing timer to stop because of dropdown handling of flow-ui-show above
    !this.hideZone ? html`
                      <flow-ui-tooltip
                        hoist
                        placement="top"
                        content=${this.formattedDisplayDateTime("ZZZZZ")}
                        @flow-ui-show=${(ev) => ev.stopImmediatePropagation()}
                      >
                        <span class="timer__zone">${this.formattedDisplayDateTime(this.zoneFormat)}</span>
                      </flow-ui-tooltip>
                    ` : nothing}
            </div>
          </div>

          ${html`
            <flow-ui-calendar
              class="timer__calendar"
              display-mode="datetime"
              value=${this.value}
              timezone=${ifDefined(this.timezone)}
              locale=${ifDefined(this.locale)}
              @flow-ui-change=${this.handleCalendarChange}
            ></flow-ui-calendar>
          `}
        </flow-ui-dropdown>

        <div class="timer__vcr-controls">
          <flow-ui-icon-button
            library="system"
            name="backward-step"
            title="Fast rewind"
            @click=${(ev) => this.handleStepClicked(ev, "fast-back")}
          ></flow-ui-icon-button>
          <flow-ui-icon-button
            library="system"
            name="backward"
            title="Rewind"
            @click=${(ev) => this.handleStepClicked(ev, "back")}
          ></flow-ui-icon-button>
          <flow-ui-icon-button
            library="system"
            name=${this.running ? "pause" : "play"}
            title=${this.running ? "pause" : "play"}
            @click=${this.handlePlayPauseClicked}
          ></flow-ui-icon-button>
          <flow-ui-icon-button
            library="system"
            name="forward"
            title="Forward"
            @click=${(ev) => this.handleStepClicked(ev, "forward")}
          ></flow-ui-icon-button>
          <flow-ui-icon-button
            library="system"
            name="forward-step"
            title="Fast Forward"
            .value=${3}
            @click=${(ev) => this.handleStepClicked(ev, "fast-forward")}
          ></flow-ui-icon-button>
        </div>
      </div>
    `;
  }
}
FlowUiTimer.styles = styles;
__decorateClass([
  query(".timer__dropdown")
], FlowUiTimer.prototype, "dropdown", 2);
__decorateClass([
  query(".timer__calendar")
], FlowUiTimer.prototype, "calendar", 2);
__decorateClass([
  state()
], FlowUiTimer.prototype, "_displayDateTime", 2);
__decorateClass([
  property()
], FlowUiTimer.prototype, "value", 2);
__decorateClass([
  property()
], FlowUiTimer.prototype, "timezone", 2);
__decorateClass([
  property()
], FlowUiTimer.prototype, "locale", 2);
__decorateClass([
  property({ type: Boolean, reflect: true })
], FlowUiTimer.prototype, "running", 2);
__decorateClass([
  property()
], FlowUiTimer.prototype, "dateFormat", 2);
__decorateClass([
  property()
], FlowUiTimer.prototype, "dayFormat", 2);
__decorateClass([
  property()
], FlowUiTimer.prototype, "timeFormat", 2);
__decorateClass([
  property()
], FlowUiTimer.prototype, "zoneFormat", 2);
__decorateClass([
  property({ attribute: "major-step" })
], FlowUiTimer.prototype, "majorStep", 2);
__decorateClass([
  property({ attribute: "minor-step" })
], FlowUiTimer.prototype, "minorStep", 2);
__decorateClass([
  property({ attribute: "update-interval" })
], FlowUiTimer.prototype, "updateInterval", 2);
__decorateClass([
  property({ type: Boolean, attribute: "hide-zone" })
], FlowUiTimer.prototype, "hideZone", 2);
__decorateClass([
  property()
], FlowUiTimer.prototype, "placement", 2);
__decorateClass([
  watch(["value", "timezone", "locale"])
], FlowUiTimer.prototype, "updateDisplayValue", 1);
__decorateClass([
  watch(["majorStep", "minorStep"])
], FlowUiTimer.prototype, "updateParsedSteps", 1);
__decorateClass([
  watch(["updateInterval"])
], FlowUiTimer.prototype, "updateUpdateInterval", 1);
__decorateClass([
  watch("running")
], FlowUiTimer.prototype, "updateRunning", 1);

export { FlowUiTimer as default };
