<!DOCTYPE html5>
<html>
<head>
    {% import "header.html" as header %}
    <title>{{channel.name}}</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <link rel="stylesheet" href="/static/css/common.css">
    <link rel="stylesheet" href="/static/css/ycdl.css">
    <script src="/static/js/common.js"></script>
    <script src="/static/js/api.js"></script>
    <script src="/static/js/hotkeys.js"></script>
    <script src="/static/js/spinner.js"></script>

<style>
.tabbed_container .tab
{
    display: grid;
    grid-auto-flow: row;
    grid-gap: 8px;
    padding: 8px;
}
#video_cards
{
}
.video_card
{
    position: relative;
    display: grid;
    grid-template:
        "thumbnail details toolbox" auto
        "embed embed embed" auto
        /auto 1fr auto;
    grid-gap: 4px;

    margin: 8px 0;
    padding: 8px;

    border-radius: 4px;
    border: 1px solid #000;
}
.video_card:hover
{
    box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.25);
}
.video_card_pending
{
    background-color: #ffffaa;
}
.video_card_ignored
{
    background-color: #ffc886;
}
.video_card_selected
{
    background-color: #13f4ff !important;
}
.video_card_downloaded
{
    background-color: #aaffaa;
}

.video_thumbnail
{
    grid-area: thumbnail;
    justify-self: center;
}

.video_title
{
    word-break: break-word;
}

.video_details
{
    grid-area: details;
    align-self: center;
    /*
    margin-right prevents the empty space of the <a> tag from swallowing
    click events meant for the video card.
    */
    margin-right: auto;
}

.embed_toolbox
{
    grid-area: embed;
    /*
    disabling pointer events on the toolbox prevents it from swallowing click
    events meant for the video card. Then we must re-enable them for child
    elements so the embed button is still clickable.
    This one uses pointer-events instead of margin because margin makes the
    whole embed too small.
    */
    pointer-events: none;
}
.embed_toolbox *
{
    pointer-events: auto;
}

.action_toolbox
{
    grid-area: toolbox;
    justify-self: right;
    display: inline-flex;
    flex-direction: row;
    position: relative;
    margin-top: auto;
    margin-bottom: auto;
}

.video_action_dropdown
{
    z-index: 1;
    background-color: #fff;
    padding: 4px;
    border: 1px solid #000;
    position: absolute;
    top: 100%;
    right: 0;
    display: none;
    flex-direction: column;
}

/*
Thank you SimonSimCity
https://stackoverflow.com/a/35153397
*/
.video_iframe_holder
{
    position: relative;
    width: 100%;
    height: 0;
    padding-bottom: 56.25%;
}
.video_iframe_holder iframe
{
    position: absolute;
    width: 100%;
    height: 100%;
    left: 0;
    top: 0;
}

@media screen and (max-width: 600px)
{
    .video_card
    {
        grid-template:
            "thumbnail details"
            "toolbox toolbox"
            "embed embed"
            /auto 1fr;
    }
}
</style>
</head>


