import {
  mdiCheckCircle,
  mdiChip,
  mdiCircleOffOutline,
  mdiCursorDefaultClickOutline,
  mdiDocker,
  mdiExclamationThick,
  mdiFlask,
  mdiKey,
  mdiLinkLock,
  mdiNetwork,
  mdiNumeric1,
  mdiNumeric2,
  mdiNumeric3,
  mdiNumeric4,
  mdiNumeric5,
  mdiNumeric6,
  mdiNumeric7,
  mdiNumeric8,
  mdiPlayCircle,
  mdiPound,
  mdiShield,
} from "@mdi/js";
import type { CSSResultGroup, TemplateResult } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import { ifDefined } from "lit/directives/if-defined";
import memoizeOne from "memoize-one";
import { atLeastVersion } from "../../../../../common/config/version";
import { fireEvent } from "../../../../../common/dom/fire_event";
import { navigate } from "../../../../../common/navigate";
import { capitalizeFirstLetter } from "../../../../../common/string/capitalize-first-letter";
import "../../../../../components/buttons/ha-progress-button";
import "../../../../../components/chips/ha-assist-chip";
import "../../../../../components/chips/ha-chip-set";
import "../../../../../components/ha-alert";
import "../../../../../components/ha-button";
import "../../../../../components/ha-card";
import "../../../../../components/ha-formfield";
import "../../../../../components/ha-markdown";
import "../../../../../components/ha-settings-row";
import "../../../../../components/ha-svg-icon";
import "../../../../../components/ha-switch";
import type { HaSwitch } from "../../../../../components/ha-switch";
import type {
  AddonCapability,
  HassioAddonDetails,
  HassioAddonSetOptionParams,
  HassioAddonSetSecurityParams,
} from "../../../../../data/hassio/addon";
import {
  fetchHassioAddonChangelog,
  fetchHassioAddonInfo,
  installHassioAddon,
  rebuildLocalAddon,
  restartHassioAddon,
  setHassioAddonOption,
  setHassioAddonSecurity,
  startHassioAddon,
  stopHassioAddon,
  uninstallHassioAddon,
  validateHassioAddonOption,
} from "../../../../../data/hassio/addon";
import type { HassioStats } from "../../../../../data/hassio/common";
import {
  extractApiErrorMessage,
  fetchHassioStats,
} from "../../../../../data/hassio/common";
import type { StoreAddonDetails } from "../../../../../data/supervisor/store";
import {
  showAlertDialog,
  showConfirmationDialog,
} from "../../../../../dialogs/generic/show-dialog-box";
import { mdiHomeAssistant } from "../../../../../resources/home-assistant-logo-svg";
import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant, Route } from "../../../../../types";
import { bytesToString } from "../../../../../util/bytes-to-string";
import { getAppDisplayName } from "../../common/app";
import "../../components/supervisor-apps-card-content";
import "../components/supervisor-app-metric";
import { extractChangelog } from "../util/supervisor-app";
import "./supervisor-app-system-managed";
import "../components/supervisor-app-update-available-card";

const STAGE_ICON = {
  stable: mdiCheckCircle,
  experimental: mdiFlask,
  deprecated: mdiExclamationThick,
};

const RATING_ICON = {
  1: mdiNumeric1,
  2: mdiNumeric2,
  3: mdiNumeric3,
  4: mdiNumeric4,
  5: mdiNumeric5,
  6: mdiNumeric6,
  7: mdiNumeric7,
  8: mdiNumeric8,
};

@customElement("supervisor-app-info")
class SupervisorAppInfo extends LitElement {
  @property({ type: Boolean }) public narrow = false;

  @property({ attribute: false }) public route!: Route;

  @property({ attribute: false }) public hass!: HomeAssistant;

  @property({ attribute: false }) public addon!:
    | HassioAddonDetails
    | StoreAddonDetails;

  @property({ type: Boolean, attribute: "control-enabled" })
  public controlEnabled = false;

  @state() private _metrics?: HassioStats;

  @state() private _error?: string;

  private _fetchDataTimeout?: number;

  public disconnectedCallback() {
    super.disconnectedCallback();

    if (this._fetchDataTimeout) {
      clearTimeout(this._fetchDataTimeout);
      this._fetchDataTimeout = undefined;
    }
  }

