import * as React from "react";
import { getHash } from "../../maze-utils/src/hash";
import { getErrorMessage } from "../../maze-utils/src/formating";
import Config from "../config";
import { asyncRequestToServer } from "../utils/requests";
import PencilIcon from "../svg-icons/pencilIcon";
import ClipboardIcon from "../svg-icons/clipboardIcon";
import CheckIcon from "../svg-icons/checkIcon";
import { showDonationLink } from "../utils/configUtils";

export const YourWorkComponent = () => {
    const [isSettingUsername, setIsSettingUsername] = React.useState(false);
    const [username, setUsername] = React.useState("");
    const [newUsername, setNewUsername] = React.useState("");
    const [usernameSubmissionStatus, setUsernameSubmissionStatus] = React.useState("");
    const [submissionCount, setSubmissionCount] = React.useState("");
    const [viewCount, setViewCount] = React.useState(0);
    const [minutesSaved, setMinutesSaved] = React.useState(0);
    const [showDonateMessage, setShowDonateMessage] = React.useState(false);

    React.useEffect(() => {
        (async () => {
            const values = ["userName", "viewCount", "minutesSaved", "vip", "permissions", "segmentCount"];
            const result = await asyncRequestToServer("GET", "/api/userInfo", {
                publicUserID: await getHash(Config.config!.userID!),
                values
            });

            if (result.ok) {
                const userInfo = JSON.parse(result.responseText);
                setUsername(userInfo.userName);
                setSubmissionCount(Math.max(Config.config.sponsorTimesContributed ?? 0, userInfo.segmentCount).toLocaleString());
                setViewCount(userInfo.viewCount);
                setMinutesSaved(userInfo.minutesSaved);

                Config.config!.isVip = userInfo.vip;
                Config.config!.permissions = userInfo.permissions;

                setShowDonateMessage(Config.config.showDonationLink && Config.config.donateClicked <= 0 && Config.config.showPopupDonationCount < 5
                    && viewCount < 50000 && !Config.config.isVip && Config.config.skipCount > 10 && showDonationLink());
            }
        })();
    }, []);

    return (
        <div className="sbYourWorkBox">
            <h2 className="sbHeader" style={{ "padding": "8px 15px" }}>
                {chrome.i18n.getMessage("yourWork")}
            </h2>
            <div className="sbYourWorkCols">
                {/* Username */}
                <div id="usernameElement">
                    <p className="u-mZ grey-text">
                        {chrome.i18n.getMessage("Username")}:
                        {/* loading/errors */}
                        <span id="setUsernameStatus" 
                            className={`u-mZ white-text${!usernameSubmissionStatus ? " hidden" : ""}`}>
                            {usernameSubmissionStatus}
                        </span>
                    </p>
                    <div id="setUsernameContainer" className={isSettingUsername ? " hidden" : ""}>
                        <p id="usernameValue">{username}</p>
                        <button id="setUsernameButton" 
                            title={chrome.i18n.getMessage("setUsername")}
                            onClick={() => {
                                setNewUsername(username);
                                setIsSettingUsername(!isSettingUsername);
                            }}>
                            <PencilIcon id="sbPopupIconEdit" className="sbPopupButton" />
                        </button>
                        <button id="copyUserID" 
                            title={chrome.i18n.getMessage("copyPublicID")}
                            onClick={async () => {
                                window.navigator.clipboard.writeText(await getHash(Config.config!.userID!));
                            }}>
                            <ClipboardIcon id="sbPopupIconCopyUserID" className="sbPopupButton" />
                        </button>
                    </div>
                    <div id="setUsername" className={!isSettingUsername ? " hidden" : " SBExpanded"}>
                        <input id="usernameInput" 
                            placeholder={chrome.i18n.getMessage("Username")}
                            value={newUsername}
                            onChange={(e) => {
                                setNewUsername(e.target.value);
                            }}/>
                        <button id="submitUsername"
                            onClick={() => {
                                if (newUsername.length > 0) {
                                    setUsernameSubmissionStatus(chrome.i18n.getMessage("Loading"));
                                    asyncRequestToServer("POST", `/api/setUsername?userID=${Config.config!.userID}&username=${newUsername}`)
                                    .then((result) => {
                                        if (result.ok) {
                                            setUsernameSubmissionStatus("");
                                            setUsername(newUsername);
                                            setIsSettingUsername(!isSettingUsername);
                                        } else {
                                            setUsernameSubmissionStatus(getErrorMessage(result.status, result.responseText));
                                        }
                                    }).catch((e) => {
                                        setUsernameSubmissionStatus(`${chrome.i18n.getMessage("Error")}: ${e}`);
                                    });
                                }
                            }}>
                            <CheckIcon id="sbPopupIconCheck" className="sbPopupButton" />
                        </button>
                    </div>
                </div>
                <SubmissionCounts
                    isSettingUsername={isSettingUsername}
                    submissionCount={submissionCount}
                />
            </div>

            <TimeSavedMessage
                viewCount={viewCount}
                minutesSaved={minutesSaved}
            />

            {showDonateMessage && <DonateMessage onClose={() => {
                setShowDonateMessage(false);
                Config.config.showPopupDonationCount = 100;
            }} />}

        </div>
    );
};

