// @ts-ignore
import pSBC from "shade-blend-color";

import styles from "./Panes.module.scss";
import { Text } from "preact-i18n";
import { useCallback, useContext, useEffect, useState } from "preact/hooks";

import TextAreaAutoSize from "../../../lib/TextAreaAutoSize";
import { debounce } from "../../../lib/debounce";

import { dispatch } from "../../../redux";
import { connectState } from "../../../redux/connector";
import { EmojiPacks, Settings } from "../../../redux/reducers/settings";

import {
    DEFAULT_FONT,
    DEFAULT_MONO_FONT,
    FONTS,
    FONT_KEYS,
    MONOSCAPE_FONTS,
    MONOSCAPE_FONT_KEYS,
    Theme,
    ThemeContext,
    ThemeOptions,
} from "../../../context/Theme";
import { useIntermediate } from "../../../context/intermediate/Intermediate";

import CollapsibleSection from "../../../components/common/CollapsibleSection";
import Button from "../../../components/ui/Button";
import Checkbox from "../../../components/ui/Checkbox";
import ColourSwatches from "../../../components/ui/ColourSwatches";
import ComboBox from "../../../components/ui/ComboBox";
import InputBox from "../../../components/ui/InputBox";
import darkSVG from "../assets/dark.svg";
import lightSVG from "../assets/light.svg";
import mutantSVG from "../assets/mutant_emoji.svg";
import notoSVG from "../assets/noto_emoji.svg";
import openmojiSVG from "../assets/openmoji_emoji.svg";
import twemojiSVG from "../assets/twemoji_emoji.svg";

interface Props {
    settings: Settings;
}