  protected render(): TemplateResult {
    const metrics = [
      {
        description: this.hass.localize(
          "ui.panel.config.apps.dashboard.cpu_usage"
        ),
        value: this._metrics?.cpu_percent,
      },
      {
        description: this.hass.localize(
          "ui.panel.config.apps.dashboard.ram_usage"
        ),
        value: this._metrics?.memory_percent,
        tooltip: `${bytesToString(this._metrics?.memory_usage)}/${bytesToString(
          this._metrics?.memory_limit
        )}`,
      },
    ];

    const systemManaged = this._isSystemManaged(this.addon);

    return html`
      ${this.addon.update_available
        ? html`
            <supervisor-app-update-available-card
              .hass=${this.hass}
              .narrow=${this.narrow}
              .addon=${this.addon}
              @update-complete=${this._updateComplete}
            ></supervisor-app-update-available-card>
          `
        : nothing}
      ${"protected" in this.addon && !this.addon.protected
        ? html`
            <ha-alert
              alert-type="error"
              .title=${this.hass.localize(
                "ui.panel.config.apps.dashboard.protection_mode.title"
              )}
            >
              ${this.hass.localize(
                "ui.panel.config.apps.dashboard.protection_mode.content"
              )}
              <ha-button
                variant="danger"
                slot="action"
                @click=${this._protectionToggled}
              >
                ${this.hass.localize(
                  "ui.panel.config.apps.dashboard.protection_mode.enable"
                )}
              </ha-button>
            </ha-alert>
          `
        : nothing}
      ${systemManaged
        ? html`
            <supervisor-app-system-managed
              .hass=${this.hass}
              .narrow=${this.narrow}
              .hideButton=${this.controlEnabled}
            ></supervisor-app-system-managed>
          `
        : nothing}

      <ha-card outlined>
        <div class="card-content">
          <div class="addon-header">
            ${!this.narrow
              ? getAppDisplayName(this.addon.name, this.addon.stage)
              : nothing}
            <div class="addon-version light-color">
              ${this.addon.version
                ? html`
                    ${this._computeIsRunning
                      ? html`
                          <ha-svg-icon
                            .title=${this.hass.localize(
                              "ui.panel.config.apps.dashboard.app_running"
                            )}
                            class="running"
                            .path=${mdiPlayCircle}
                          ></ha-svg-icon>
                        `
                      : html`
                          <ha-svg-icon
                            .title=${this.hass.localize(
                              "ui.panel.config.apps.dashboard.app_stopped"
                            )}
                            class="stopped"
                            .path=${mdiCircleOffOutline}
                          ></ha-svg-icon>
                        `}
                  `
                : html` ${this.addon.version_latest} `}
            </div>
          </div>
          <div class="description light-color">
            ${this.addon.version
              ? html`
                  ${this.hass.localize(
                    "ui.panel.config.apps.dashboard.current_version",
                    { version: this.addon.version }
                  )}
                  <div class="changelog" @click=${this._openChangelog}>
                    (<span class="changelog-link"
                      >${this.hass.localize(
                        "ui.panel.config.apps.dashboard.changelog"
                      )}</span
                    >)
                  </div>
                `
              : html`<span class="changelog-link" @click=${this._openChangelog}
                  >${this.hass.localize(
                    "ui.panel.config.apps.dashboard.changelog"
                  )}</span
                >`}
          </div>

          <ha-chip-set class="capabilities">
            ${this.addon.stage !== "stable"
              ? html`
                  <ha-assist-chip
                    filled
                    class=${classMap({
                      yellow: this.addon.stage === "experimental",
                      red: this.addon.stage === "deprecated",
                    })}
                    @click=${this._showMoreInfo}
                    id="stage"
                    .label=${capitalizeFirstLetter(
                      this.hass.localize(
                        `ui.panel.config.apps.dashboard.capability.stages.${this.addon.stage}`
                      )
                    )}
                  >
                    <ha-svg-icon
                      slot="icon"
                      .path=${STAGE_ICON[this.addon.stage]}
                    >
                    </ha-svg-icon>
                  </ha-assist-chip>
                `
              : nothing}

            <ha-assist-chip
              filled
              class=${classMap({
                green: Number(this.addon.rating) >= 6,
                yellow: [3, 4, 5].includes(Number(this.addon.rating)),
                red: Number(this.addon.rating) <= 2,
              })}
              @click=${this._showMoreInfo}
              id="rating"
              .label=${capitalizeFirstLetter(
                this.hass.localize(
                  "ui.panel.config.apps.dashboard.capability.label.rating"
                )
              )}
            >
              <ha-svg-icon slot="icon" .path=${RATING_ICON[this.addon.rating]}>
              </ha-svg-icon>
            </ha-assist-chip>
            ${this.addon.host_network
              ? html`
                  <ha-assist-chip
                    filled
                    @click=${this._showMoreInfo}
                    id="host_network"
                    .label=${capitalizeFirstLetter(
                      this.hass.localize(
                        "ui.panel.config.apps.dashboard.capability.label.host"
                      )
                    )}
                  >
                    <ha-svg-icon slot="icon" .path=${mdiNetwork}> </ha-svg-icon>
                  </ha-assist-chip>
                `
              : nothing}
            ${this.addon.full_access
              ? html`
                  <ha-assist-chip
                    filled
                    @click=${this._showMoreInfo}
                    id="full_access"
                    .label=${capitalizeFirstLetter(
                      this.hass.localize(
                        "ui.panel.config.apps.dashboard.capability.label.hardware"
                      )
                    )}
                  >
                    <ha-svg-icon slot="icon" .path=${mdiChip}></ha-svg-icon>
                  </ha-assist-chip>
                `
              : nothing}
            ${this.addon.homeassistant_api
              ? html`
                  <ha-assist-chip
                    filled
                    @click=${this._showMoreInfo}
                    id="homeassistant_api"
                    .label=${capitalizeFirstLetter(
                      this.hass.localize(
                        "ui.panel.config.apps.dashboard.capability.label.core"
                      )
                    )}
                  >
                    <ha-svg-icon
                      slot="icon"
                      .path=${mdiHomeAssistant}
                    ></ha-svg-icon>
                  </ha-assist-chip>
                `
              : nothing}
            ${this._computeHassioApi
              ? html`
                  <ha-assist-chip
                    filled
                    @click=${this._showMoreInfo}
                    id="hassio_api"
                    .label=${capitalizeFirstLetter(
                      this.hass.localize(
                        `ui.panel.config.apps.dashboard.capability.role.${this.addon.hassio_role}`
                      ) || this.addon.hassio_role
                    )}
                  >
                    <ha-svg-icon
                      slot="icon"
                      .path=${mdiHomeAssistant}
                    ></ha-svg-icon>
                  </ha-assist-chip>
                `
              : nothing}
            ${this.addon.docker_api
              ? html`
                  <ha-assist-chip
                    filled
                    @click=${this._showMoreInfo}
                    id="docker_api"
                    .label=${capitalizeFirstLetter(
                      this.hass.localize(
                        "ui.panel.config.apps.dashboard.capability.label.docker"
                      )
                    )}
                  >
                    <ha-svg-icon slot="icon" .path=${mdiDocker}></ha-svg-icon>
                  </ha-assist-chip>
                `
              : nothing}
            ${this.addon.host_pid
              ? html`
                  <ha-assist-chip
                    filled
                    @click=${this._showMoreInfo}
                    id="host_pid"
                    .label=${capitalizeFirstLetter(
                      this.hass.localize(
                        "ui.panel.config.apps.dashboard.capability.label.host_pid"
                      )
                    )}
                  >
                    <ha-svg-icon slot="icon" .path=${mdiPound}></ha-svg-icon>
                  </ha-assist-chip>
                `
              : nothing}
            ${this.addon.apparmor !== "default"
              ? html`
                  <ha-assist-chip
                    filled
                    @click=${this._showMoreInfo}
                    class=${this._computeApparmorClassName}
                    id="apparmor"
                    .label=${capitalizeFirstLetter(
                      this.hass.localize(
                        "ui.panel.config.apps.dashboard.capability.label.apparmor"
                      )
                    )}
                  >
                    <ha-svg-icon slot="icon" .path=${mdiShield}></ha-svg-icon>
                  </ha-assist-chip>
                `
              : nothing}
            ${this.addon.auth_api
              ? html`
                  <ha-assist-chip
                    filled
                    @click=${this._showMoreInfo}
                    id="auth_api"
                    .label=${capitalizeFirstLetter(
                      this.hass.localize(
                        "ui.panel.config.apps.dashboard.capability.label.auth"
                      )
                    )}
                  >
                    <ha-svg-icon slot="icon" .path=${mdiKey}></ha-svg-icon>
                  </ha-assist-chip>
                `
              : nothing}
            ${this.addon.ingress
              ? html`
                  <ha-assist-chip
                    filled
                    @click=${this._showMoreInfo}
                    id="ingress"
                    .label=${capitalizeFirstLetter(
                      this.hass.localize(
                        "ui.panel.config.apps.dashboard.capability.label.ingress"
                      )
                    )}
                  >
                    <ha-svg-icon
                      slot="icon"
                      .path=${mdiCursorDefaultClickOutline}
                    ></ha-svg-icon>
                  </ha-assist-chip>
                `
              : nothing}
            ${this.addon.signed
              ? html`
                  <ha-assist-chip
                    filled
                    @click=${this._showMoreInfo}
                    id="signed"
                    .label=${capitalizeFirstLetter(
                      this.hass.localize(
                        "ui.panel.config.apps.dashboard.capability.label.signed"
                      )
                    )}
                  >
                    <ha-svg-icon slot="icon" .path=${mdiLinkLock}></ha-svg-icon>
                  </ha-assist-chip>
                `
              : nothing}
            ${systemManaged
              ? html`
                  <ha-assist-chip
                    filled
                    @click=${this._showSystemManagedInfo}
                    id="system_managed"
                    .label=${capitalizeFirstLetter(
                      this.hass.localize(
                        "ui.panel.config.apps.dashboard.system_managed.badge"
                      )
                    )}
                  >
                    <ha-svg-icon
                      slot="icon"
                      .path=${mdiHomeAssistant}
                    ></ha-svg-icon>
                  </ha-assist-chip>
                `
              : nothing}
          </ha-chip-set>

          <div class="description light-color">
            ${this.addon.description}.<br />
            ${this.hass.localize(
              "ui.panel.config.apps.dashboard.visit_app_page",
              {
                name: html`<a
                  href=${this.addon.url!}
                  target="_blank"
                  rel="noreferrer"
                  >${getAppDisplayName(this.addon.name, this.addon.stage)}</a
                >`,
              }
            )}
          </div>
          <div class="addon-container">
            <div>
              ${this.addon.logo
                ? html`
                    <img
                      class="logo"
                      alt=""
                      src="/api/hassio/addons/${this.addon.slug}/logo"
                    />
                  `
                : nothing}
              ${this.addon.version
                ? html`
                    <div
                      class=${classMap({
                        "addon-options": true,
                        started: this.addon.state === "started",
                      })}
                    >
                      <ha-settings-row ?three-line=${this.narrow}>
                        <span slot="heading">
                          ${this.hass.localize(
                            "ui.panel.config.apps.dashboard.option.boot.title"
                          )}
                        </span>
                        <span slot="description">
                          ${this.hass.localize(
                            "ui.panel.config.apps.dashboard.option.boot.description"
                          )}
                        </span>
                        <ha-switch
                          .disabled=${systemManaged && !this.controlEnabled}
                          @change=${this._startOnBootToggled}
                          .checked=${this.addon.boot === "auto"}
                          haptic
                        ></ha-switch>
                      </ha-settings-row>

                      ${this.addon.startup !== "once"
                        ? html`
                            <ha-settings-row ?three-line=${this.narrow}>
                              <span slot="heading">
                                ${this.hass.localize(
                                  "ui.panel.config.apps.dashboard.option.watchdog.title"
                                )}
                              </span>
                              <span slot="description">
                                ${this.hass.localize(
                                  "ui.panel.config.apps.dashboard.option.watchdog.description"
                                )}
                              </span>
                              <ha-switch
                                .disabled=${systemManaged &&
                                !this.controlEnabled}
                                @change=${this._watchdogToggled}
                                .checked=${this.addon.watchdog || false}
                                haptic
                              ></ha-switch>
                            </ha-settings-row>
                          `
                        : nothing}
                      <ha-settings-row ?three-line=${this.narrow}>
                        <span slot="heading">
                          ${this.hass.localize(
                            "ui.panel.config.apps.dashboard.option.auto_update.title"
                          )}
                        </span>
                        <span slot="description">
                          ${this.hass.localize(
                            "ui.panel.config.apps.dashboard.option.auto_update.description"
                          )}
                        </span>
                        <ha-switch
                          .disabled=${systemManaged && !this.controlEnabled}
                          @change=${this._autoUpdateToggled}
                          .checked=${this.addon.auto_update}
                          haptic
                        ></ha-switch>
                      </ha-settings-row>
                      ${!this._computeCannotIngressSidebar && this.addon.ingress
                        ? html`
                            <ha-settings-row ?three-line=${this.narrow}>
                              <span slot="heading">
                                ${this.hass.localize(
                                  "ui.panel.config.apps.dashboard.option.ingress_panel.title"
                                )}
                              </span>
                              <span slot="description">
                                ${this.hass.localize(
                                  "ui.panel.config.apps.dashboard.option.ingress_panel.description"
                                )}
                              </span>
                              <ha-switch
                                .disabled=${systemManaged &&
                                !this.controlEnabled}
                                @change=${this._panelToggled}
                                .checked=${this.addon.ingress_panel}
                                haptic
                              ></ha-switch>
                            </ha-settings-row>
                          `
                        : nothing}
                      ${this._computeUsesProtectedOptions
                        ? html`
                            <ha-settings-row ?three-line=${this.narrow}>
                              <span slot="heading">
                                ${this.hass.localize(
                                  "ui.panel.config.apps.dashboard.option.protected.title"
                                )}
                              </span>
                              <span slot="description">
                                ${this.hass.localize(
                                  "ui.panel.config.apps.dashboard.option.protected.description"
                                )}
                              </span>
                              <ha-switch
                                .disabled=${systemManaged &&
                                !this.controlEnabled}
                                @change=${this._protectionToggled}
                                .checked=${this.addon.protected}
                                haptic
                              ></ha-switch>
                            </ha-settings-row>
                          `
                        : nothing}
                    </div>
                  `
                : nothing}
            </div>
            <div>
              ${this.addon.version && this.addon.state === "started"
                ? html`<ha-settings-row ?three-line=${this.narrow} empty>
                      <span slot="heading">
                        ${this.hass.localize(
                          "ui.panel.config.apps.dashboard.hostname"
                        )}
                      </span>
                      <code slot="description"> ${this.addon.hostname} </code>
                    </ha-settings-row>
                    ${metrics.map(
                      (metric) => html`
                        <supervisor-app-metric
                          .description=${metric.description}
                          .value=${metric.value ?? 0}
                          .tooltip=${metric.tooltip}
                        ></supervisor-app-metric>
                      `
                    )}`
                : nothing}
            </div>
          </div>
          ${this._error
            ? html`<ha-alert alert-type="error">${this._error}</ha-alert>`
            : nothing}
        </div>
        <div class="card-actions">
          <div>
            ${this.addon.version
              ? this._computeIsRunning
                ? html`
                    <ha-progress-button
                      variant="danger"
                      appearance="plain"
                      @click=${this._stopClicked}
                      .disabled=${systemManaged && !this.controlEnabled}
                    >
                      ${this.hass.localize(
                        "ui.panel.config.apps.dashboard.stop"
                      )}
                    </ha-progress-button>
                    <ha-progress-button
                      variant="danger"
                      appearance="plain"
                      @click=${this._restartClicked}
                      .disabled=${systemManaged && !this.controlEnabled}
                    >
                      ${this.hass.localize(
                        "ui.panel.config.apps.dashboard.restart"
                      )}
                    </ha-progress-button>
                  `
                : html`
                    <ha-progress-button
                      @click=${this._startClicked}
                      .progress=${this.addon.state === "startup"}
                      appearance="plain"
                    >
                      ${this.hass.localize(
                        "ui.panel.config.apps.dashboard.start"
                      )}
                    </ha-progress-button>
                  `
              : nothing}
          </div>
          <div>
            ${this.addon.version
              ? html`
                  <ha-progress-button
                    variant="danger"
                    appearance="plain"
                    @click=${this._uninstallClicked}
                    .disabled=${systemManaged && !this.controlEnabled}
                  >
                    ${this.hass.localize(
                      "ui.panel.config.apps.dashboard.uninstall"
                    )}
                  </ha-progress-button>
                  ${this.addon.build
                    ? html`
                        <ha-progress-button
                          variant="danger"
                          appearance="plain"
                          @click=${this._rebuildClicked}
                        >
                          ${this.hass.localize(
                            "ui.panel.config.apps.dashboard.rebuild"
                          )}
                        </ha-progress-button>
                      `
                    : nothing}
                  ${this._computeShowWebUI || this._computeShowIngressUI
                    ? html`
                        <ha-button
                          href=${ifDefined(
                            !this._computeShowIngressUI
                              ? this._pathWebui!
                              : nothing
                          )}
                          target=${ifDefined(
                            !this._computeShowIngressUI ? "_blank" : nothing
                          )}
                          rel=${ifDefined(
                            !this._computeShowIngressUI ? "noopener" : nothing
                          )}
                          @click=${!this._computeShowWebUI
                            ? this._openIngress
                            : undefined}
                        >
                          ${this.hass.localize(
                            "ui.panel.config.apps.dashboard.open_web_ui"
                          )}
                        </ha-button>
                      `
                    : nothing}
                `
              : html`
                  <ha-progress-button
                    .disabled=${!this.addon.available}
                    @click=${this._installClicked}
                  >
                    ${this.hass.localize(
                      "ui.panel.config.apps.dashboard.install"
                    )}
                  </ha-progress-button>
                `}
          </div>
        </div>
      </ha-card>

      ${this.addon.long_description
        ? html`
            <ha-card class="long-description" outlined>
              <div class="card-content">
                <ha-markdown
                  .content=${this.addon.long_description}
                  lazy-images
                ></ha-markdown>
              </div>
            </ha-card>
          `
        : nothing}
    `;
  }

