import Long from "long";
import { API } from "revolt.js";
import { Permission } from "revolt.js";
import styled from "styled-components";

import { Text } from "preact-i18n";
import { useMemo } from "preact/hooks";

import Checkbox from "../../ui/Checkbox";
import { OverrideSwitch } from "@revoltchat/ui";

interface PermissionSelectProps {
    id: keyof typeof Permission;
    permission: number;
    value: API.OverrideField | number;
    onChange: (value: API.OverrideField | number) => void;
}

type State = "Allow" | "Neutral" | "Deny";

const PermissionEntry = styled.label`
    gap: 8px;
    width: 100%;
    margin: 8px 0;
    display: flex;
    font-size: 1.1em;
    align-items: center;

    .title {
        flex-grow: 1;

        display: flex;
        flex-direction: column;
    }

    .description {
        font-size: 0.8em;
        color: var(--secondary-foreground);
    }
`;

export function PermissionSelect({
    id,
    permission,
    value,
    onChange,
}: PermissionSelectProps) {
    const state: State = useMemo(() => {
        if (typeof value === "object") {
            if (Long.fromNumber(value.d).and(permission).eq(permission)) {
                return "Deny";
            }

            if (Long.fromNumber(value.a).and(permission).eq(permission)) {
                return "Allow";
            }

            return "Neutral";
        } else {
            if (Long.fromNumber(value).and(permission).eq(permission)) {
                return "Allow";
            }

            return "Neutral";
        }
    }, [value]);

    function onSwitch(state: State) {
        if (typeof value !== "object") throw "!";

        // Convert to Long so we can do bitwise ops.
        let allow = Long.fromNumber(value.a);
        let deny = Long.fromNumber(value.d);

        // Clear the current permission value.
        if (allow.and(permission).eq(permission)) {
            allow = allow.xor(permission);
        }

        if (deny.and(permission).eq(permission)) {
            deny = deny.xor(permission);
        }

        // Apply the current permission state.
        if (state === "Allow") {
            allow = allow.or(permission);
        }

        if (state === "Deny") {
            deny = deny.or(permission);
        }

        // Invoke state change.
        onChange({
            a: allow.toNumber(),
            d: deny.toNumber(),
        });
    }

    return (
        <PermissionEntry>
            <span class="title">
                <Text id={`permissions.${id}.t`}>{id}</Text>
                <span class="description">
                    <Text id={`permissions.${id}.d`} />
                </span>
            </span>
            {typeof value === "object" ? (
                <OverrideSwitch state={state} onChange={onSwitch} />
            ) : (
                <Checkbox
                    checked={state === "Allow"}
                    onChange={() =>
                        onChange(
                            Long.fromNumber(value, false)
                                .xor(permission)
                                .toNumber(),
                        )
                    }
                />
            )}
        </PermissionEntry>
    );
}