<body>
{{header.make_header()}}
<div id="content_body">
    {% if channel is not none %}
    <h2>{{channel.name}}</h2>
    {% endif %}

    {% if channel is not none %}
    <div class="tabbed_container">
    <div class="tab" data-tab-title="Videos">
    <div><button class="refresh_button button_with_spinner" onclick="return refresh_channel_form(false);">Refresh new videos</button></div>
    <div><button class="refresh_button button_with_spinner" onclick="return refresh_channel_form(true);">Refresh everything</button></div>

    {% endif %}

    <div>View
    {% if channel is not none %}
    <a class="merge_params {{"bold" if not state else ""}}" href="/channel/{{channel.id}}">All</a>
    {% else %}
    <a class="merge_params {{"bold" if not state else ""}}" href="/videos">All</a>
    {% endif %}

    {% for statename in all_states %}
    {% if channel is not none %}
    <a class="merge_params {{"bold" if state == statename else ""}}" href="/channel/{{channel.id}}/{{statename}}">{{statename.capitalize()}}</a>
    {% else %}
    <a class="merge_params {{"bold" if state == statename else ""}}" href="/videos/{{statename}}">{{statename.capitalize()}}</a>
    {% endif %}
    {% endfor %}
    </div>

    <div>Sort by
    <a class="merge_params {{"bold" if orderby == "published" or not orderby else ""}}" href="?orderby=published">Date</a>
    <a class="merge_params {{"bold" if orderby == "duration" else ""}}" href="?orderby=duration">Duration</a>
    <a class="merge_params {{"bold" if orderby == "views" else ""}}" href="?orderby=views">Views</a>
    <a class="merge_params {{"bold" if orderby == "random" else ""}}" href="?orderby=random">Random</a>
    </div>

    <div id="video_cards">
        <center><input disabled class="enable_on_pageload" type="text" id="search_filter"/></center>
        <center><span id="search_filter_count">{{videos|length}}</span> {{state or ""}} items</center>

        {% for video in videos %}
        <div id="video_card_{{video.id}}"
        data-ytid="{{video.id}}"
        onclick="return onclick_select(event);"
        class="video_card video_card_{{video.state}}"
        >
            <img class="video_thumbnail" loading="lazy" src="http://i3.ytimg.com/vi/{{video.id}}/default.jpg" height="100px">
            <div class="video_details">
            <a class="video_title" href="https://www.youtube.com/watch?v={{video.id}}">{{video.published_string}} - {{video.title}}</a>
            <span>({{video.duration | seconds_to_hms}})</span>
            <span>({{video.views}})</span>
            {% if channel is none %}
            <a href="/channel/{{video.author_id}}">({{video.author.name if video.author else video.author_id}})</a> <a href="/channel/{{video.author_id}}/pending">(p)</a>
            {% endif %}
            </div>

            <div class="action_toolbox">
                <button
                {% if video.state == "pending" %}
                class="video_action_pending hidden"
                {% else %}
                class="video_action_pending"
                {% endif %}
                onclick="return action_button_passthrough(event, api.videos.mark_state, 'pending');"
                >Revert to Pending</button>

                {% if video.live_broadcast is none %}
                <button
                {% if video.state == "pending" %}
                class="video_action_download"
                {% else %}
                class="video_action_download hidden"
                {% endif %}
                onclick="return action_button_passthrough(event, api.videos.start_download);"
                >Download</button>
                {% else %}
                <button disabled>Video is {{video.live_broadcast}}</button>
                {% endif %}

                <button
                {% if video.state == "pending" %}
                class="video_action_ignore"
                {% else %}
                class="video_action_ignore hidden"
                {% endif %}
                onclick="return action_button_passthrough(event, api.videos.mark_state, 'ignored');"
                >Ignore</button>
            </div>
            <div class="embed_toolbox">
            <button class="toggle_embed_button" onclick="return toggle_embed_video(event);">Embed</button>
            </div>
        </div>
        {% endfor %}
    </div> <!-- video_cards -->

    {% if channel is not none %}
    </div> <!-- tab-videos -->

    <div class="tab" data-tab-title="Settings">
    <div>
        <label><input type="checkbox" id="set_autorefresh_checkbox" {{"checked" if channel.autorefresh else ""}} onchange="return set_autorefresh_form(event);"/> Automatically refresh this channel regularly.</label>
        <span id="set_autorefresh_spinner" class="hidden">Working...</span>
    </div>

    <div>
        New videos are:
        <select onchange="return set_automark_form(event);">
            <option value="pending" {{"selected" if channel.automark == "pending" else ""}}  >pending</option>
            <option value="downloaded" {{"selected" if channel.automark == "downloaded" else ""}}  >downloaded</option>
            <option value="ignored" {{"selected" if channel.automark == "ignored" else ""}}  >ignored</option>
        </select>
        <span id="set_automark_spinner" class="hidden">Working...</span>
    </div>

    <div>
        <input type="text" id="set_queuefile_extension_input" placeholder="Queuefile extension" value="{{channel.queuefile_extension or ''}}"/>
        <button id="set_queuefile_extension_button" class="button_with_spinner" onclick="return set_queuefile_extension_form();">Set extension</button>
    </div>

    <div>
        <input type="text" id="set_download_directory_input" placeholder="Queuefile directory" value="{{channel.download_directory or ''}}"/>
        <button id="set_download_directory_button" class="button_with_spinner" onclick="return set_download_directory_form();">Set directory</button>
    </div>

    <div><a href="https://www.youtube.com/channel/{{channel.id}}/videos">Channel page</a></div>

    <div><a href="https://www.youtube.com/feeds/videos.xml?channel_id={{channel.id}}">Channel RSS</a></div>

    <button class="red_button button_with_confirm"
    data-prompt="Delete channel and all videos?"
    data-onclick="return delete_channel_form();"
    >Delete Channel</button>
    </div> <!-- tab-settings -->

    </div> <!-- tabbed_container -->
    {% endif %}
