<template>
    <div>
        <input id="searchbox0" class="searchbox" type="text" v-model="searchbox_str" placeholder="Search String goes here, for example: >5m,c++"/>
        <div class="grid-x large-up-6">
            <div v-for="video in Videos" :key="video.ID" class="cell">
                <div class="card ytcard">
                    <a :href="video.URL"><img :src="video.Thumbnail"></a>
                    <div class="card-section description">
                        <div class="descriptiontitle">{{ video.Title }}</div>
                        <div class="descriptionchannel">{{ video.Channel }}</div>
                    </div>
                </div>
            </div>
        </div >
    </div>
</template>

<script lang="ts">
import Vue from "vue";
import Axios from "axios";
import * as _ from "lodash";

// Wrapper for videos returned from our server.
class Video {
    // Title of the video according to youtube.
    public Title: string;

    // Description of video according to youtube.
    public Description: string;

    // Youtube ID
    public ID: string;

    // Thumbnail
    public Thumbnail: string;
    
    // What channel made this video.
    public Channel: string;

    // Duration of the video in seconds.
    public Seconds: number;

    // Tags relevant to the video.
    public Tags: Array<string>;
    
    // Youtube URL of the video.
    public URL: string;

    // Popuplate this using data from our server.
    constructor(v: any){
        this.Title = v.title;
        this.Description = v.description;
        this.ID = v.id;
        this.Thumbnail = v.thumbnail;
        this.Channel = v.channel;
        this.Seconds = v.seconds;
        this.Tags = v.tags;
        this.URL = "https://www.youtube.com/watch?v=" + v.id;
    }
}

async function search_videos(searchstr : string): Promise<Array<Video>> {
    // How many chars at most for the description.
    const maxcharsdescriptionfield = 100;

    // Temporary holder for videos.
    let Videos : Array<Video> = [];

    // Ask server for videos.
    let resp = await Axios.get('http://localhost:62214/api/Videos/search/' + searchstr).catch(e => console.log(e));

    // Handle all our nulls.
    if (resp == null || resp.data == null)
        console.log("server /api/videos/search return is null");
    else {
        // Parse our videos.
        resp.data.forEach((v: any) => {
            // Trim description if needed.
            if (v.description.length > maxcharsdescriptionfield) {
                v.description = v.description.substring(0, maxcharsdescriptionfield) + " ...";
            }

            // Add it to our array
            Videos.push(new Video(v));
        });
    }
    
    // Send back the resulting videos.
    return Promise.resolve(Videos);
}

async function get_videos(): Promise<Array<Video>> {
    // How many chars at most for the description.
    const maxcharsdescriptionfield = 100;

    // Temporary holder for videos.
    let Videos : Array<Video> = [];

    // Ask server for videos.
    let resp = await Axios.get('http://localhost:62214/api/Videos').catch(e => console.log(e));

    // Handle all our nulls.
    if (resp == null || resp.data == null)
        console.log("server /api/videos return is null");
    else {
        // Parse our videos.
        resp.data.forEach((v: any) => {
            // Trim description if needed.
            if (v.description.length > maxcharsdescriptionfield) {
                v.description = v.description.substring(0, maxcharsdescriptionfield) + " ...";
            }

            // Add it to our array
            Videos.push(new Video(v));
        });
    }
    
    // Send back the resulting videos.
    return Promise.resolve(Videos);
}

// Vue class for keeping state of the videos.
export default Vue.extend({
    data() {
        return {
            searchbox_str: "",
            Videos: Array<Video>()
        }
    },

    // Manually attaching functions to watchers of data.
    watch: {
        // Searchbox updater.
        searchbox_str (s: string) {
            if (s.trim().length > 0){
                var v = _.debounce((s) => {
                    search_videos(s).then(e => this.Videos = e);
                })
                v(s);
            } else {
                get_videos().then(e => this.Videos = e );
            }
        }
    },

    // Ugh, vue doesn't have async support for computed, wow ...
    mounted() { get_videos().then(e => this.Videos = e ); }
});
</script>

<style scoped>
    .ytcard {
        border-bottom-left-radius: 10px;
        border-bottom-right-radius: 10px;
        background-color:#ddd9d4;
        margin: 6px 2px 6px;
    }

    .description {
        padding: 7px 5px 7px;
    }

    .descriptiontitle {
        font-size: 14px;
        padding-bottom:10px;
    }

    .descriptionchannel {
        font-size: 10px;
        text-align: right;
    }

    .searchbox {
        font-size: 1.2em;
        max-width: 70em;
        margin-left: auto;
        margin-right: auto;
        margin-top: 2em;
    }
</style>