  protected updated(changedProps) {
    super.updated(changedProps);
    if (changedProps.has("addon")) {
      this._loadData();
      if (
        !this._fetchDataTimeout &&
        this.addon &&
        "state" in this.addon &&
        this.addon.state === "startup"
      ) {
        // App is starting up, wait for it to start
        this._scheduleDataUpdate();
      }
    }
  }

  private _scheduleDataUpdate() {
    this._fetchDataTimeout = window.setTimeout(async () => {
      const addon = await fetchHassioAddonInfo(this.hass, this.addon.slug);
      if (addon.state !== "startup") {
        this._fetchDataTimeout = undefined;
        this.addon = addon;
        const eventdata = {
          success: true,
          response: undefined,
          path: "start",
        };
        fireEvent(this, "hass-api-called", eventdata);
      } else {
        this._scheduleDataUpdate();
      }
    }, 500);
  }

  private async _loadData(): Promise<void> {
    if ("state" in this.addon && this.addon.state === "started") {
      this._metrics = await fetchHassioStats(
        this.hass,
        `addons/${this.addon.slug}`
      );
    }
  }

  private get _computeHassioApi(): boolean {
    return (
      this.addon.hassio_api &&
      (this.addon.hassio_role === "manager" ||
        this.addon.hassio_role === "admin")
    );
  }