</div>
</body>


<script type="text/javascript">
const CHANNEL_ID = "{{channel.id if channel else ""}}";

const STATE = "{{state if state else ""}}";

// FILTER BOX //////////////////////////////////////////////////////////////////////////////////////

var search_filter_wait_for_typing;

var search_filter_hook = function(event)
{
    clearTimeout(search_filter_wait_for_typing);
    search_filter_wait_for_typing = setTimeout(function()
    {
        filter_video_cards(search_filter_box.value);
    }, 200);
}

function filter_video_cards(search_term)
{
    /*
    Apply the current download filter (pending, ignored, downloaded) by removing
    mismatched cards from the dom.
    Apply the search filter textbox by hiding the mismatched cards.
    */
    let count = 0;
    let video_cards = document.getElementById("video_cards");
    video_cards.classList.add("hidden");
    search_term = search_term.toLocaleLowerCase();
    let state_class = "video_card_" + STATE;
    Array.from(video_cards.getElementsByClassName("video_card")).forEach(function(video_card)
    {
        let title = video_card.getElementsByClassName("video_title")[0].innerText.toLocaleLowerCase();
        if (STATE && !video_card.classList.contains(state_class))
        {
            video_cards.removeChild(video_card);
        }
        else if (search_term !== "" && title.indexOf(search_term) == -1)
        {
            video_card.classList.add("hidden");
        }
        else
        {
            video_card.classList.remove("hidden");
            count += 1;
        }
    });
    video_cards.classList.remove("hidden");
    document.getElementById("search_filter_count").innerText = count;
}

var search_filter_box = document.getElementById("search_filter");
search_filter_box.addEventListener("keyup", search_filter_hook);

// VIDEO CARD SELECTION ////////////////////////////////////////////////////////////////////////////

var video_card_selections = document.getElementsByClassName("video_card_selected");
var video_card_first_selected = null;

function select_all()
{
    video_card_first_selected = null;
    for (const video_card of document.getElementsByClassName("video_card"))
    {
        if (video_card.classList.contains("hidden"))
        {
            continue;
        }
        video_card.classList.add("video_card_selected");
    }
}

function select_all_hotkey()
{
    if (! CHANNEL_ID)
    {
        select_all();
        return;
    }
    const tabbed_container = document.getElementsByClassName("tabbed_container")[0];
    if (tabbed_container.dataset.activeTabId === "Videos")
    {
        select_all();
    }
}

function deselect_all()
{
    video_card_first_selected = null;
    for (const video_card of Array.from(video_card_selections))
    {
        if (video_card.classList.contains("hidden"))
        {
            continue;
        }
        video_card.classList.remove("video_card_selected");
    }
}

