DaennyOfficial / DBNA UserDistance

// ==UserScript==
// @name         DBNA UserDistance
// @namespace    http://tampermonkey.net/
// @version      0.1.1
// @description  Shows the distance and an estimate travel time on the profile of a DBNA user 
// @author       Daenny
// @match        https://mein.dbna.de/*
// @grant        none
// @license     MIT
// ==/UserScript==

DBNA = {};
DBNA.UserDistance = function () {
    var settings = {
        googleMapsApiKey: '',
        fromCity: ''
    };
    var pageFunctions = {
        rating: insertDistanceOnRatingPage
    };

    this.handleRequest = function (pageFullUrl) {
        //["http://mein.dbna.de/index.php?page=index", "mein", "index.php?page=index"]
        var pageUrlMatch = /https:\/\/([a-z]+).dbna.de\/(.*$)/.exec(pageFullUrl);
        var isDbnaUrl = pageUrlMatch !== null && pageUrlMatch.length == 3;
        if (!isDbnaUrl)
            return;

        var subdomain = pageUrlMatch[1];
        var urlRessource = pageUrlMatch[2];
        var pageNameMatch = /\.php\?page=([a-z]+)/.exec(urlRessource);
        var pageName = (pageNameMatch != null ? pageNameMatch[1] : null);

        if (pageName != null) {
            var pageFunctionKeys = Object.keys(pageFunctions);
            if ($.inArray(pageName, pageFunctionKeys) > -1) {
                doGlobalActionsOnAllHandledPages(function () {
                    pageFunctions[pageName]();
                });
            }
        } else {
            // Steckbrief
            if (urlRessource.startsWith('kurzsteckbrief.php')) {
                doGlobalActionsOnAllHandledPages(function () {
                    insertDistanceOnProfilePage();
                });
            }
        }
    };

    function doGlobalActionsOnAllHandledPages(onGlobalActionsDone) {
        var settingsAreLoaded = loadSettings();
        if (!settingsAreLoaded)
            return;

        // Font Awesome laden
        loadCssFile('https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css');

        // Google Maps Api
        var googleMapsScriptUrl = 'https://maps.googleapis.com/maps/api/js?key=' + settings.googleMapsApiKey + '&signed_in=true&libraries=places';
        $.getScript(googleMapsScriptUrl, function () {
            onGlobalActionsDone();
        });
    }

    function googleMapsResponseToHtml(googleMapsResponseFirstElement) {
        var distanceText = googleMapsResponseFirstElement['distance']['text'];
        var durationText = googleMapsResponseFirstElement['duration']['text'];

        var color;
        var rawDistanceKm = parseInt(googleMapsResponseFirstElement['distance']['value']) / 1000;
        if (rawDistanceKm <= 50)
            color = 'green';
        else if (rawDistanceKm > 50 && rawDistanceKm < 90)
            color = 'orange';
        else
            color = 'red';

        var distanceHtml = '<div><i class="fa fa-car" aria-hidden="true"></i> ' + distanceText + '</div>';
        var durationHtml = '<div><i class="fa fa-clock-o" aria-hidden="true" style="margin-right: 6px;margin-left: 2px;"></i>' + durationText + '</div>';
        return '<div style="color:' + color + ';font-weight:bold;font-style:normal;">' + distanceHtml + durationHtml + '</div>';
    }

    function calculateDistanceAndDuration(fromCity, toCity, onDistanceCalculated, onError) {
        var service = new google.maps.DistanceMatrixService();
        service.getDistanceMatrix({
            origins: [fromCity],
            destinations: [toCity],
            travelMode: google.maps.TravelMode.DRIVING,
            unitSystem: google.maps.UnitSystem.METRIC,
            avoidHighways: false,
            avoidTolls: false
        }, function (response, status) {
            if (status == google.maps.DistanceMatrixStatus.OK && response.rows[0].elements[0].status != "ZERO_RESULTS") {
                var firstElement = response['rows'][0]['elements'][0];
                onDistanceCalculated(firstElement);
            } else {
                onError();
            }
        });
    }

    function insertDistanceOnRatingPage() {
        showSettingsPage();
        var lastVoteUserLocation = $('.cboxcard-text em').html();
        calculateDistanceAndDuration(settings.fromCity, lastVoteUserLocation, function (googleMapsFirstElement) {
            var html = googleMapsResponseToHtml(googleMapsFirstElement);
            $('.cboxcard-text em').append(html);
        });
    }

    function insertDistanceOnProfilePage() {
        var userLocationElement = $('.dbnatooltipp:not(#herzen)');
        var userLocationString = userLocationElement.html();

        calculateDistanceAndDuration(settings.fromCity, userLocationString, function (googleMapsFirstElement) {
            var html = googleMapsResponseToHtml(googleMapsFirstElement);
            userLocationElement.append(html);
        });
    }

    function showSettingsPage() {
        if (settings.googleMapsApiKey.length > 0 && settings.fromCity.length > 0)
            return;

        loadCssFile('https://cdnjs.cloudflare.com/ajax/libs/vex-js/3.0.0/css/vex.min.css');
        loadCssFile('https://cdnjs.cloudflare.com/ajax/libs/vex-js/3.0.0/css/vex-theme-os.min.css');

        $.getScript('https://cdnjs.cloudflare.com/ajax/libs/vex-js/3.0.0/js/vex.combined.min.js', function () {
            vex.defaultOptions.className = 'vex-theme-os';

            vex.dialog.open({
                message: 'DBNA-Distance Einstellungen',
                input: [
                    '<input name="googleMapsApiKey" type="text" placeholder="Google Maps API Key" value="' + settings.googleMapsApiKey + '" required />',
                    '<input name="fromCity" type="text" placeholder="Dein Wohnort (Startort)" value="' + settings.fromCity + '" required />'
                ].join(''),
                buttons: [
                    $.extend({}, vex.dialog.buttons.YES, { text: 'Speichern' }),
                    $.extend({}, vex.dialog.buttons.NO, { text: 'Abbrechen' })
                ],
                callback: function (data) {
                    if (data) {
                        settings.googleMapsApiKey = data.googleMapsApiKey;
                        settings.fromCity = data.fromCity;
                        saveSettings();
                        window.location.reload();
                    }
                }
            });

        });
    }

    function loadSettings() {
        var serializedSettings = localStorage.getItem('dbnaTampermonkeySettings');
        var settingsArePresent = (serializedSettings !== null && serializedSettings.length > 0);

        if (settingsArePresent) {
            settings = JSON.parse(serializedSettings);
        } else {
            showSettingsPage();
        }

        return settingsArePresent;
    }

    function saveSettings() {
        var serializedSettings = JSON.stringify(settings);
        localStorage.setItem('dbnaTampermonkeySettings', serializedSettings);
    }

    function loadCssFile(cssFilePath) {
        var head = document.getElementsByTagName('head')[0];
        var link = document.createElement('link');

        link.rel = 'stylesheet';
        link.type = 'text/css';
        link.href = cssFilePath;
        link.media = 'all';
        head.appendChild(link);
    }
};

(function () {
    'use strict';

    var userDistance = new DBNA.UserDistance();
    userDistance.handleRequest(window.location.href);
})();