  private get _computeApparmorClassName(): string {
    if (this.addon.apparmor === "profile") {
      return "green";
    }
    if (this.addon.apparmor === "disable") {
      return "red";
    }
    return "";
  }

  private _showMoreInfo(ev): void {
    const id = ev.currentTarget.id as AddonCapability;
    showAlertDialog(this, {
      title: this.hass.localize(
        `ui.panel.config.apps.dashboard.capability.${id}.title`
      ),
      text: this.hass.localize(
        `ui.panel.config.apps.dashboard.capability.${id}.description`
      ),
    });
  }

  private _showSystemManagedInfo() {
    showAlertDialog(this, {
      title: this.hass.localize(
        "ui.panel.config.apps.dashboard.system_managed.title"
      ),
      text: this.hass.localize(
        "ui.panel.config.apps.dashboard.system_managed.description"
      ),
    });
  }

  private get _computeIsRunning(): boolean {
    return (this.addon as HassioAddonDetails)?.state === "started";
  }

  private get _pathWebui(): string | null {
    return (this.addon as HassioAddonDetails).webui!.replace(
      "[HOST]",
      document.location.hostname
    );
  }

  private get _computeShowWebUI(): boolean | "" | null {
    return (
      !this.addon.ingress &&
      (this.addon as HassioAddonDetails).webui &&
      this._computeIsRunning
    );
  }

