// Copyright (c) Jupyter Development Team.
// Copyright (c) Microsoft Corporation.
// Distributed under the terms of the Modified BSD License.

import { css, ElementStyles } from '@microsoft/fast-element';
import {
  disabledCursor,
  display,
  focusVisible,
  forcedColorsStylesheetBehavior,
  FoundationElementTemplate,
  SwitchOptions
} from '@microsoft/fast-foundation';
import { SystemColors } from '@microsoft/fast-web-utilities';
import {
  accentFillActive,
  accentFillFocus,
  accentFillHover,
  accentFillRest,
  bodyFont,
  controlCornerRadius,
  designUnit,
  disabledOpacity,
  errorFillActive,
  errorFillFocus,
  errorFillHover,
  errorFillRest,
  focusStrokeWidth,
  foregroundOnAccentActive,
  foregroundOnAccentHover,
  foregroundOnAccentRest,
  neutralFillInputActive,
  neutralFillInputHover,
  neutralFillInputRest,
  neutralForegroundRest,
  neutralStrokeActive,
  neutralStrokeHover,
  neutralStrokeRest,
  strokeWidth,
  typeRampBaseFontSize,
  typeRampBaseLineHeight
} from '../design-tokens.js';
import {
  DirectionalStyleSheetBehavior,
  heightNumber
} from '../styles/index.js';

/**
 * Styles for Switch
 * @public
 */
export const switchStyles: FoundationElementTemplate<
  ElementStyles,
  SwitchOptions