// ! FIXME: code needs to be rewritten to fix jittering
export function Component(props: Props) {
    const theme = useContext(ThemeContext);
    const { writeClipboard, openScreen } = useIntermediate();

    function setTheme(theme: ThemeOptions) {
        dispatch({
            type: "SETTINGS_SET_THEME",
            theme,
        });
    }

    function pushOverride(custom: Partial<Theme>) {
        dispatch({
            type: "SETTINGS_SET_THEME_OVERRIDE",
            custom,
        });
    }

    function setAccent(accent: string) {
        setOverride({
            accent,
            "scrollbar-thumb": pSBC(-0.2, accent),
        });
    }

    const emojiPack = props.settings.appearance?.emojiPack ?? "mutant";
    function setEmojiPack(emojiPack: EmojiPacks) {
        dispatch({
            type: "SETTINGS_SET_APPEARANCE",
            options: {
                emojiPack,
            },
        });
    }

    const setOverride = useCallback(debounce(pushOverride, 200), []) as (
        custom: Partial<Theme>,
    ) => void;
    const [css, setCSS] = useState(props.settings.theme?.custom?.css ?? "");

    useEffect(() => setOverride({ css }), [css]);

    const selected = props.settings.theme?.preset ?? "dark";
    return (
        <div className={styles.appearance}>
            <h3>
                <Text id="app.settings.pages.appearance.theme" />
            </h3>
            <div className={styles.themes}>
                <div className={styles.theme}>
                    <img
                        src={lightSVG}
                        data-active={selected === "light"}
                        onClick={() =>
                            selected !== "light" &&
                            setTheme({ preset: "light" })
                        }
                    />
                    <h4>
                        <Text id="app.settings.pages.appearance.color.light" />
                    </h4>
                </div>
                <div className={styles.theme}>
                    <img
                        src={darkSVG}
                        data-active={selected === "dark"}
                        onClick={() =>
                            selected !== "dark" && setTheme({ preset: "dark" })
                        }
                    />
                    <h4>
                        <Text id="app.settings.pages.appearance.color.dark" />
                    </h4>
                </div>
            </div>

            <h3>
                <Text id="app.settings.pages.appearance.accent_selector" />
            </h3>
            <ColourSwatches value={theme.accent} onChange={setAccent} />

            {/*<h3>
                <Text id="app.settings.pages.appearance.message_display" />
            </h3>
            <div className={styles.display}>
                <Radio
                    description={
                        <Text id="app.settings.pages.appearance.display.default_description" />
                    }
                    checked
                >
                    <Text id="app.settings.pages.appearance.display.default" />
                </Radio>
                <Radio
                    description={
                        <Text id="app.settings.pages.appearance.display.compact_description" />
                    }
                    disabled
                >
                    <Text id="app.settings.pages.appearance.display.compact" />
                </Radio>
            </div>*/}

            <h3>
                <Text id="app.settings.pages.appearance.font" />
            </h3>
            <ComboBox
                value={theme.font ?? DEFAULT_FONT}
                onChange={(e) =>
                    setTheme({ custom: { font: e.currentTarget.value as any } })
                }>
                {FONT_KEYS.map((key) => (
                    <option value={key}>
                        {FONTS[key as keyof typeof FONTS].name}
                    </option>
                ))}
            </ComboBox>
            <p>
                <Checkbox
                    checked={props.settings.theme?.ligatures === true}
                    onChange={() =>
                        setTheme({
                            ligatures: !props.settings.theme?.ligatures,
                        })
                    }
                    description={
                        <Text id="app.settings.pages.appearance.ligatures_desc" />
                    }>
                    <Text id="app.settings.pages.appearance.ligatures" />
                </Checkbox>
            </p>

            <h3>
                <Text id="app.settings.pages.appearance.emoji_pack" />
            </h3>
            <div className={styles.emojiPack}>
                <div className={styles.row}>
                    <div>
                        <div
                            className={styles.button}
                            onClick={() => setEmojiPack("mutant")}
                            data-active={emojiPack === "mutant"}>
                            <img src={mutantSVG} draggable={false} />
                        </div>
                        <h4>
                            Mutant Remix{" "}
                            <a
                                href="https://mutant.revolt.chat"
                                target="_blank">
                                (by Revolt)
                            </a>
                        </h4>
                    </div>
                    <div>
                        <div
                            className={styles.button}
                            onClick={() => setEmojiPack("twemoji")}
                            data-active={emojiPack === "twemoji"}>
                            <img src={twemojiSVG} draggable={false} />
                        </div>
                        <h4>Twemoji</h4>
                    </div>
                </div>
                <div className={styles.row}>
                    <div>
                        <div
                            className={styles.button}
                            onClick={() => setEmojiPack("openmoji")}
                            data-active={emojiPack === "openmoji"}>
                            <img src={openmojiSVG} draggable={false} />
                        </div>
                        <h4>Openmoji</h4>
                    </div>
                    <div>
                        <div
                            className={styles.button}
                            onClick={() => setEmojiPack("noto")}
                            data-active={emojiPack === "noto"}>
                            <img src={notoSVG} draggable={false} />
                        </div>
                        <h4>Noto Emoji</h4>
                    </div>
                </div>
            </div>

            <CollapsibleSection
                id="settings_advanced_appearance"
                defaultValue={false}
                summary={<Text id="app.settings.pages.appearance.advanced" />}>
                <h3>
                    <Text id="app.settings.pages.appearance.overrides" />
                </h3>
                <div className={styles.actions}>
                    <Button contrast onClick={() => setTheme({ custom: {} })}>
                        <Text id="app.settings.pages.appearance.reset_overrides" />
                    </Button>
                    <Button
                        contrast
                        onClick={() => writeClipboard(JSON.stringify(theme))}>
                        <Text id="app.settings.pages.appearance.export_clipboard" />
                    </Button>
                    <Button
                        contrast
                        onClick={async () => {
                            const text = await navigator.clipboard.readText();
                            setOverride(JSON.parse(text));
                        }}>
                        <Text id="app.settings.pages.appearance.import_clipboard" />
                    </Button>
                    <Button
                        contrast
                        onClick={async () => {
                            openScreen({
                                id: "_input",
                                question: (
                                    <Text id="app.settings.pages.appearance.import_theme" />
                                ),
                                field: (
                                    <Text id="app.settings.pages.appearance.theme_data" />
                                ),
                                callback: async (string) =>
                                    setOverride(JSON.parse(string)),
                            });
                        }}>
                        <Text id="app.settings.pages.appearance.import_manual" />
                    </Button>
                </div>
                <div className={styles.overrides}>
                    {(
                        [
                            "accent",
                            "background",
                            "foreground",
                            "primary-background",
                            "primary-header",
                            "secondary-background",
                            "secondary-foreground",
                            "secondary-header",
                            "tertiary-background",
                            "tertiary-foreground",
                            "block",
                            "message-box",
                            "mention",
                            "scrollbar-thumb",
                            "scrollbar-track",
                            "status-online",
                            "status-away",
                            "status-busy",
                            "status-streaming",
                            "status-invisible",
                            "success",
                            "warning",
                            "error",
                            "hover",
                        ] as const
                    ).map((x) => (
                        <div className={styles.entry} key={x}>
                            <span>{x}</span>
                            <div className={styles.override}>
                                <div
                                    className={styles.picker}
                                    style={{ backgroundColor: theme[x] }}>
                                    <input
                                        type="color"
                                        value={theme[x]}
                                        onChange={(v) =>
                                            setOverride({
                                                [x]: v.currentTarget.value,
                                            })
                                        }
                                    />
                                </div>
                                <InputBox
                                    className={styles.text}
                                    value={theme[x]}
                                    onChange={(y) =>
                                        setOverride({
                                            [x]: y.currentTarget.value,
                                        })
                                    }
                                />
                            </div>
                        </div>
                    ))}
                </div>

                <h3>
                    <Text id="app.settings.pages.appearance.mono_font" />
                </h3>
                <ComboBox
                    value={theme.monoscapeFont ?? DEFAULT_MONO_FONT}
                    onChange={(e) =>
                        setTheme({
                            custom: {
                                monoscapeFont: e.currentTarget.value as any,
                            },
                        })
                    }>
                    {MONOSCAPE_FONT_KEYS.map((key) => (
                        <option value={key}>
                            {
                                MONOSCAPE_FONTS[
                                    key as keyof typeof MONOSCAPE_FONTS
                                ].name
                            }
                        </option>
                    ))}
                </ComboBox>

                <h3>
                    <Text id="app.settings.pages.appearance.custom_css" />
                </h3>
                <TextAreaAutoSize
                    maxRows={20}
                    minHeight={480}
                    code
                    value={css}
                    onChange={(ev) => setCSS(ev.currentTarget.value)}
                />
            </CollapsibleSection>
        </div>
    );
}

export const Appearance = connectState(Component, (state) => {
    return {
        settings: state.settings,
    };
});