  private _openIngress(): void {
    navigate(`/app/${this.addon.slug}`);
  }

  private get _computeShowIngressUI(): boolean {
    return this.addon.ingress && this._computeIsRunning;
  }

  private get _computeCannotIngressSidebar(): boolean {
    return (
      !this.addon.ingress || !atLeastVersion(this.hass.config.version, 0, 92)
    );
  }

  private get _computeUsesProtectedOptions(): boolean {
    return (
      this.addon.docker_api || this.addon.full_access || this.addon.host_pid
    );
  }

  private async _startOnBootToggled(): Promise<void> {
    this._error = undefined;
    const data: HassioAddonSetOptionParams = {
      boot:
        (this.addon as HassioAddonDetails).boot === "auto" ? "manual" : "auto",
    };
    try {
      await setHassioAddonOption(this.hass, this.addon.slug, data);
      const eventdata = {
        success: true,
        response: undefined,
        path: "option",
      };
      fireEvent(this, "hass-api-called", eventdata);
    } catch (err: any) {
      this._error = this.hass.localize(
        "ui.panel.config.apps.dashboard.failed_to_save",
        {
          error: extractApiErrorMessage(err),
        }
      );
    }
  }

  private async _watchdogToggled(): Promise<void> {
    this._error = undefined;
    const data: HassioAddonSetOptionParams = {
      watchdog: !(this.addon as HassioAddonDetails).watchdog,
    };
    try {
      await setHassioAddonOption(this.hass, this.addon.slug, data);
      const eventdata = {
        success: true,
        response: undefined,
        path: "option",
      };
      fireEvent(this, "hass-api-called", eventdata);
    } catch (err: any) {
      this._error = this.hass.localize(
        "ui.panel.config.apps.dashboard.failed_to_save",
        {
          error: extractApiErrorMessage(err),
        }
      );
    }
  }

