import { css } from '@emotion/react';
import { avatarColors, relativeFontSizeToBase16 } from '@atlaskit/editor-shared-styles';
import { getGlobalTheme } from '@atlaskit/tokens';

// Format of the payload returned by the callback function passed to the collab provider
// that gets called when syncing with the back-end service fails.

// Format of the document and its metadata returned from the collab provider
// after editing and for draft sync

// Provider Errors
// Emitted errors
export let PROVIDER_ERROR_CODE = /*#__PURE__*/function (PROVIDER_ERROR_CODE) {
  PROVIDER_ERROR_CODE["NO_PERMISSION_ERROR"] = "NO_PERMISSION_ERROR";
  PROVIDER_ERROR_CODE["INVALID_USER_TOKEN"] = "INVALID_USER_TOKEN";
  PROVIDER_ERROR_CODE["DOCUMENT_NOT_FOUND"] = "DOCUMENT_NOT_FOUND";
  PROVIDER_ERROR_CODE["LOCKED"] = "LOCKED";
  PROVIDER_ERROR_CODE["FAIL_TO_SAVE"] = "FAIL_TO_SAVE";
  PROVIDER_ERROR_CODE["DOCUMENT_RESTORE_ERROR"] = "DOCUMENT_RESTORE_ERROR";
  PROVIDER_ERROR_CODE["INITIALISATION_ERROR"] = "INITIALISATION_ERROR";
  PROVIDER_ERROR_CODE["NETWORK_ISSUE"] = "NETWORK_ISSUE";
  PROVIDER_ERROR_CODE["INVALID_PROVIDER_CONFIGURATION"] = "INVALID_PROVIDER_CONFIGURATION";
  PROVIDER_ERROR_CODE["INTERNAL_SERVICE_ERROR"] = "INTERNAL_SERVICE_ERROR";
  PROVIDER_ERROR_CODE["DOCUMENT_UPDATE_ERROR"] = "DOCUMENT_UPDATE_ERROR";
  return PROVIDER_ERROR_CODE;
}({});
/**
 * This occurs when the provided user token is considered invalid for the given document ARI.
 * It happens during initialisation of the provider.
 * It could mean the document has been deleted (hence not found).
 * @message Message returned to editor, i.e User does not have permissions to access this document or document is not found
 * @recoverable It is recoverable, as we will try to refresh the token.
 */

/**
 * Similar to InsufficientEditingPermission, but the user token is invalid because it has expired or been revoked.
 * It may also be an invalid token format.
 * This error is given to the provider by NCS.
 * @message Message returned to editor, i.e. The user token was invalid
 * @recoverable It is recoverable, as we will try to refresh the token.
 */

/**
 * Document not found error, thrown when the provider is unable to find a document with the given ARI and user token.
 * It occurs during fetchCatchup, a function that fetches the latest document state during catchup.
 * We need to recieve a 404 from the document service to throw this error.
 * @message Message returned to editor, i.e. The requested document is not found
 * @recoverable It is recoverable, as the provider can try again later.
 */

/**
 * This error is thrown when the document is locked by another user.
 * The error is passed to us by NCS.
 * @message Message returned to editor, i.e. The document is currently not available, please try again later
 * @recoverable It is recoverable, as the provider can try again later.
 */

/**
 * This error is thrown when the provider is unable to save the document.
 * This can happen when the connection to dynamoDB is lost, or when we do not have sufficient permissions (DYNAMO ERROR).
 * This error is given to us by NCS.
 * @message Message returned to editor, i.e. Collab service is not able to save changes
 * @recoverable It is not recoverable, as we don't want the user to continue editing a document that is not being saved.
 */

/**
 * This error is thrown when the provider is unable to restore the document.
 * It occurs during onRestore, a function that restores the document to a previous version and reapplies unconfirmed steps.
 * onRestore is called when page recovery has emitted an 'init' event on a page client is currently connected to.
 * It could mean we failed to update the page metadata, or we failed to reapply unconfirmed steps.
 * @message Message returned to editor, i.e. Collab service unable to restore document
 * @recoverable It is not recoverable, as the provider has no further options after this.
 * The user will need to refresh the page to try again.
 */