function deselect_all_hotkey()
{
    if (! CHANNEL_ID)
    {
        deselect_all();
        return;
    }
    const tabbed_container = document.getElementsByClassName("tabbed_container")[0];
    if (tabbed_container.dataset.activeTabId === "Videos")
    {
        deselect_all();
    }
}

function select_one(event)
{
    deselect_all();
    event.target.classList.add("video_card_selected");
    video_card_first_selected = event.target;
}

function select_shift(event)
{
    let video_cards = Array.from(document.getElementsByClassName("video_card"));
    video_cards = video_cards.filter(card => ! card.classList.contains("hidden"))

    let start_index = video_cards.indexOf(video_card_first_selected);
    let end_index = video_cards.indexOf(event.target);
    if (end_index < start_index)
    {
        [start_index, end_index] = [end_index, start_index];
    }

    for (let index = start_index; index <= end_index; index += 1)
    {
        video_cards[index].classList.add("video_card_selected");
    }
}

function select_ctrl(event)
{
    if (event.target.classList.contains("video_card_selected"))
    {
        event.target.classList.remove("video_card_selected");
    }
    else
    {
        video_card_first_selected = event.target;
        event.target.classList.add("video_card_selected");
    }
}

function onclick_select(event)
{
    if (!event.target.classList.contains("video_card"))
    {
        return;
    }

    if (video_card_first_selected === null)
    {
        video_card_first_selected = event.target;
    }

    if (event.shiftKey === false && event.ctrlKey === false)
    {
        select_one(event);
    }
    else if (event.shiftKey === true)
    {
        select_shift(event);
    }
    else if (event.ctrlKey === true)
    {
        select_ctrl(event);
    }

    document.getSelection().removeAllRanges();

    return false;
}

// VIDEO CARD BUTTONS //////////////////////////////////////////////////////////////////////////////

function action_button_passthrough(event, action_function, action_argument)
{
    let elements;
    const this_card = event.target.closest(".video_card");
    if (this_card.classList.contains("video_card_selected"))
    {
        // The clicked card is indeed part of the current selected group.
        elements = Array.from(video_card_selections);
    }
    else
    {
        // The clicked card is actually not one of the selected, so we'll just
        // action it by itself.
        elements = [this_card];
    }

    const video_ids = elements.map(element => element.dataset["ytid"]).join(",");

    if (action_argument === undefined)
    {
        action_function(video_ids, receive_action_response);
    }
    else
    {
        action_function(video_ids, action_argument, receive_action_response);
    }
    if (! event.shiftKey)
    {
        deselect_all();
    }
}

function give_action_buttons(video_card_div)
{
    const toolbox = video_card_div.getElementsByClassName("action_toolbox")[0]
    const buttons = Array.from(toolbox.getElementsByTagName("button"));
    const is_pending = video_card_div.classList.contains("video_card_pending");
    for (const button of buttons)
    {
        if (is_pending)
            { button.classList.remove("hidden"); }
        else
            { button.classList.add("hidden"); }
    }

    const button_pending = video_card_div.getElementsByClassName("video_action_pending")[0];
    if (is_pending)
        { button_pending.classList.add("hidden"); }
    else
        { button_pending.classList.remove("hidden"); }
}

function receive_action_response(response)
{
    if (response.meta.status !== 200)
    {
        alert(JSON.stringify(response));
        return;
    }
    const video_ids = response.data.video_ids;
    const state = response.data.state;
    const state_class = "video_card_" + state;
    for (const video_id of video_ids)
    {
        const card = document.getElementById("video_card_" + video_id);
        {% for statename in all_states %}
        card.classList.remove("video_card_{{statename}}");
        {% endfor %}
        card.classList.add(state_class);
        give_action_buttons(card);
    }
}