> = (context, definition) =>
  css`
    :host([hidden]) {
      display: none;
    }

    ${display('inline-flex')} :host {
      align-items: center;
      outline: none;
      font-family: ${bodyFont};
      margin: calc(${designUnit} * 1px) 0;
      ${
        /*
         * Chromium likes to select label text or the default slot when
         * the checkbox is clicked. Maybe there is a better solution here?
         */ ''
      } user-select: none;
    }

    :host([disabled]) {
      opacity: ${disabledOpacity};
    }

    :host([disabled]) .label,
    :host([readonly]) .label,
    :host([readonly]) .switch,
    :host([disabled]) .switch {
      cursor: ${disabledCursor};
    }

    .switch {
      position: relative;
      outline: none;
      box-sizing: border-box;
      width: calc(${heightNumber} * 1px);
      height: calc((${heightNumber} / 2 + ${designUnit}) * 1px);
      background: ${neutralFillInputRest};
      border-radius: calc(${controlCornerRadius} * 1px);
      border: calc(${strokeWidth} * 1px) solid ${neutralStrokeRest};
    }

    :host([aria-invalid='true']) .switch {
      border-color: ${errorFillRest};
    }

    .switch:hover {
      background: ${neutralFillInputHover};
      border-color: ${neutralStrokeHover};
      cursor: pointer;
    }

    :host([disabled]) .switch:hover,
    :host([readonly]) .switch:hover {
      background: ${neutralFillInputHover};
      border-color: ${neutralStrokeHover};
      cursor: ${disabledCursor};
    }

    :host([aria-invalid='true'][disabled]) .switch:hover,
    :host([aria-invalid='true'][readonly]) .switch:hover {
      border-color: ${errorFillHover};
    }

    :host(:not([disabled])) .switch:active {
      background: ${neutralFillInputActive};
      border-color: ${neutralStrokeActive};
    }

    :host([aria-invalid='true']:not([disabled])) .switch:active {
      border-color: ${errorFillActive};
    }

    :host(:${focusVisible}) .switch {
      outline-offset: 2px;
      outline: solid calc(${focusStrokeWidth} * 1px) ${accentFillFocus};
    }

    :host([aria-invalid='true']:${focusVisible}) .switch {
      outline-color: ${errorFillFocus};
    }

    .checked-indicator {
      position: absolute;
      top: 5px;
      bottom: 5px;
      background: ${neutralForegroundRest};
      border-radius: calc(${controlCornerRadius} * 1px);
      transition: all 0.2s ease-in-out;
    }

    .status-message {
      color: ${neutralForegroundRest};
      cursor: pointer;
      font-size: ${typeRampBaseFontSize};
      line-height: ${typeRampBaseLineHeight};
    }

    :host([disabled]) .status-message,
    :host([readonly]) .status-message {
      cursor: ${disabledCursor};
    }

    .label {
      color: ${neutralForegroundRest};
      margin-inline-end: calc(${designUnit} * 2px + 2px);
      font-size: ${typeRampBaseFontSize};
      line-height: ${typeRampBaseLineHeight};
      cursor: pointer;
    }

    .label__hidden {
      display: none;
      visibility: hidden;
    }

    ::slotted([slot='checked-message']),
    ::slotted([slot='unchecked-message']) {
      margin-inline-start: calc(${designUnit} * 2px + 2px);
    }

    :host([aria-checked='true']) .checked-indicator {
      background: ${foregroundOnAccentRest};
    }

    :host([aria-checked='true']) .switch {
      background: ${accentFillRest};
      border-color: ${accentFillRest};
    }

    :host([aria-checked='true']:not([disabled])) .switch:hover {
      background: ${accentFillHover};
      border-color: ${accentFillHover};
    }

    :host([aria-invalid='true'][aria-checked='true']) .switch {
      background-color: ${errorFillRest};
      border-color: ${errorFillRest};
    }

    :host([aria-invalid='true'][aria-checked='true']:not([disabled]))
      .switch:hover {
      background-color: ${errorFillHover};
      border-color: ${errorFillHover};
    }

    :host([aria-checked='true']:not([disabled]))
      .switch:hover
      .checked-indicator {
      background: ${foregroundOnAccentHover};
    }

    :host([aria-checked='true']:not([disabled])) .switch:active {
      background: ${accentFillActive};
      border-color: ${accentFillActive};
    }

    :host([aria-invalid='true'][aria-checked='true']:not([disabled]))
      .switch:active {
      background-color: ${errorFillActive};
      border-color: ${errorFillActive};
    }

    :host([aria-checked='true']:not([disabled]))
      .switch:active
      .checked-indicator {
      background: ${foregroundOnAccentActive};
    }

    :host([aria-checked="true"]:${focusVisible}:not([disabled])) .switch {
      outline: solid calc(${focusStrokeWidth} * 1px) ${accentFillFocus};
    }

    :host([aria-invalid='true'][aria-checked="true"]:${focusVisible}:not([disabled])) .switch {
      outline-color: ${errorFillFocus};
    }

    .unchecked-message {
      display: block;
    }

    .checked-message {
      display: none;
    }

    :host([aria-checked='true']) .unchecked-message {
      display: none;
    }

    :host([aria-checked='true']) .checked-message {
      display: block;
    }
  `.withBehaviors(
    forcedColorsStylesheetBehavior(css`
      .checked-indicator,
      :host(:not([disabled])) .switch:active .checked-indicator {
        forced-color-adjust: none;
        background: ${SystemColors.FieldText};
      }
      .switch {
        forced-color-adjust: none;
        background: ${SystemColors.Field};
        border-color: ${SystemColors.FieldText};
      }
      :host([aria-invalid='true']) .switch {
        border-style: dashed;
      }
      :host(:not([disabled])) .switch:hover {
        background: ${SystemColors.HighlightText};
        border-color: ${SystemColors.Highlight};
      }
      :host([aria-checked='true']) .switch {
        background: ${SystemColors.Highlight};
        border-color: ${SystemColors.Highlight};
      }
      :host([aria-checked='true']:not([disabled])) .switch:hover,
      :host(:not([disabled])) .switch:active {
        background: ${SystemColors.HighlightText};
        border-color: ${SystemColors.Highlight};
      }
      :host([aria-checked='true']) .checked-indicator {
        background: ${SystemColors.HighlightText};
      }
      :host([aria-checked='true']:not([disabled]))
        .switch:hover
        .checked-indicator {
        background: ${SystemColors.Highlight};
      }
      :host([disabled]) {
        opacity: 1;
      }
      :host(:${focusVisible}) .switch {
        border-color: ${SystemColors.Highlight};
        outline-offset: 2px;
        outline: solid calc(${focusStrokeWidth} * 1px) ${SystemColors.FieldText};
      }
      :host([aria-checked="true"]:${focusVisible}:not([disabled])) .switch {
        outline: solid calc(${focusStrokeWidth} * 1px) ${SystemColors.FieldText};
      }
      :host([disabled]) .checked-indicator {
        background: ${SystemColors.GrayText};
      }
      :host([disabled]) .switch {
        background: ${SystemColors.Field};
        border-color: ${SystemColors.GrayText};
      }
    `),
    new DirectionalStyleSheetBehavior(
      css`
        .checked-indicator {
          left: 5px;
          right: calc(((${heightNumber} / 2) + 1) * 1px);
        }

        :host([aria-checked='true']) .checked-indicator {
          left: calc(((${heightNumber} / 2) + 1) * 1px);
          right: 5px;
        }
      `,
      css`
        .checked-indicator {
          right: 5px;
          left: calc(((${heightNumber} / 2) + 1) * 1px);
        }

        :host([aria-checked='true']) .checked-indicator {
          right: calc(((${heightNumber} / 2) + 1) * 1px);
          left: 5px;
        }
      `
    )
  );
