import React from "react";
import { ClassNames } from "@emotion/react";
import {
	Badge,
	Box,
	SimpleGrid,
	Tooltip,
	Wrap,
	WrapItem,
	useColorModeValue,
	useTheme,
} from "@chakra-ui/react";
import {
	CheckIcon,
	EditIcon,
	NotAllowedIcon,
	StarIcon,
} from "@chakra-ui/icons";
import { HiSparkles } from "react-icons/hi";

import SquareItemCard from "./SquareItemCard";
import { safeImageUrl, useCommonStyles } from "../util";
import usePreferArchive from "./usePreferArchive";

function ItemCard({ item, badges, variant = "list", ...props }) {
	const { brightBackground } = useCommonStyles();

	switch (variant) {
		case "grid":
			return <SquareItemCard item={item} {...props} />;
		case "list":
			return (
				<Box
					as="a"
					href={`/items/${item.id}`}
					display="block"
					p="2"
					boxShadow="lg"
					borderRadius="lg"
					background={brightBackground}
					transition="all 0.2s"
					className="item-card"
					width="100%"
					minWidth="0"
					{...props}
				>
					<ItemCardContent
						item={item}
						badges={badges}
						focusSelector=".item-card:hover &, .item-card:focus &"
					/>
				</Box>
			);
		default:
			throw new Error(`Unexpected ItemCard variant: ${variant}`);
	}
}

export function ItemCardContent({
	item,
	badges,
	isWorn,
	isDisabled,
	itemNameId,
	focusSelector,
}) {
	return (
		<Box display="flex">
			<Box>
				<Box flex="0 0 auto" marginRight="3">
					<ItemThumbnail
						item={item}
						isActive={isWorn}
						isDisabled={isDisabled}
						focusSelector={focusSelector}
					/>
				</Box>
			</Box>
			<Box flex="1 1 0" minWidth="0" marginTop="1px">
				<ItemName
					id={itemNameId}
					isWorn={isWorn}
					isDisabled={isDisabled}
					focusSelector={focusSelector}
				>
					{item.name}
				</ItemName>

				{badges}
			</Box>
		</Box>
	);
}

/**
 * ItemThumbnail shows a small preview image for the item, including some
 * hover/focus and worn/unworn states.
 */
export function ItemThumbnail({
	item,
	size = "md",
	isActive,
	isDisabled,
	focusSelector,
	...props
}) {
	const [preferArchive] = usePreferArchive();
	const theme = useTheme();

	const borderColor = useColorModeValue(
		theme.colors.green["700"],
		"transparent",
	);

	const focusBorderColor = useColorModeValue(
		theme.colors.green["600"],
		"transparent",
	);

	return (
		<ClassNames>
			{({ css }) => (
				<Box
					width={size === "lg" ? "80px" : "50px"}
					height={size === "lg" ? "80px" : "50px"}
					transition="all 0.15s"
					transformOrigin="center"
					position="relative"
					className={css([
						{
							transform: "scale(0.8)",
						},
						!isDisabled &&
							!isActive && {
								[focusSelector]: {
									opacity: "0.9",
									transform: "scale(0.9)",
								},
							},
						!isDisabled &&
							isActive && {
								opacity: 1,
								transform: "none",
							},
					])}
					{...props}
				>
					<Box
						borderRadius="lg"
						boxShadow="md"
						border="1px"
						overflow="hidden"
						width="100%"
						height="100%"
						className={css([
							{
								borderColor: `${borderColor} !important`,
							},
							!isDisabled &&
								!isActive && {
									[focusSelector]: {
										borderColor: `${focusBorderColor} !important`,
									},
								},
						])}
					>
						{/* If the item is still loading, wait with an empty box. */}
						{item && (
							<Box
								as="img"
								width="100%"
								height="100%"
								src={safeImageUrl(item.thumbnailUrl, { preferArchive })}
								alt={`Thumbnail art for ${item.name}`}
							/>
						)}
					</Box>
				</Box>
			)}
		</ClassNames>
	);
}

/**
 * ItemName shows the item's name, including some hover/focus and worn/unworn
 * states.
 */
function ItemName({ children, isDisabled, focusSelector, ...props }) {
	const theme = useTheme();

	return (
		<ClassNames>
			{({ css }) => (
				<Box
					fontSize="md"
					transition="all 0.15s"
					overflow="hidden"
					whiteSpace="nowrap"
					textOverflow="ellipsis"
					className={
						!isDisabled &&
						css`
							${focusSelector} {
								opacity: 0.9;
								font-weight: ${theme.fontWeights.medium};
							}

							input:checked + .item-container & {
								opacity: 1;
								font-weight: ${theme.fontWeights.bold};
							}
						`
					}
					{...props}
				>
					{children}
				</Box>
			)}
		</ClassNames>
	);
}

export function ItemCardList({ children }) {
	return (
		<SimpleGrid columns={{ sm: 1, md: 2, lg: 3 }} spacing="6">
			{children}
		</SimpleGrid>
	);
}

export function ItemBadgeList({ children, ...props }) {
	return (
		<Wrap spacing="2" opacity="0.7" {...props}>
			{React.Children.map(
				children,
				(badge) => badge && <WrapItem>{badge}</WrapItem>,
			)}
		</Wrap>
	);
}