function toggle_embed_video(event)
{
    const video_card = event.target.closest(".video_card");
    const video_id = video_card.dataset.ytid;
    const toggle_button = video_card.getElementsByClassName("toggle_embed_button")[0];
    const embed_toolbox = video_card.getElementsByClassName("embed_toolbox")[0];
    const embeds = video_card.getElementsByClassName("video_iframe_holder");
    if (embeds.length == 0)
    {
        const html = `
        <div class="video_iframe_holder">
        <iframe width="711" height="400" frameborder="0" allow="encrypted-media" allowfullscreen
        src="https://www.youtube.com/embed/${video_id}"></iframe>
        </div>
        `
        const embed = common.html_to_element(html);
        embed_toolbox.appendChild(embed);
        toggle_button.innerText = "Unembed";
    }
    else
    {
        embeds[0].parentElement.removeChild(embeds[0]);
        toggle_button.innerText = "Embed";
    }
}

// CHANNEL ACTIONS /////////////////////////////////////////////////////////////////////////////////

function delete_channel_form()
{
    api.channels.delete_channel(CHANNEL_ID, api.channels.callback_go_to_channels);
}

function refresh_channel_form(force)
{
    console.log(`Refreshing channel ${CHANNEL_ID}, force=${force}.`);
    api.channels.refresh_channel(CHANNEL_ID, force, refresh_channel_callback)
}

function refresh_channel_callback(response)
{
    if (response.meta.status == 200)
    {
        common.refresh();
    }
    else
    {
        alert(JSON.stringify(response));
    }
}

function set_automark_form(event)
{
    set_automark_spinner.show();
    api.channels.set_automark(CHANNEL_ID, event.target.value, set_automark_callback);
}

function set_automark_callback(response)
{
    if (response.meta.status != 200)
    {
        alert(JSON.stringify(response));
    }
    set_automark_spinner.hide();
}

function set_autorefresh_form(event)
{
    set_autorefresh_spinner.show();
    api.channels.set_autorefresh(CHANNEL_ID, event.target.checked, set_autorefresh_callback);
}

function set_autorefresh_callback(response)
{
    if (response.meta.status != 200)
    {
        alert(JSON.stringify(response));
    }
    set_autorefresh_spinner.hide();
}

function set_download_directory_form(event)
{
    const download_directory = set_download_directory_input.value.trim();
    api.channels.set_download_directory(CHANNEL_ID, download_directory, set_download_directory_callback);
}

function set_download_directory_callback(response)
{
    if (response.meta.status != 200)
    {
        alert(JSON.stringify(response));
    }
    window[set_download_directory_button.dataset.spinnerCloser]();
}

function set_queuefile_extension_form(event)
{
    const extension = set_queuefile_extension_input.value.trim();
    api.channels.set_queuefile_extension(CHANNEL_ID, extension, set_queuefile_extension_callback);
}

function set_queuefile_extension_callback(response)
{
    if (response.meta.status != 200)
    {
        alert(JSON.stringify(response));
    }
    window[set_queuefile_extension_button.dataset.spinnerCloser]();
}

if (CHANNEL_ID)
{
    var set_queuefile_extension_input = document.getElementById("set_queuefile_extension_input");
    var set_queuefile_extension_button = document.getElementById("set_queuefile_extension_button");
    common.bind_box_to_button(set_queuefile_extension_input, set_queuefile_extension_button);

    var set_automark_spinner = document.getElementById("set_automark_spinner");
    set_automark_spinner = new spinner.Spinner(set_automark_spinner);

    var set_autorefresh_spinner = document.getElementById("set_autorefresh_spinner");
    set_autorefresh_spinner = new spinner.Spinner(set_autorefresh_spinner);
}

////////////////////////////////////////////////////////////////////////////////////////////////////

function on_pageload()
{
    hotkeys.register_hotkey("ctrl a", select_all_hotkey, "Select all videos.");
    hotkeys.register_hotkey("ctrl d", deselect_all_hotkey, "Deselect all videos.");
}
document.addEventListener("DOMContentLoaded", on_pageload);
</script>
</html>