import { CSSProperties, MouseEvent } from 'react';

import { Game } from '../lib/types';
import {
    downloadProgressPercent,
    formatDownloadBytes,
    formatDownloadEta,
    formatDownloadSpeed,
    formatDownloadSpeedShort,
} from '../lib/gameState';

import { Icon } from './Icon';

interface Props {
    game: Game;
    size?: 'md' | 'lg';
    full?: boolean;
    onCancel?: (game: Game) => void;
}

const progressStats = (game: Game) => {
    const progress = game.download_progress;
    const downloaded = progress?.downloaded_bytes ?? 0;
    const total = progress?.total_bytes ?? game.size;
    const speed = progress?.bytes_per_second ?? 0;
    const remaining = Math.max(0, total - downloaded);
    const etaSeconds = speed > 0 ? remaining / speed : Number.POSITIVE_INFINITY;

    return {
        pct: Math.min(99, Math.round(downloadProgressPercent(game))),
        downloaded,
        total,
        speed,
        eta: etaSeconds,
        activePeerCount: progress?.active_peer_count ?? 0,
    };
};

export const DownloadProgress = ({ game, size = 'md', full = false, onCancel }: Props) => {
    const stats = progressStats(game);
    const progressStyle = {
        '--download-progress': `${stats.pct}%`,
    } as CSSProperties;
    const className = [
        'dl',
        size === 'lg' ? 'dl-lg' : 'dl-md',
        full ? 'dl-full' : '',
    ].filter(Boolean).join(' ');

    const handleCancel = (event: MouseEvent<HTMLButtonElement>) => {
        event.stopPropagation();
        onCancel?.(game);
    };

    if (size === 'lg') {
        const peerUnit = stats.activePeerCount === 1 ? 'peer' : 'peers';

        return (
            <div
                className={className}
                role="progressbar"
                aria-label={`Downloading ${game.name}`}
                aria-valuemin={0}
                aria-valuemax={100}
                aria-valuenow={stats.pct}
                style={progressStyle}
            >
                <div className="dl-fill" aria-hidden />
                <div className="dl-lg-grid">
                    <div className="dl-lg-primary">
                        <span className="dl-pulse" aria-hidden />
                        <span className="dl-label">Downloading</span>
                    </div>
                    <div className="dl-lg-secondary">
                        <span className="dl-bytes">
                            <strong>{formatDownloadBytes(stats.downloaded)}</strong>
                            <span className="dl-of"> / {formatDownloadBytes(stats.total)}</span>
                        </span>
                        <span className="dl-sep">·</span>
                        <span className="dl-speed">{formatDownloadSpeed(stats.speed)}</span>
                        {stats.activePeerCount > 0 && (
                            <>
                                <span className="dl-sep dl-sep-peers">·</span>
                                <span
                                    className="dl-peers"
                                    title={`Downloading from ${stats.activePeerCount} ${peerUnit} on the LAN`}
                                >
                                    <Icon.users />
                                    <span>{stats.activePeerCount}</span>
                                </span>
                            </>
                        )}
                        <span className="dl-sep dl-sep-eta">·</span>
                        <span className="dl-eta">{formatDownloadEta(stats.eta)} left</span>
                    </div>
                    <div className="dl-lg-pct">
                        {stats.pct}
                        <span className="dl-pct-sym">%</span>
                    </div>
                    {onCancel && (
                        <button
                            type="button"
                            className="dl-cancel"
                            onClick={handleCancel}
                            aria-label={`Cancel download of ${game.name}`}
                        >
                            <Icon.close />
                        </button>
                    )}
                </div>
            </div>
        );
    }

    return (
        <div
            className={className}
            role="progressbar"
            aria-label={`Downloading ${game.name}`}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-valuenow={stats.pct}
            title={`${stats.pct}% · ${formatDownloadSpeed(stats.speed)} · ${formatDownloadEta(stats.eta)} left`}
            style={progressStyle}
        >
            <div className="dl-fill" aria-hidden />
            <div className="dl-md-row">
                <span className="dl-pct">
                    <span className="dl-pulse" aria-hidden />
                    {stats.pct}
                    <span className="dl-pct-sym">%</span>
                </span>
                <span className="dl-speed">{formatDownloadSpeedShort(stats.speed)}</span>
            </div>
        </div>
    );
};