function SubmissionCounts(props: { isSettingUsername: boolean; submissionCount: string }): JSX.Element {
    return <>
        <div id="sponsorTimesContributionsContainer" className={props.isSettingUsername ? " hidden" : ""}>
            <p className="u-mZ grey-text">
                {chrome.i18n.getMessage("Submissions")}:
            </p>
            <p id="sponsorTimesContributionsDisplay" className="u-mZ">{props.submissionCount}</p>
        </div>
    </>
}

function TimeSavedMessage({ viewCount, minutesSaved }: { viewCount: number; minutesSaved: number }): JSX.Element {
    return (
        <>
            {
                viewCount > 0 &&
                <p id="sponsorTimesViewsContainer" className="u-mZ sbStatsSentence">
                    {chrome.i18n.getMessage("savedPeopleFrom")}
                    <b>
                        <span id="sponsorTimesViewsDisplay">{viewCount.toLocaleString()}</span>{" "}
                    </b>
                    <span id="sponsorTimesViewsDisplayEndWord">{viewCount !== 1 ? chrome.i18n.getMessage("Segments") : chrome.i18n.getMessage("Segment")}</span>
                    <br />
                    <span className="sbExtraInfo">
                        {"("}{" "}
                        <b>
                            <span id="sponsorTimesOthersTimeSavedDisplay">{getFormattedHours(minutesSaved)}</span>{" "}
                            <span id="sponsorTimesOthersTimeSavedEndWord">{minutesSaved !== 1 ? chrome.i18n.getMessage("minsLower") : chrome.i18n.getMessage("minLower")}</span>{" "}
                        </b>
                        <span>{chrome.i18n.getMessage("youHaveSavedTimeEnd")}</span>{" "}
                        {" )"}
                    </span>
                </p>
            }
            <p id="sponsorTimesSkipsDoneContainer" className="u-mZ sbStatsSentence">
                {chrome.i18n.getMessage("youHaveSkipped")}
                <b>
                    <span id="sponsorTimesSkipsDoneDisplay">{Config.config.skipCount}</span>{" "}
                </b>
                <span id="sponsorTimesSkipsDoneEndWord">{Config.config.skipCount > 1 ? chrome.i18n.getMessage("Segments") : chrome.i18n.getMessage("Segment")}</span>{" "}
                <span className="sbExtraInfo">
                    {"("}{" "}
                    <b>
                        <span id="sponsorTimeSavedDisplay">{Config.config.minutesSaved}</span>{" "}
                        <span id="sponsorTimeSavedEndWord">{Config.config.minutesSaved !== 1 ? chrome.i18n.getMessage("minsLower") : chrome.i18n.getMessage("minLower")}</span>{" "}
                    </b>
                    {")"}
                </span>
            </p>
        </>
    );
}

function DonateMessage(props: { onClose: () => void }): JSX.Element {
    return (
        <div id="sponsorTimesDonateContainer" style={{ alignItems: "center", justifyContent: "center" }}>
            <img className="sbHeart" src="/icons/heart.svg" alt="Heart icon" />
            <a id="sbConsiderDonateLink" href="https://sponsor.ajay.app/donate" target="_blank" rel="noreferrer" onClick={() => {
                Config.config.donateClicked = Config.config.donateClicked + 1;
            }}>
                {chrome.i18n.getMessage("considerDonating")}
            </a>
            <img id="sbCloseDonate" src="/icons/close.png" alt={chrome.i18n.getMessage("closeIcon")} height="8" style={{ paddingLeft: "5px", cursor: "pointer" }} onClick={props.onClose} />
        </div>
    );
}

/**
 * Converts time in minutes to 2d 5h 25.1
 * If less than 1 hour, just returns minutes
 *
 * @param {float} minutes
 * @returns {string}
 */
function getFormattedHours(minutes) {
    minutes = Math.round(minutes * 10) / 10;
    const years = Math.floor(minutes / 525600); // Assumes 365.0 days in a year
    const days = Math.floor(minutes / 1440) % 365;
    const hours = Math.floor(minutes / 60) % 24;
    return (years > 0 ? years + chrome.i18n.getMessage("yearAbbreviation") + " " : "") + (days > 0 ? days + chrome.i18n.getMessage("dayAbbreviation") + " " : "") + (hours > 0 ? hours + chrome.i18n.getMessage("hourAbbreviation") + " " : "") + (minutes % 60).toFixed(1);
}