/**
 * Clientside Script of the Netflix Stats Generator
 * @author Marvin Borner
 * @copyright Marvin Borner 2018
 */

$(function () {
    const CookieInput = $(".CookieInput");
    let NetflixJson;

    CookieInput.keyup(function (e) {
        if (e.keyCode === 13) {
            $.ajax({
                url: "assets/php/getNetflixJson.php",
                data: {
                    "Cookie": CookieInput.val()
                },
                type: "POST",
            }).done(function (response) {
                CookieInput.val("");
                CookieInput.hide();
                $(".Main").fadeIn();
                AnalyzeData(response);
            });
        }
    });

    /**
     * Analyzes the Netflix data JSON response
     * @param {JSON} JsonResponse 
     */
    function AnalyzeData(JsonResponse) {
        /**
         * @example response of a series:
         *  bookmark: 0
         *  country: "DE"
         *  date: 1529338765489
         *  dateStr: "18.06.18"
         *  deviceType: 1481
         *  duration: 3302
         *  episodeTitle: "Folge 13"
         *  estRating: "50"
         *  index: 0
         *  movieID: 80205354
         *  seasonDescriptor: "Teil 1"
         *  series: 80192098
         *  seriesTitle: "Haus des Geldes"
         *  title: "Teil 1: \"Folge 13\""
         *  topNodeId: "80192098"
         *  videoTitle: "Folge 13"
         * 
         *  @example response of a movie:
         *  bookmark: 7771
         *  country: "DE"
         *  date: 1476477258019
         *  dateStr: "14.10.16"
         *  deviceType: 1193
         *  duration: 8160
         *  estRating: "30"
         *  index: 916
         *  movieID: 20557937
         *  title: "Matrix"
         *  topNodeId: "20557937"
         *  videoTitle: "Matrix"
         */
        NetflixJson = JSON.parse(JsonResponse);
        console.log(NetflixJson);
        let EveryWatched = [];
        let IndividualTitles = [];
        let IndividualSeries = [];
        let IndividualMovies = [];
        let AverageWatchTimes = [];

        NetflixJson.forEach(function (item, pageKey) {
            item.forEach(function (eachItem, ItemNumber) {
                if ("seriesTitle" in eachItem) { // is series
                    const CurrentTitle = NetflixJson[pageKey][ItemNumber].seriesTitle;
                    EveryWatched.push(CurrentTitle);
                    if (IndividualSeries.indexOf(CurrentTitle) === -1 && CurrentTitle !== undefined) { // only if not already crawled -> individualism
                        IndividualSeries.push(CurrentTitle);
                        IndividualTitles.push(CurrentTitle);
                    }
                } else { // is movie
                    const CurrentTitle = NetflixJson[pageKey][ItemNumber].videoTitle;
                    EveryWatched.push(CurrentTitle);
                    if (IndividualMovies.indexOf(CurrentTitle) === -1 && CurrentTitle !== undefined) { // only if not already crawled -> individualism
                        IndividualMovies.push(CurrentTitle);
                        IndividualTitles.push(CurrentTitle);
                    }
                }

                // get watch time
                const DayTimeInSeconds = new Date(NetflixJson[pageKey][ItemNumber].date * 1000);
                const DayTimeInHours = DayTimeInSeconds.getHours();
                AverageWatchTimes.push(DayTimeInHours);
            });
        });

        const TotalSeriesWatched = IndividualSeries.length;

        // Calculate watch time occurrence (average times in which the user watches sth.)
        let AverageWatchTimeOccurrence = [];
        const WatchTimeOccurrenceCounter = new Map([...new Set(AverageWatchTimes)].map(
            x => [x, AverageWatchTimes.filter(y => y === x).length]
        ));
        for (let i = 0; i < 24; i++) {
            AverageWatchTimeOccurrence.push(WatchTimeOccurrenceCounter.get(i));
        }

        // Calculate the most watched series/movies
        let TitleCount = [];
        const UnsortedTitleOccurrenceCounter = EveryWatched.reduce((prev, curr) => (prev[curr] = ++prev[curr] || 1, prev), {});
        const SortedTitleOccurrenceCounter = sortObject(UnsortedTitleOccurrenceCounter);
        const TopSeries = Object.keys(SortedTitleOccurrenceCounter)[Object.keys(SortedTitleOccurrenceCounter).length - 1];
        RenderTopSeries(TopSeries);

        // log
        console.table(IndividualTitles);
        console.table(IndividualSeries);
        console.table(IndividualMovies);
        console.table(AverageWatchTimeOccurrence);
        console.table(SortedTitleOccurrenceCounter);

        RenderDayTimeChart(AverageWatchTimeOccurrence);
        RenderMostWatchedChart(SortedTitleOccurrenceCounter);
    }

    /**
     * Renders the day time chart
     * @param {Array} AverageWatchTimeOccurrenceArray 
     */
    function RenderDayTimeChart(AverageWatchTimeOccurrenceArray) {
        var randomColorGenerator = function () {
            return '#' + (Math.random().toString(16) + '0000000').slice(2, 8);
        };

        // Render day time chart
        const WatchTimeChartElement = document.getElementById("WatchTimeChart").getContext("2d");
        const WatchTimeChart = new Chart(WatchTimeChartElement, {
            type: 'line',
            data: {
                labels: ["12am", "1am", "2am", "3am", "4am", "5am", "6am", "7am", "8am", "9am", "10am", "11am", "12pm", "1pm", "2pm", "3pm", "4pm", "5pm", "6pm", "7pm", "8pm", "9pm", "10pm", "11pm"],
                datasets: [{
                    label: "Watches at daytime",
                    borderColor: "rgb(255, 99, 132)",
                    cubicInterpolationMode: "monotone",
                    pointRadius: 0,
                    pointHitRadius: 15,
                    data: AverageWatchTimeOccurrenceArray
                }]
            },
            options: {
                scales: {
                    yAxes: [{
                        ticks: {
                            display: false
                        },
                        gridLines: {
                            zeroLineColor: 'transparent',
                            zeroLineWidth: 2,
                            drawTicks: false,
                            drawBorder: false,
                            color: 'transparent'
                        }
                    }],
                    xAxes: [{
                        gridLines: {
                            zeroLineColor: 'rgba(255, 255, 255, 0.25)',
                            display: true,
                            drawBorder: false,
                            color: 'rgba(255, 255, 255, 0.25)'
                        }
                    }]
                },
                tension: 1
            }
        });
    }

    /**
     * Renders the "most watched series" doughnut chart
     * @param {Object} TitleOccurrenceCounterObject 
     */
    function RenderMostWatchedChart(TitleOccurrenceCounterObject) {
        // Render and calculate most watched chart

        const GenerateRandomColorArray = function () {
            let RandomColorArray = [];
            const Generate = function () {
                var letters = '0123456789ABCDEF'.split('');
                var color = '#';
                for (var i = 0; i < 6; i++) {
                    color += letters[Math.floor(Math.random() * 16)];
                }
                return color;
            };
            for (var key in TitleOccurrenceCounterObject) {
                RandomColorArray.push(Generate());
            }
            return RandomColorArray;
        };

        const MostWatchedChartElement = document.getElementById("MostWatchedChart").getContext("2d");
        var MostWatchedChartData = {
            labels: [],
            datasets: [{
                label: "Most watched",
                backgroundColor: GenerateRandomColorArray(),
                data: []
            }]
        };
        Chart.pluginService.register({
            beforeInit: function (chart) {
                var data = chart.config.data;
                for (var key in TitleOccurrenceCounterObject) {
                    if (TitleOccurrenceCounterObject.hasOwnProperty(key)) {
                        if (TitleOccurrenceCounterObject[key] > 2) {
                            data.labels.push(key);
                            data.datasets[0].data.push(TitleOccurrenceCounterObject[key]);
                        }
                    }
                }
            }
        });
        var MostWatchedChart = new Chart(MostWatchedChartElement, {
            type: 'doughnut',
            data: MostWatchedChartData,
            options: {
                animation: {
                    animateScale: true
                },
                legend: {
                    display: false
                }
            }
        });
    }

    /**
     * Renders the top series in the DOM
     * @param {String} Title 
     */
    function RenderTopSeries(Title) {
        const InformationJSON = getTitleInformation(Title, output => {
            return output;
        });
        console.table(InformationJSON);
        // TODO: Write to site/DOM + logging output
    }

    /**
     * Gets an JSON information object of the requested series/movie
     * @param {String} Title 
     */
    function getTitleInformation(Title, handleFunction) {
        $.ajax({
            url: "assets/php/getInformation.php",
            data: {
                "Title": Title
            },
            type: "POST",
        }).done(function (response) {
            handleFunction(JSON.parse(response));
        });
    }

    /**
     * Sorts an js object by value {int}
     * @param {Object} list 
     */
    function sortObject(list) {
        var sortable = [];
        for (var key in list) {
            sortable.push([key, list[key]]);
        }
        sortable.sort(function (a, b) {
            return (a[1] < b[1] ? -1 : (a[1] > b[1] ? 1 : 0));
        });
        var orderedList = {};
        for (var i = 0; i < sortable.length; i++) {
            orderedList[sortable[i][0]] = sortable[i][1];
        }
        return orderedList;
    }
});