  private async _autoUpdateToggled(): Promise<void> {
    this._error = undefined;
    const data: HassioAddonSetOptionParams = {
      auto_update: !(this.addon as HassioAddonDetails).auto_update,
    };
    try {
      await setHassioAddonOption(this.hass, this.addon.slug, data);
      const eventdata = {
        success: true,
        response: undefined,
        path: "option",
      };
      fireEvent(this, "hass-api-called", eventdata);
    } catch (err: any) {
      this._error = this.hass.localize(
        "ui.panel.config.apps.dashboard.failed_to_save",
        {
          error: extractApiErrorMessage(err),
        }
      );
    }
  }

  private async _protectionToggled(): Promise<void> {
    this._error = undefined;
    const data: HassioAddonSetSecurityParams = {
      protected: !(this.addon as HassioAddonDetails).protected,
    };
    try {
      await setHassioAddonSecurity(this.hass, this.addon.slug, data);
      const eventdata = {
        success: true,
        response: undefined,
        path: "security",
      };
      fireEvent(this, "hass-api-called", eventdata);
    } catch (err: any) {
      this._error = this.hass.localize(
        "ui.panel.config.apps.dashboard.failed_to_save",
        {
          error: extractApiErrorMessage(err),
        }
      );
    }
  }

  private async _panelToggled(): Promise<void> {
    this._error = undefined;
    const data: HassioAddonSetOptionParams = {
      ingress_panel: !(this.addon as HassioAddonDetails).ingress_panel,
    };
    try {
      await setHassioAddonOption(this.hass, this.addon.slug, data);
      const eventdata = {
        success: true,
        response: undefined,
        path: "option",
      };
      fireEvent(this, "hass-api-called", eventdata);
    } catch (err: any) {
      this._error = this.hass.localize(
        "ui.panel.config.apps.dashboard.failed_to_save",
        {
          error: extractApiErrorMessage(err),
        }
      );
    }
  }

  private async _openChangelog(): Promise<void> {
    try {
      const content = await fetchHassioAddonChangelog(
        this.hass,
        this.addon.slug
      );

      showAlertDialog(this, {
        title: this.hass.localize("ui.panel.config.apps.dashboard.changelog"),
        text: html`<ha-markdown
          .content=${extractChangelog(
            this.addon as HassioAddonDetails,
            content
          )}
        ></ha-markdown>`,
      });
    } catch (err: any) {
      showAlertDialog(this, {
        title: this.hass.localize(
          "ui.panel.config.apps.dashboard.action_error.get_changelog"
        ),
        text: extractApiErrorMessage(err),
      });
    }
  }

  private _updateComplete() {
    const eventdata = {
      success: true,
      response: undefined,
      path: "install",
    };
    fireEvent(this, "hass-api-called", eventdata);
  }

  private async _installClicked(ev: CustomEvent): Promise<void> {
    const button = ev.currentTarget as any;
    button.progress = true;

    try {
      await installHassioAddon(this.hass, this.addon.slug);
      const eventdata = {
        success: true,
        response: undefined,
        path: "install",
      };
      fireEvent(this, "hass-api-called", eventdata);
    } catch (err: any) {
      showAlertDialog(this, {
        title: this.hass.localize(
          "ui.panel.config.apps.dashboard.action_error.install"
        ),
        text: extractApiErrorMessage(err),
      });
    }
    button.progress = false;
  }

