import React, { useCallback, useState, type ComponentProps } from 'react';
import { EmptyState, DataList, HStack, Tabs, Box, Flex, Stack, Text, Separator, IconButton, Container, Float, Icon, Link, Span, Show, Menu, Group, Portal, type MenuItemProps, type MenuSelectionDetails } from "@chakra-ui/react"
import { LuCode, LuText, LuCheck, LuX } from "react-icons/lu"
import type { JsonPlayObject, PlayObjectMinimal } from '../../core/Atomic.js';
import { shortTodayAwareFormat, timeToHumanTimestamp } from '../../core/TimeUtils.js';
import dayjs from 'dayjs';
import { ChakraCodeBlock } from './CodeBlock.js';
import { TextMuted } from './TextMuted.js';
import { formatNumber } from '../../core/DataUtils.js';
import { Muted } from './Typography.js';
import { ArtistCreditTags } from './ArtistCreditDisplay.js';
import { MSErrorBoundary } from './ErrorBoundary.js';
import { EllipsisButton, EyeClosedIcon, EyeIcon, getMusicServiceIconElement } from './icons/ChakraIcons.js';
import { MusicbrainzInfoIcon } from './musicServices/Musicbrainz.js';
import type { IconType } from 'react-icons/lib';
import { capitalize } from '../../core/StringUtils.js';
const EmptyPlayData = () => {
return (
No Play object was provided.
);
}
export type DisplayDates = false | 'all' | 'played' | 'seen';
export interface PlayInfoProps {
play?: JsonPlayObject | PlayObjectMinimal
final?: JsonPlayObject
showCodeToggle?: boolean
showCompare?: boolean
compareDefault?: 'Initial' | 'Final'
dates?: false | 'all' | 'played' | 'seen'
}
const primaryActionProps: ComponentProps = {
//margin: "1px",
variant: "outline",
size: 'xs'
}
const menuItem = (Icon: IconType, value: string, name?: string) => (props: Pick = {}) => ({name ?? capitalize(value)})
const MenuMbidShow = menuItem(EyeIcon, 'mbidShow', 'Show MBIDs');
const MenuMbidHide = menuItem(EyeClosedIcon, 'mbidHide', 'Hide MBIDs');
export const PlayData = (props?: PlayInfoProps) => {
const {
play,
final,
showCodeToggle = true,
showCompare = true,
compareDefault = 'Initial',
dates = 'all'
} = props ?? {};
const [codeMode, setCodeMode] = useState(false);
const [showMbid, setShowMBid] = useState(false);
const menuCb = useCallback((select: MenuSelectionDetails) => {
if (select.value === 'mbidShow') {
setShowMBid(true);
} else if (select.value === 'mbidHide') {
setShowMBid(false);
}
}, [setShowMBid])
if (play === undefined) {
return
}
let code: React.JSX.Element | null = null;
const comparable = showCompare && final !== undefined;
const menuItems: React.JSX.Element[] = [
showMbid ? :
];
if (showCodeToggle) {
code = (
setCodeMode(!codeMode)}>
{codeMode ? : }
);
}
let content: React.JSX.Element;
if (!comparable) {
content = codeMode ? : ;
} else {
content = (
Initial
Final
{codeMode ? : }
{codeMode ? : }
)
}
return (
{code}
{menuItems}
{content}
);
}
export const PlayDataDataList = (props: { play: JsonPlayObject, dates: DisplayDates, showMbid?: boolean }) => {
const {
play,
dates,
showMbid = false
} = props;
let albumArtistElm: React.JSX.Element;
if (play.data.albumArtists !== undefined && play.data.albumArtists.length > 0) {
albumArtistElm = (
Album Artists
);
}
const {
data: {
track,
artists = [],
listenedFor,
duration,
repeat,
meta: {
brainz = {}
} = {}
} = {},
meta: {
url: {
web: webUrl,
origin: originUrl
} = {},
source,
musicService
} = {}
} = play;
const titleLinks: React.JSX.Element[] = [];
if (webUrl !== undefined || originUrl !== undefined) {
titleLinks.push({getMusicServiceIconElement(musicService ?? source)});
}
if (brainz.track !== undefined) {
titleLinks.push()
}
if (brainz.recording !== undefined) {
titleLinks.push()
}
const titleElm = {track}{titleLinks}
return (
Title
{titleElm}
Artists
{artists.length === 0 ? (No Artists) :
}
{albumArtistElm}
Album
{play.data.album}
Duration
Track Length: {duration === undefined ? 'N/A' : timeToHumanTimestamp(dayjs.duration(duration, 's'))}
{listenedFor !== undefined ? Listened For: {timeToHumanTimestamp(dayjs.duration(listenedFor, 's'))} ({formatNumber((listenedFor / duration) * 100)}%) : null}
Repeat?
{repeat ? : }
)
}
export const PlayInfoContainer = (props?: PlayInfoProps) => {
return
}
export const PlayDatesStack = (props: { play: JsonPlayObject, dates: DisplayDates }) => {
const {
play,
dates
} = props;
let datesItem: React.JSX.Element | null;
if (dates === false) {
datesItem = null;
} else {
const dateElements = [];
if (dates.includes('played') || dates.includes('all')) {
dateElements.push(({`Played ${shortTodayAwareFormat(dayjs(play.data.playDate))}`}));
if (play.data.playDateCompleted !== undefined) {
dateElements.push(({`Played Until ${shortTodayAwareFormat(dayjs(play.data.playDateCompleted))}`}));
}
}
if (dates.includes('seen') || dates.includes('all')) {
dateElements.push(({`Seen ${shortTodayAwareFormat(dayjs(play.meta.seenAt))}`}));
}
datesItem = (
Dates
{dateElements}
)
}
return datesItem;
}
export const PlayDatesFooter = (props: { play: JsonPlayObject, dates: DisplayDates }) => {
const {
play,
dates
} = props;
let dateElm: React.JSX.Element;
if (dates !== false) {
let playDate: React.JSX.Element,
seenDate: React.JSX.Element;
if (play.data.playDate !== undefined && ['all', 'played'].includes(dates)) {
playDate = {`Played ${shortTodayAwareFormat(dayjs(play.data.playDate))}`}
}
// TODO implement seenAt for play data
if (play.meta.seenAt !== undefined && ['all', 'seen'].includes(dates)) {
seenDate = {`Seen ${shortTodayAwareFormat(dayjs(play.meta.seenAt))}`}
}
if (playDate !== undefined && seenDate !== undefined) {
dateElm = {playDate}{seenDate}
} else if (playDate !== undefined) {
dateElm = playDate;
} else if (seenDate !== undefined) {
dateElm = seenDate;
}
}
return dateElm;
}