import { Main, n_of, pick_random, render_and_copy } from "./common.tsx";

// ⾋ is grass which is neat
// meh, this seems to be the least worst option
// random ascii rocks and bunnies and such might be neat but would
// be total possible actually so i'm going to do that now
const grass_chars = ".,'`".split("");
// const grass_chars = ["^", '"', "'", ";", ":", "*", "+", "~"];
// authentic colors are kind of ugly
const grass_colors = ["#9DDA33", "#10F565"];

// const grass_colors = ["#136D15", "#117C13", "#138510", "#268B07", "#41980A"];

// i want to keep this minimal (i want to have a lot of grass :])
// b works nicely i think
// generally kinda doubting if the ascii look jives with the rest of the idea
// looks terrible when synchronized obviously lol
// i'm going to need to be smarter and consider the position but that's going
// to be a lot more difficult

// i should really have more randomness utilities
const blade_delay = (x: number, y: number): number => {
    const t = x + y;
    return t + (Math.random() - 0.5) * 1.5 - 120;
    // return Math.sin(t / 3) < 0 ? 3 * Math.sin(t) : Math.sin(t) / 4;
    // const den = 3;
    // return (
    //     (Math.sin(t / den) < 0 && Math.sin(t) < 0
    //         ? Math.sin(t) / den
    //         : Math.sin(t)) +
    //     (Math.random() - 0.5) * 1.5
    // );
};

// truncing floats a bit could save a lot of bytes but eh
// should be a util obviously
// toFixed is sufficient for css stuff methinks
// you know it's a good css crime when using toFixed saves multiple kilobytes
const Blade = ({ x, y }: { x: number; y: number }) => (
    <b
        style={{
            // transformOrigin: "bottom",
            // transform: "translateX(0.5rem)",
            // putting everything here *drastically* reduces size
            animation: `6.5s spin ${blade_delay(x, y).toFixed(
                2
            )}s infinite ease-in-out alternate`,
            transform: "translateX(0.5rem)",
            color: pick_random(grass_colors),
            // helps the squareness
            overflow: "hidden",
        }}
    >
        {pick_random(grass_chars)}
    </b>
);

// ☺ is too inconsistently rendered i think
// i can't NOT have it come on
const statics = "r•gbpM☺".split("");
const static_colors: Record<string, string[]> = {
    r: ["rgb(215, 155, 45)"],
    // turns out df has a lot of rocks
    // there are repeated colors but that should be good for recreating the general distribution
    "•": [
        "rgb(255, 255, 255)",
        "rgb(215, 155, 45)",
        "rgb(160, 160, 160)",
        "rgb(215, 155, 45)",
        "rgb(255, 255, 255)",
        "rgb(255, 255, 255)",
        "rgb(215, 155, 45)",
        "rgb(255, 255, 255)",
        "rgb(215, 155, 45)",
        "rgb(160, 160, 160)",
        "rgb(215, 155, 45)",
        "rgb(160, 160, 160)",
        "rgb(160, 160, 160)",
        "rgb(192, 192, 192)",
        "rgb(160, 160, 160)",
        "rgb(160, 160, 160)",
        "rgb(192, 192, 192)",
        "rgb(160, 160, 160)",
        "rgb(160, 160, 160)",
        "rgb(192, 192, 192)",
        "rgb(255, 255, 255)",
        "rgb(192, 192, 192)",
        "rgb(255, 255, 255)",
        "rgb(215, 155, 45)",
        "rgb(160, 160, 160)",
    ],
    g: ["white"],
    b: [
        "rgb(160, 160, 160)",
        "rgb(192, 192, 192)",
        "rgb(192, 192, 192)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(255, 17, 58)",
        "rgb(140, 102, 255)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(160, 160, 160)",
        "rgb(215, 155, 45)",
        "rgb(160, 160, 160)",
        "rgb(160, 160, 160)",
        "rgb(160, 160, 160)",
        "rgb(255, 255, 255)",
        "rgb(255, 255, 255)",
        "rgb(255, 113, 17)",
        "rgb(167, 60, 213)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(160, 160, 160)",
        "rgb(160, 160, 160)",
        "rgb(162, 220, 52)",
    ],
    p: [
        "rgb(140, 102, 255)",
        "rgb(232, 17, 255)",
        "rgb(140, 102, 255)",
        "rgb(192, 192, 192)",
        "rgb(192, 192, 192)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(19, 253, 101)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(232, 17, 255)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(255, 17, 58)",
        "rgb(255, 17, 58)",
        "rgb(140, 102, 255)",
        "rgb(255, 255, 255)",
        "rgb(140, 102, 255)",
        "rgb(160, 160, 160)",
        "rgb(255, 255, 255)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(160, 160, 160)",
        "rgb(160, 160, 160)",
    ],
    M: [
        "rgb(192, 192, 192)",
        "rgb(215, 155, 45)",
        "rgb(18, 254, 207)",
        "rgb(192, 192, 192)",
        "rgb(160, 160, 160)",
        "rgb(140, 102, 255)",
        "rgb(19, 253, 101)",
        "rgb(192, 192, 192)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(160, 160, 160)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(192, 192, 192)",
        "rgb(160, 160, 160)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(232, 17, 255)",
        "rgb(255, 17, 58)",
        "rgb(255, 113, 17)",
        "rgb(160, 160, 160)",
        "rgb(160, 160, 160)",
        "rgb(255, 113, 17)",
        "rgb(255, 113, 17)",
        "rgb(215, 155, 45)",
        "rgb(215, 155, 45)",
        "rgb(160, 160, 160)",
        "rgb(18, 254, 207)",
        "rgb(160, 160, 160)",
    ],
    "☺": ["grey", "rgb(113, 187, 176)"],
};
const StaticGuy = () => {
    const stat = pick_random(statics);
    return (
        <b
            style={{
                overflow: "hidden",
                color: pick_random(static_colors[stat]),
            }}
        >
            {stat}
        </b>
    );
};

const Field = ({ width }: { width: number }) => (
    <div
        style={{
            width: "100%",
            aspectRatio: "1",
            display: "grid",
            gridTemplateRows: `repeat(${width}, 1fr)`,
            gridTemplateColumns: `repeat(${width}, 1fr)`,
            // what dfwiki uses
            fontFamily:
                '"Courier New", "Quicktype Mono", "Bitstream Vera Sans Mono", "Lucida Console", "Lucida Sans Typewriter", monospace',
            // brown doesn't really work because the grass isn't dense enough
            // maybe a complete dfivorce isn't in order
            backgroundColor: "black",
            fontWeight: "bolder",
            fontSize: "1.1rem",
            // shweet
            lineHeight: "100%",
        }}
    >
        {new Array(width * width)
            .fill(undefined)
            .map((_, i) =>
                Math.random() < 0.05 ? (
                    <StaticGuy />
                ) : (
                    <Blade x={i % width} y={Math.floor(i / width)} />
                )
            )}
    </div>
);

// it's funny how the whole idea was to emulate waves of grass but then i just
// didn't do that because it's hawd :[
// okay, seeing how pretty the waves in the wrapped text of the source are has
// inspired me. i'm going to work on this tomorrow and do the hawd thing (waves)

// adding more grass doesn't really help and mainly just causes size problems
// takes some shuffling to get a nice distribution of statics
render_and_copy(<Field width={30} />);