  private async _stopClicked(ev: CustomEvent): Promise<void> {
    if (this._isSystemManaged(this.addon) && !this.controlEnabled) {
      return;
    }

    const button = ev.currentTarget as any;
    button.progress = true;

    try {
      await stopHassioAddon(this.hass, this.addon.slug);
      const eventdata = {
        success: true,
        response: undefined,
        path: "stop",
      };
      fireEvent(this, "hass-api-called", eventdata);
    } catch (err: any) {
      showAlertDialog(this, {
        title: this.hass.localize(
          "ui.panel.config.apps.dashboard.action_error.stop"
        ),
        text: extractApiErrorMessage(err),
      });
    }
    button.progress = false;
  }

  private async _restartClicked(ev: CustomEvent): Promise<void> {
    if (this._isSystemManaged(this.addon) && !this.controlEnabled) {
      return;
    }

    const button = ev.currentTarget as any;
    button.progress = true;

    try {
      await restartHassioAddon(this.hass, this.addon.slug);
      const eventdata = {
        success: true,
        response: undefined,
        path: "restart",
      };
      fireEvent(this, "hass-api-called", eventdata);
    } catch (err: any) {
      showAlertDialog(this, {
        title: this.hass.localize(
          "ui.panel.config.apps.dashboard.action_error.restart"
        ),
        text: extractApiErrorMessage(err),
      });
    }
    button.progress = false;
  }

  private async _rebuildClicked(ev: CustomEvent): Promise<void> {
    const button = ev.currentTarget as any;
    button.progress = true;

    try {
      await rebuildLocalAddon(this.hass, this.addon.slug);
    } catch (err: any) {
      showAlertDialog(this, {
        title: this.hass.localize(
          "ui.panel.config.apps.dashboard.action_error.rebuild"
        ),
        text: extractApiErrorMessage(err),
      });
    }
    button.progress = false;
  }

  private async _startClicked(ev: CustomEvent): Promise<void> {
    const button = ev.currentTarget as any;
    button.progress = true;
    try {
      const validate = await validateHassioAddonOption(
        this.hass,
        this.addon.slug
      );
      if (!validate.valid) {
        await showConfirmationDialog(this, {
          title: this.hass.localize(
            "ui.panel.config.apps.dashboard.action_error.start_invalid_config"
          ),
          text: validate.message.split(" Got ")[0],
          confirm: () => this._openConfiguration(),
          confirmText: this.hass.localize(
            "ui.panel.config.apps.dashboard.action_error.go_to_config"
          ),
          dismissText: this.hass.localize("ui.common.cancel"),
        });
        button.actionError();
        button.progress = false;
        return;
      }
    } catch (err: any) {
      button.actionError();
      button.progress = false;
      showAlertDialog(this, {
        title: this.hass.localize(
          "ui.panel.config.apps.dashboard.action_error.validate_config"
        ),
        text: extractApiErrorMessage(err),
      });
      return;
    }

    try {
      await startHassioAddon(this.hass, this.addon.slug);
      this.addon = await fetchHassioAddonInfo(this.hass, this.addon.slug);
      const eventdata = {
        success: true,
        response: undefined,
        path: "start",
      };
      fireEvent(this, "hass-api-called", eventdata);
    } catch (err: any) {
      button.actionError();
      button.progress = false;
      showAlertDialog(this, {
        title: this.hass.localize(
          "ui.panel.config.apps.dashboard.action_error.start"
        ),
        text: extractApiErrorMessage(err),
      });
      return;
    }
    button.actionSuccess();
    button.progress = false;
  }

  private _openConfiguration(): void {
    navigate(`/config/app/${this.addon.slug}/config`);
  }

  private async _uninstallClicked(ev: CustomEvent): Promise<void> {
    if (this._isSystemManaged(this.addon) && !this.controlEnabled) {
      return;
    }

    const button = ev.currentTarget as any;
    button.progress = true;
    let removeData = false;
    const _removeDataToggled = (e: Event) => {
      removeData = (e.target as HaSwitch).checked;
    };

    const confirmed = await showConfirmationDialog(this, {
      title: this.hass.localize(
        "ui.panel.config.apps.dashboard.uninstall_dialog.title",
        {
          name: getAppDisplayName(this.addon.name, this.addon.stage),
        }
      ),
      text: html`
        <ha-formfield
          .label=${html`<p>
            ${this.hass.localize(
              "ui.panel.config.apps.dashboard.uninstall_dialog.remove_data"
            )}
          </p>`}
        >
          <ha-switch
            @change=${_removeDataToggled}
            .checked=${removeData}
            haptic
          ></ha-switch>
        </ha-formfield>
      `,
      confirmText: this.hass.localize(
        "ui.panel.config.apps.dashboard.uninstall_dialog.uninstall"
      ),
      dismissText: this.hass.localize("ui.common.cancel"),
      destructive: true,
    });

    if (!confirmed) {
      button.progress = false;
      return;
    }

    this._error = undefined;
    try {
      await uninstallHassioAddon(this.hass, this.addon.slug, removeData);
      const eventdata = {
        success: true,
        response: undefined,
        path: "uninstall",
      };
      fireEvent(this, "hass-api-called", eventdata);
      button.actionSuccess();
    } catch (err: any) {
      showAlertDialog(this, {
        title: this.hass.localize(
          "ui.panel.config.apps.dashboard.action_error.uninstall"
        ),
        text: extractApiErrorMessage(err),
      });
      button.actionError();
    }
    button.progress = false;
  }

