<div id="trainingPage" class="section-profile" x-data="alpineTraining()"
     x-init="initTraining(); $watch('selectedCert', value => getTraining(value)); $watch('selectedBadge', value => updateVisibleFlags(value))">

    <!-- CONFETTI -->
    <template x-if="completedCertificate">
        <canvas id="confettiCanvas"></canvas>
    </template>

    <div class="z-index-1">
        <div>
            <div x-ref="trainingHeader">
                <h2>Training</h2>
            </div>
            <hr>
        </div>

        <!-- CERT SELECTION -->

        <form>
            <div id="select-certificate" class="field has-addons">
                <label class="label">Select a certificate &nbsp;&nbsp;&nbsp;</label>
                <div class="control is-expanded">
                    <div class="select is-small is-fullwidth">
                        <select x-model="selectedCert">
                            <option default disabled value="">---</option>
                            {% for cert in certificates %}
                            <option>{{ cert.name }}</option>
                            {% endfor %}}
                        </select>
                    </div>
                </div>
            </div>
        </form>

        <!-- CERT COMPLETION CODE -->

        <template x-if="completedCertificate">
            <div class="content is-flex is-align-items-center is-flex-direction-column mt-4">
                <h3>🎉 Certificate complete! 🎉</h3>
                <div class="field has-addons">
                    <div class="control">
                        <input id="certificatecode" type="text" readonly
                               class="input is-small"
                               x-model="certificateCode"
                               aria-label="Certificate code"/>
                    </div>
                    <div class="control">
                        <a class="button is-small" x-on:click="copyCode()">
                            <span class="icon">
                                <em class="fas fa-copy"></em>
                            </span>
                            <span>Copy</span>
                        </a>
                    </div>
                </div>
                <p>
                    Congrats! Fill out the form to validate your code and get a certificate of completion.
                </p>
                <a class="button fancy-button" href="https://forms.office.com/g/sYRNDuxCjC" target="_blank" rel="noopener">Get your certificate 🎓 </a>
            </div>
        </template>

        <!-- BADGES -->

        <template x-if="badgeList">
            <div class="is-flex is-justify-content-space-evenly mt-3">
                <template x-for="(badge, index) in badgeList" :key="index">
                    <button class="badge-container-button"
                            x-on:click="(selectedBadge === badge) ? selectedBadge = '' : selectedBadge = badge"
                            x-bind:class="{ 'selected-badge': selectedBadge.name === badge.name }">
                        <span class="is-flex is-flex-direction-column is-justify-content-center is-align-items-center p-2">
                            <span class="badge-icon-container"
                                  x-bind:class="badge.completed ? 'badge-completed' : ''">
                                <svg xmlns="http://www.w3.org/2000/svg"
                                     fill="current"
                                     viewBox="0 0 24 24"
                                     stroke="currentColor">
                                    <path stroke-linecap="round"
                                          stroke-linejoin="round"
                                          stroke-width="2"
                                          d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
                                </svg>
                            </span>
                            <img x-bind:alt="badge.name"
                                 class="badge-icon-img"
                                 onerror="this.src='/training/img/badges/defaultlock.png'"
                                 x-bind:src="badge.icon_src"/>
                        </span>
                        <span class="badge-text hover:bg-caldera-primary rounded"
                              x-bind:class="{ 'badge-completed-text': badge.completed }"
                              x-text="badge.name"></span>
                    </button>
                </template>
            </div>
        </template>

        <!-- FLAG STATUS -->

        <div class="has-text-centered mt-4 mb-4">
            <template x-for="(flag, index) in visibleFlagList" :key="index">
                <span class="icon">
                    <em x-bind:class="flag.completed ? 'fas fa-flag' : 'far fa-flag'">
                </span>
            </template>
        </div>

        <!-- FLAGS -->

        <div class="flag-card-container">
            <template x-for="(flag, index) in visibleFlagList" :key="flag.name">
                <div class="flag-card is-flex is-flex-direction-column rounded">
                    <div class="flag-card-content is-flex is-flex-direction-column overflow-hidden"
                         x-bind:class="{ 'flag-card-content-active': isCardActive(index), 'flag-show-more': flag.showMore }">

                        <!-- FLAG TITLE -->

                        <div class="flag-card-title is-flex is-justify-content-space-evenly is-align-items-center"
                             x-bind:class="{ 'flag-card-title-active': flag.completed || isCardActive(index) }">
                            <div class="is-flex is-justify-content-start is-align-items-center flag-card-title-name">
                                <span class="icon" x-bind:class="flag.completed ? 'flag-icon-completed' : ''">
                                    <em x-bind:class="flag.completed ? 'fas fa-flag' : 'far fa-flag'"></em>
                                </span>
                                <p x-text="flag.name"></p>
                            </div>
                            <a class="icon has-tooltip-left solution-guide-link"
                               x-bind:class="flag.has_solution_guide ? '' : 'hidden'"
                               x-bind:href="`/plugin/training/solution-guides/certificates/${flag.cert_name}/badges/${flag.badge_name}/flags/${flag.name}`"
                               target="_blank"
                               data-tooltip="Solution Guide">
                                <em class="far fa-question-circle"></em>
                            </a>
                            <div class="is-flex is-justify-content-center is-align-items-center flag-card-title-badge">
                                <span class="flag-badge-icon-container">
                                    <svg xmlns="http://www.w3.org/2000/svg"
                                            fill="current"
                                            viewBox="0 0 24 24"
                                            stroke="currentColor">
                                        <path stroke-linecap="round"
                                                stroke-linejoin="round"
                                                stroke-width="2"
                                                d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/>
                                    </svg>
                                </span>
                                <img x-bind:alt="flag.badge_name"
                                        class="badge-icon-img"
                                        onerror="this.src='/training/img/badges/defaultlock.png'"
                                        x-bind:src="flag.badge_icon"/>
                            </div>
                        </div>

                        <!--  FLAG CHALLENGE TEXT -->

                        <div class="flag-card-text">
                            <div>
                                <div class="is-flex is-flex-direction-column is-justify-content-center has-text-left">
                                    <p class="has-text-weight-bold" x-text="flag.challenge"></p>
                                    <p x-text="flag.extra_info"></p>
                                    <template x-if="flag.code.includes('text-entry')">
                                        <span>
                                            <label x-bind:for="flag.code">Write text here:</label>
                                            <input x-bind:disabled="flag.completed"
                                                   class="text-colors-black pl-1 pr-2"
                                                   x-bind:id="flag.code"
                                                   placeholder="type here"
                                                   x-on:input="onTextInput"/>
                                        </span>
                                    </template>
                                </div>
                            </div>
                        </div>
                    </div>

                    <!-- SHOW MORE BUTTON -->

                    <div x-on:click="flag.showMore = !flag.showMore" class="flag-show-more-button is-flex is-justify-content-center" x-bind:class="{ 'flag-show-more-active': isCardActive(index) }">
                        <span class="icon is-small">
                            <em x-bind:class="flag.showMore ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"></em>
                        </span>
                    </div>
                </div>
            </template>
        </div>

    </div>
