export type MediaSessionHandlers = {
  play?: () => void;
  pause?: () => void;
  stop?: () => void;

  previoustrack?: () => void;
  nexttrack?: () => void;

  togglemicrophone?: () => void;
  togglecamera?: () => void;
  hangup?: () => void;

  seekbackward?: (details: MediaSessionActionDetails) => void;
  seekforward?: (details: MediaSessionActionDetails) => void;
  seekTo?: ((details: MediaSessionActionDetails) => void);
};

interface MediaMetadataParameters {
  title?: string;
  artist?: string;
  album?: string;
  artwork?: MediaImage[];
}

const DEFAULT_HANDLERS = {
  play: undefined,
  pause: undefined,
  seekbackward: undefined,
  seekforward: undefined,
  previoustrack: undefined,
  nexttrack: undefined,
  stop: undefined,
  seekTo: undefined,
};

export function registerMediaSession(metadata?: MediaMetadata, handlers?: MediaSessionHandlers) {
  const { mediaSession } = window.navigator;
  if (mediaSession) {
    if (metadata) updateMetadata(metadata);
    if (handlers) setMediaSessionHandlers(handlers);
  } else {
    // eslint-disable-next-line no-console
    console.warn('MediaSession API not supported in this browser');
  }
}

export function updateMetadata(metadata?: MediaMetadata) {
  const { mediaSession } = window.navigator;
  if (mediaSession) {
    // eslint-disable-next-line no-null/no-null
    mediaSession.metadata = metadata ?? null;
  }
}

export function setMediaSessionHandlers(handlers: MediaSessionHandlers) {
  const { mediaSession } = window.navigator;
  if (mediaSession) {
    Object.entries({ ...DEFAULT_HANDLERS, ...handlers }).forEach(([key, handler]) => {
      try {
        // @ts-ignore API not standardized yet
        mediaSession.setActionHandler(key, handler);
      } catch (err) {
        // Handler not supported, ignoring
      }
    });
  }
}

export function clearMediaSession() {
  const { mediaSession } = window.navigator;
  if (mediaSession) {
    // eslint-disable-next-line no-null/no-null
    mediaSession.metadata = null;
    setMediaSessionHandlers(DEFAULT_HANDLERS);
    if (mediaSession.playbackState) mediaSession.playbackState = 'none';
    mediaSession.setPositionState?.();
  }
}

export function setPlaybackState(state: 'none' | 'paused' | 'playing' = 'none') {
  const { mediaSession } = window.navigator;
  if (mediaSession && mediaSession.playbackState) {
    mediaSession.playbackState = state;
  }
}

export function setPositionState(state?: MediaPositionState) {
  if (!state || state.position === undefined || state.duration === undefined) return;
  state.position = Math.min(state.position, state.duration);

  const { mediaSession } = window.navigator;
  mediaSession?.setPositionState?.(state);
}

export function setMicrophoneActive(active: boolean) {
  const { mediaSession } = window.navigator;
  mediaSession?.setMicrophoneActive?.(active);
}

export function setCameraActive(active: boolean) {
  const { mediaSession } = window.navigator;
  mediaSession?.setCameraActive?.(active);
}

export function buildMediaMetadata({
  title, artist, album, artwork,
}: MediaMetadataParameters) {
  if ('MediaMetadata' in window) {
    return new window.MediaMetadata({
      title,
      artist,
      album,
      artwork,
    });
  }
  return undefined;
}