export function ItemBadgeTooltip({ label, children }) {
	return (
		<Tooltip
			label={<Box textAlign="center">{label}</Box>}
			placement="top"
			openDelay={400}
		>
			{children}
		</Tooltip>
	);
}

export const NcBadge = React.forwardRef(({ isEditButton, ...props }, ref) => {
	return (
		<ItemBadgeTooltip label="Neocash">
			<Badge
				ref={ref}
				as={isEditButton ? "button" : "span"}
				colorScheme="purple"
				display="flex"
				alignItems="center"
				_focus={{ outline: "none", boxShadow: "outline" }}
				{...props}
			>
				NC
				{isEditButton && <EditIcon fontSize="0.85em" marginLeft="1" />}
			</Badge>
		</ItemBadgeTooltip>
	);
});

export const NpBadge = React.forwardRef(({ isEditButton, ...props }, ref) => {
	return (
		<ItemBadgeTooltip label="Neopoints">
			<Badge
				ref={ref}
				as={isEditButton ? "button" : "span"}
				display="flex"
				alignItems="center"
				_focus={{ outline: "none", boxShadow: "outline" }}
				{...props}
			>
				NP
				{isEditButton && <EditIcon fontSize="0.85em" marginLeft="1" />}
			</Badge>
		</ItemBadgeTooltip>
	);
});

export const PbBadge = React.forwardRef(({ isEditButton, ...props }, ref) => {
	return (
		<ItemBadgeTooltip label="This item is only obtainable via paintbrush">
			<Badge
				ref={ref}
				as={isEditButton ? "button" : "span"}
				colorScheme="orange"
				display="flex"
				alignItems="center"
				_focus={{ outline: "none", boxShadow: "outline" }}
				{...props}
			>
				PB
				{isEditButton && <EditIcon fontSize="0.85em" marginLeft="1" />}
			</Badge>
		</ItemBadgeTooltip>
	);
});

export const ItemKindBadge = React.forwardRef(
	({ isNc, isPb, isEditButton, ...props }, ref) => {
		if (isNc) {
			return <NcBadge ref={ref} isEditButton={isEditButton} {...props} />;
		} else if (isPb) {
			return <PbBadge ref={ref} isEditButton={isEditButton} {...props} />;
		} else {
			return <NpBadge ref={ref} isEditButton={isEditButton} {...props} />;
		}
	},
);

export function YouOwnThisBadge({ variant = "long" }) {
	let badge = (
		<Badge
			colorScheme="green"
			display="flex"
			alignItems="center"
			minHeight="1.5em"
		>
			<CheckIcon aria-label="Check" />
			{variant === "medium" && <Box marginLeft="1">Own</Box>}
			{variant === "long" && <Box marginLeft="1">You own this!</Box>}
		</Badge>
	);

	if (variant === "short" || variant === "medium") {
		badge = (
			<ItemBadgeTooltip label="You own this item">{badge}</ItemBadgeTooltip>
		);
	}

	return badge;
}

export function YouWantThisBadge({ variant = "long" }) {
	let badge = (
		<Badge
			colorScheme="blue"
			display="flex"
			alignItems="center"
			minHeight="1.5em"
		>
			<StarIcon aria-label="Star" />
			{variant === "medium" && <Box marginLeft="1">Want</Box>}
			{variant === "long" && <Box marginLeft="1">You want this!</Box>}
		</Badge>
	);

	if (variant === "short" || variant === "medium") {
		badge = (
			<ItemBadgeTooltip label="You want this item">{badge}</ItemBadgeTooltip>
		);
	}

	return badge;
}

function ZoneBadge({ variant, zoneLabel }) {
	// Shorten the label when necessary, to make the badges less bulky
	const shorthand = zoneLabel
		.replace("Background Item", "BG Item")
		.replace("Foreground Item", "FG Item")
		.replace("Lower-body", "Lower")
		.replace("Upper-body", "Upper")
		.replace("Transient", "Trans")
		.replace("Biology", "Bio");

	if (variant === "restricts") {
		return (
			<ItemBadgeTooltip
				label={`Restricted: This item can't be worn with ${zoneLabel} items`}
			>
				<Badge>
					<Box display="flex" alignItems="center">
						{shorthand} <NotAllowedIcon marginLeft="1" />
					</Box>
				</Badge>
			</ItemBadgeTooltip>
		);
	}

	if (shorthand !== zoneLabel) {
		return (
			<ItemBadgeTooltip label={zoneLabel}>
				<Badge>{shorthand}</Badge>
			</ItemBadgeTooltip>
		);
	}

	return <Badge>{shorthand}</Badge>;
}

export function getZoneBadges(zones, propsForAllBadges) {
	// Get the sorted zone labels. Sometimes an item occupies multiple zones of
	// the same name, so it's important to de-duplicate them!
	let labels = zones.map((z) => z.label);
	labels = new Set(labels);
	labels = [...labels].sort();

	return labels.map((label) => (
		<ZoneBadge key={label} zoneLabel={label} {...propsForAllBadges} />
	));
}

export function MaybeAnimatedBadge() {
	return (
		<ItemBadgeTooltip label="Maybe animated? (Support only)">
			<Badge
				colorScheme="orange"
				display="flex"
				alignItems="center"
				minHeight="1.5em"
			>
				<Box as={HiSparkles} aria-label="Sparkles" />
			</Badge>
		</ItemBadgeTooltip>
	);
}

export default ItemCard;