</div>

<script>
    function alpineTraining() {
        return {
            selectedCert: '',
            selectedBadge: '',
            badgeList: [],
            visibleFlagList: [],
            completedFlags: 0,
            completedBadges: 0,
            flagList: [],
            completedCertificate: false,
            certificateCodeList: [],
            certificateCode: '',
            end: 0,

            async initTraining() {
                function sleep(ms) {
                    return new Promise((resolve) => setTimeout(resolve, ms));
                }

                while (this.$refs.trainingHeader) {
                    await sleep(3000);
                    this.getTraining();
                }
            },

            getEmptyDataObject() {
                return {
                    flagList: [],
                    badgeList: [],
                    completedFlags: 0,
                    completedBadges: 0,
                    certificateCodeList: [],
                };
            },

            isCardActive(index) {
                if (this.selectedBadge) {
                    const badgeIndex = this.badgeList.findIndex((badge) => badge.name === this.selectedBadge.name);
                    if (badgeIndex > 0) {
                        const earlierFlags = this.flagList.filter((flag) => flag.badge_name === this.badgeList[badgeIndex - 1].name);
                        if (!earlierFlags[earlierFlags.length - 1].completed) {
                            return false;
                        }
                    }
                }

                return (
                    (index === 0 && this.visibleFlagList.length > 0 && !this.visibleFlagList[0].completed) ||
                    (this.visibleFlagList[index] && !this.visibleFlagList[index].completed && this.visibleFlagList[index - 1].completed)
                );
            },

            /*
            updateVisibleFlags() is called by $watch in training.html, when the
            variable selectedBadge is updated,
            and updates the list of visible flags as well
            */
            updateVisibleFlags(badge) {
                if (badge) {
                    this.selectedBadge = badge;
                    this.visibleFlagList = this.flagList.filter(
                        (flag) => flag.badge_name === this.selectedBadge.name,
                    );
                } else {
                    this.visibleFlagList = this.flagList;
                }
            },

            /*
            Check if certificate is complete, and generate code if completed
            */
            checkCertificateCompletion() {
                if (this.completedBadges === this.badgeList.length) {
                    this.completedCertificate = true;
                    let code = this.certificateCodeList.sort(
                        (a, b) => a.toString().length - b.toString().length,
                    );
                    code = code.join(' ');
                    this.certificateCode = btoa(code);

                    const duration = 10000;
                    if (this.end === 0) this.end = Date.now() + duration; // spray confetti for 10 seconds
                    this.confetti();
                }
            },

            compareFlags(currentBadge, iconSrc, flag, flagIndex) {
                const updatedFlag = {
                    ...flag,
                    badge_name: currentBadge.name,
                    badge_icon: iconSrc,
                    cert_name: this.selectedCert,
                    showMore: false,
                };
                if (this.flagList[flagIndex]) {
                    const previousFlag = this.flagList[flagIndex];
                    if (previousFlag.name === updatedFlag.name) {
                        updatedFlag.showMore = previousFlag.showMore;
                    }
                }
                return updatedFlag;
            },

            updateFlagData(newData) {
                if (newData) {
                    this.flagList = newData.flagList;
                    this.badgeList = newData.badgeList;
                    this.completedFlags = newData.completedFlags;
                    this.completedBadges = newData.completedBadges;
                    this.certificateCodeList = newData.certificateCodeList;
                }
            },

            async getFlags(data) {
                if (!data) return;
                const newData = this.getEmptyDataObject();
                let runningFlagIndex = 0;

                // Fetch flag from API and compares it to previous data,
                // rather than completely override (for variables like showMore)
                data.badges.forEach((badge) => {
                    const iconSrc = `/training/img/badges/${badge.name}.png`;
                    let isBadgeCompleted = false;
                    let badgeCompletedFlags = 0;

                    badge.flags.forEach((flag) => {
                        const currentFlag = this.compareFlags(badge, iconSrc, flag, runningFlagIndex);
                        if (currentFlag.completed) badgeCompletedFlags += 1;
                        newData.flagList.push(currentFlag);
                        newData.certificateCodeList.push(currentFlag.code);
                        runningFlagIndex += 1;
                    });

                    if (badgeCompletedFlags === badge.flags.length) {
                        newData.completedBadges += 1;
                        isBadgeCompleted = true;
                    }

                    newData.badgeList.push({...badge, completed: isBadgeCompleted, icon_src: iconSrc});
                    // Keep selected badge so it doesn't get overriden by new data
                    if (this.selectedBadge.name === badge.name) this.selectedBadge = badge;
                    newData.completedFlags += badgeCompletedFlags;
                });
                this.updateFlagData(newData);
            },

            /*
                getTraining() makes call to get flags, and if successful, does the following:
                1) sets a refresher() to fetch flags again after set interval
                2) check if certificate is complete
                3) updates visibleFlagList
            */
            getTraining() {
                if (!this.selectedCert) return;
                apiV2('POST', '/plugin/training/flags', {
                    name: this.selectedCert,
                    answers: {},
                }).then((data) => {
                    this.getFlags(data);
                    this.updateVisibleFlags(this.selectedBadge);
                    this.checkCertificateCompletion();
                }).catch((e) => console.error(e));
            },

            copyCode() {
                document.getElementById('certificatecode').select();
                document.execCommand('copy');
                toast('Code copied', true);
            },

            // Source: https://github.com/catdad/canvas-confetti
            confetti() {
                const canvas = document.getElementById('confettiCanvas');
                if (!canvas || !confetti) return;
                // eslint-disable-next-line
                const confettiCanon = confetti.create(canvas, {
                    resize: true,
                    useWorker: true,
                });

                const frame = () => {
                    // launch a few confetti from the left edge
                    confettiCanon({
                        particleCount: 100,
                        angle: 60,
                        spread: 55,
                        origin: {x: 0},
                    });
                    // and launch a few from the right edge
                    confettiCanon({
                        particleCount: 100,
                        angle: 120,
                        spread: 55,
                        origin: {x: 1},
                    });
                };

                // keep going until we are out of time
                if (Date.now() < this.end) {
                    requestAnimationFrame(frame);
                }
            },
        };
    }