/**
 * The initial document couldn't be loaded from the collab service.
 * This error is given to us by NCS.
 * It could indicate either a network issue, or an internal service error in NCS.
 * @message Message returned to editor, i.e. The initial document couldn't be loaded from the collab service
 * @recoverable It is not recoverable, as the provider cannot do anything to fix it.
 * The user will need to refresh the page to try again.
 */

/**
 * Couldn't reconnect to the collab service (NCS) due to network issues.
 * NCS could be down, or the user could be offline. It's also possible the url is incorrect, or the user is behind a proxy blocking the connection.
 * Fired upon a reconnection attempt error (from Socket.IO Manager)
 * @message Message returned to editor, i.e. Couldn't reconnect to the collab service due to network issues
 * @recoverable It is recoverable, as the provider will try to reconnect.
 */

/**
 * This error is thrown when the provider has an invalid configuration.
 * It could happen due to these errors from NCS:
 *  NAMESPACE_INVALID
    INVALID_ACTIVATION_ID
    INVALID_DOCUMENT_ARI
    INVALID_CLOUD_ID
 * @message Message returned to editor, i.e. Invalid provider configuration
 * @recoverable It is not recoverable, as the provider cannot do anything to fix it.
 * The service using the provider will need to fix the configuration.
 */

/**
 * This error is thrown when the provider encounters an internal service error, not otherwise accounted for.
 * @message Message returned to editor, i.e. Collab Provider experienced an unrecoverable error
 * @recoverable It is not recoverable, as the provider cannot do anything to fix it.
 */

/**
 * A union of all possible provider errors that can be emitted back to the editor.
 */

// Collab Provider interface

// TODO: Deprecate redundant payload types

export let DisconnectReason = /*#__PURE__*/function (DisconnectReason) {
  DisconnectReason["CLIENT_DISCONNECT"] = "CLIENT_DISCONNECT";
  DisconnectReason["SERVER_DISCONNECT"] = "SERVER_DISCONNECT";
  DisconnectReason["SOCKET_CLOSED"] = "SOCKET_CLOSED";
  DisconnectReason["SOCKET_ERROR"] = "SOCKET_ERROR";
  DisconnectReason["SOCKET_TIMEOUT"] = "SOCKET_TIMEOUT";
  DisconnectReason["UNKNOWN_DISCONNECT"] = "UNKNOWN_DISCONNECT";
  return DisconnectReason;
}({});
const telepointerColorStyle = (color, index) => {
  const {
    colorMode
  } = getGlobalTheme();
  const backgroundStyle = colorMode === 'dark' ? `linear-gradient(to bottom, ${color} -800000%, transparent 200000%)` : `linear-gradient(to bottom, ${color} -850000%, transparent 150000%)`;
  return `
    &.color-${index} {
      background: ${backgroundStyle};
      &::after {
        background-color: ${color};
        color: ${"var(--ds-text-inverse, #FFFFFF)"};
        border-color: ${color};
      }
    }
  `;
};
export const TELEPOINTER_DIM_CLASS = 'telepointer-dim';

// ED-22557: Safely convert to object styling
// Disable top: -14px since it is necessary to align to cursor
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage/preview, @atlaskit/design-system/no-css-tagged-template-expression, @atlaskit/design-system/no-exported-css
export const telepointerStyle = css`
  .ProseMirror .telepointer {
    position: relative;
    transition: opacity 200ms;

    &.telepointer-selection {
      line-height: 1.2;
      pointer-events: none;
      user-select: none;
    }

    &.telepointer-selection-badge::after {
      content: attr(data-initial);
      position: absolute;
      display: block;
      top: -14px;
      font-size: ${relativeFontSizeToBase16(9)};
      padding: ${"var(--ds-space-025, 2px)"};
      color: ${"var(--ds-text-inverse, #FFFFFF)"};
      left: 0px;
      border-radius: 2px 2px 2px 0;
      line-height: initial;
    }

    &.${TELEPOINTER_DIM_CLASS} {
      opacity: 0.2;
    }

    ${avatarColors.map((color, index) => telepointerColorStyle(color, index))};
  }
`;
const tintKey = 'collab:isDirtyTransaction';
export const isDirtyTransaction = tr => {
  return Boolean(tr.getMeta(tintKey));
};
/*
 * This function is used to mark which commands that are dispatching
 * unnecessary changes on Editor.
 */
export const tintDirtyTransaction = tr => {
  tr.setMeta(tintKey, true);
};