  private _isSystemManaged = memoizeOne(
    (addon: HassioAddonDetails | StoreAddonDetails) =>
      "system_managed" in addon && addon.system_managed
  );

  static get styles(): CSSResultGroup {
    return [
      haStyle,
      css`
        :host {
          display: block;
        }
        ha-card {
          display: block;
          margin-bottom: var(--ha-space-4);
        }
        ha-card.warning {
          background-color: var(--error-color);
          color: white;
        }
        ha-card.warning .card-header {
          color: white;
        }
        ha-card.warning .card-content {
          color: white;
        }
        ha-card.warning ha-button {
          --mdc-theme-primary: white !important;
        }
        .warning {
          color: var(--error-color);
          --mdc-theme-primary: var(--error-color);
        }
        .light-color {
          color: var(--secondary-text-color);
        }
        .addon-header {
          padding-left: var(--ha-space-2);
          padding-inline-start: var(--ha-space-2);
          padding-inline-end: initial;
          font-size: var(--ha-font-size-2xl);
          color: var(--ha-card-header-color, var(--primary-text-color));
        }
        .addon-version {
          float: var(--float-end);
          font-size: var(--ha-font-size-l);
          vertical-align: middle;
        }
        .errors {
          color: var(--error-color);
          margin-bottom: var(--ha-space-4);
        }
        .description {
          margin-bottom: var(--ha-space-4);
        }
        img.logo {
          max-width: 100%;
          max-height: 60px;
          margin: var(--ha-space-4) 0;
          display: block;
        }

        ha-svg-icon.running {
          color: var(--success-color);
        }
        ha-svg-icon.stopped {
          color: var(--error-color);
        }
        protection-enable ha-button {
          --mdc-theme-primary: white;
        }
        .description a {
          color: var(--primary-color);
        }
        .long-description {
          direction: ltr;
        }
        ha-assist-chip {
          --md-sys-color-primary: var(--text-primary-color);
          --md-sys-color-on-surface: var(--text-primary-color);
          --ha-assist-chip-filled-container-color: var(--primary-color);
        }

        .red {
          --ha-assist-chip-filled-container-color: var(
            --label-badge-red,
            #df4c1e
          );
        }
        .blue {
          --ha-assist-chip-filled-container-color: var(
            --label-badge-blue,
            #039be5
          );
        }
        .green {
          --ha-assist-chip-filled-container-color: var(
            --label-badge-green,
            #0da035
          );
        }
        .yellow {
          --ha-assist-chip-filled-container-color: var(
            --label-badge-yellow,
            #f4b400
          );
        }
        .capabilities {
          margin-bottom: var(--ha-space-4);
        }
        .card-actions {
          justify-content: space-between;
          display: flex;
          direction: var(--direction);
        }
        .changelog {
          display: contents;
        }
        .changelog-link {
          color: var(--primary-color);
          text-decoration: underline;
          cursor: pointer;
        }
        ha-markdown {
          padding: var(--ha-space-4);
          --markdown-image-background-color: transparent;
          --markdown-image-border-radius: 0;
          --markdown-image-min-height: auto;
          --markdown-image-text-indent: 0;
          --markdown-image-transition: none;
        }
        ha-settings-row,
        supervisor-app-metric {
          --settings-row-prefix-flex: 2;
        }
        ha-settings-row {
          padding: 0;
          height: 54px;
          width: 100%;
        }
        ha-settings-row > span[slot="description"] {
          white-space: normal;
          color: var(--secondary-text-color);
        }
        ha-settings-row[three-line] {
          height: 74px;
        }
        .addon-options ha-settings-row {
          padding: 0;
          width: 100%;
          --settings-row-body-padding-top: 0;
          --settings-row-body-padding-bottom: 0;
          --settings-row-content-padding-block: var(--ha-space-2);
          --settings-row-switch-padding-block: var(--ha-space-2);
        }

        .addon-options {
          max-width: 90%;
        }

        .addon-container {
          display: grid;
          grid-auto-flow: column;
          grid-template-columns: 60% 40%;
        }

        .addon-container > div:last-of-type {
          align-self: end;
        }

        ha-alert ha-button {
          --mdc-theme-primary: var(--primary-text-color);
        }

        :host > ha-alert {
          display: block;
          margin-bottom: var(--ha-space-4);
        }

        a {
          text-decoration: none;
        }

        supervisor-app-update-available-card {
          padding-bottom: var(--ha-space-4);
        }

        @media (max-width: 720px) {
          .addon-options {
            max-width: 100%;
          }
          .addon-container {
            display: block;
          }
        }
      `,
    ];
  }
}
declare global {
  interface HTMLElementTagNameMap {
    "supervisor-app-info": SupervisorAppInfo;
  }
}