</script>

<style>
    #select-certificate {
        max-width: 800px;
        margin: 0 auto;
    }

    #trainingPage .z-index-1 * {
        z-index: 1
    }

    #trainingPage canvas {
        position: fixed;
        z-index: 0;
        width: 85%;
        height: 100%;
        top: 0;
    }

    #trainingPage .overflow-hidden {
        overflow: hidden;
    }

    #trainingPage .hover\:bg-caldera-primary:hover {
        background-color: var(--primary-color);
    }

    #trainingPage .rounded {
        border-radius: 4px !important;
    }

    #trainingPage .solution-guide-link {
        color: white;
        cursor: pointer;
    }

    #trainingPage .hidden {
        pointer-events: none;
        color: grey;
    }

    #trainingPage .badge-container {
        margin: 0.75rem 0;
    }

    #trainingPage .badge-container-button {
        color: var(--color-white);
        width: 5rem !important;
        padding: 0.85rem 0.25rem 0.25rem;
        font-size: 1rem;
        line-height: 1.5rem;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
        cursor: pointer;
        background-color: initial;
        border: none;
    }

    #trainingPage .badge-container-button:hover {
        background-color: var(--primary-color);
    }

    #trainingPage .badge-icon-container {
        z-index: 0;
        width: 3.5rem !important;
        fill: currentColor;
        position: absolute;
        opacity: 0.8;
    }

    #trainingPage .badge-icon-img {
        /*Important styles to override those from shared.css*/
        width: 20px !important;
        height: auto !important;
        border: none !important;
        background-color: initial !important;
        z-index: 10;
        max-width: 100%;
        display: block;
        border-radius: 0;
        margin-bottom: 0;
    }

    #trainingPage .badge-completed-text {
        background-color: var(--color-complete);
        color: var(--color-gray) !important;
    }

    #trainingPage .badge-text {
        text-decoration: none;
        color: var(--color-white);
        padding-left: 0.25rem;
        padding-right: 0.25rem;
        margin-top: 1rem;
        font-size: 0.75rem;
        line-height: 1rem;
    }

    #trainingPage .selected-badge {
        font-weight: bold;
        background-color: var(--primary-color);
        border-radius: 5px;
    }

    #trainingPage .flag-card-container {
        display: flex;
        justify-content: space-evenly;
        flex-flow: row wrap;
        box-sizing: border-box;
    }

    #trainingPage .flag-card {
        box-sizing: border-box;
        margin: 0.25rem;
        transition-property: all;
        transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
        transition-duration: 150ms;
        background-color: initial !important;
    }

    @media (min-width: 640px) {
        #trainingPage .flag-card {
            width: 100%;
            font-size: 0.875rem;
            line-height: 1.25rem;
        }
    }

    @media (min-width: 768px) {
        #trainingPage .flag-card {
            width: 33.333333%;
            font-size: 1rem;
            line-height: 1.75rem;
        }
    }

    @media (min-width: 1024px) {
        #trainingPage .flag-card {
            width: 24%;
            font-size: 0.9rem;
            line-height: 2rem;
        }
    }

    #trainingPage .flag-icon-completed {
        color: gold;
    }

    #trainingPage .flag-card-content {
        height: 18rem;
        width: 100%;
        background-color: #272727;
        border-radius: 4px 4px 0 0;
    }

    #trainingPage .flag-show-more {
        min-height: 18rem;
        height: auto;
    }

    #trainingPage .flag-card-title {
        padding: 5px;
        background-color: #202020;
        color: var(--color-white);
        font-size: 1.125rem;
        line-height: 1.75rem;
        text-align: left;
    }

    #trainingPage .flag-card-title-active {
        background-color: var(--primary-color);
    }

    #trainingPage .flag-card-title div:first-child span {
        width: 1.5rem;
        margin-right: 0.5rem;
    }

    #trainingPage .flag-card:not(.flag-card-completed) .flag-card-title svg {
        opacity: 0.5;
    }

    #trainingPage .flag-card-title-name {
        width: 83.333333%;
    }

    #trainingPage .flag-card-title-badge {
        width: 16.666667%;
    }

    #trainingPage .flag-badge-icon-container {
        z-index: 0;
        fill: currentColor;
        position: absolute;
        width: 35px;
        padding-top: 6px;
    }

    #trainingPage .flag-card-text {
        overflow-wrap: break-word;
        padding: 0 0.5rem;
        background-color: #272727;
    }

    #trainingPage .flag-card-content-active {
        border: 2px solid var(--primary-color);
        border-bottom: none;
    }

    #trainingPage .flag-show-more-button {
        padding: 0.5rem;
        cursor: pointer;
        background-color: #272727;
        border-radius: 0 0 4px 4px;
    }

    #trainingPage .flag-show-more-active {
        border: 2px solid var(--primary-color);
        border-top: none;
    }

    #trainingPage .flag-show-more-button span {
        width: 1rem;
    }
</style>
