/* global options, settings, updateToolTips, bindClickToList */
'use strict';

// Global DEBUG variable
var DEBUG = false;

var UST = window.UST ? window.UST : window.UST = {};

/***
 Ajax requests sent to the server
***/
UST.API = (function () {

    //In case anything goes wrong
    function catchFail () {
        // Only display the message if no other message is visible
        if(jQuery('.alertify').length > 0) return;
        
        alertify.alert("Something went wrong on the server-side. Please try again!");
    }

    // Display list of resolutions window sizes available in db
    // Returns: Promise
    // The .fail() is treated in this function
    function getResolutions () {

        if (options.url === undefined) {
            alertify.alert('No pages saved in the database. Database may be empty.');
            return;
        }

        return jQuery.ajax({
            type: 'POST',
            dataType: "json",
            url: 'helpers/getResolutions.php',
            data: { url: options.url, domain: options.domain },
            beforeSend: function (x) {
                if (x && x.overrideMimeType) {
                    x.overrideMimeType("application/j-son;charset=UTF-8");
                }
            }
        }).fail((data) => {
            alertify.alert(data.responseText);
        });
    }

    // Display list of pages available in db
    function getPages () {
        return jQuery.ajax({
            type: 'POST',
            dataType: "json",
            url: 'helpers/getPages.php',
            data: { domain: options.domain },
            beforeSend: function (x) {
                if (x && x.overrideMimeType) {
                    x.overrideMimeType("application/j-son;charset=UTF-8");
                }
            }
        }).fail((data) => {
            if (data.responseText.indexOf('login') !== -1)
                window.location = 'login.php';
            else
                alertify.alert("Could not load pages list from db." + data.responseText);
        });
    }

    // Delete records that go over the specified limit
    function limitRecordNumber () {
        jQuery.ajax({
            type: 'POST',
            dataType: "json",
            url: 'helpers/limitRecordNumber.php',
            data: {
                domain: options.domain
            },
            beforeSend: function (x) {
                if (x && x.overrideMimeType) {
                    x.overrideMimeType("application/j-son;charset=UTF-8");
                }
            },
            success: function () {},
            error: function (data) {
                alertify.alert(data.responseText);
            }
        });
    }

    // Set the max number of recordings saved for this domain
    function setRecordLimit (domain, limit) {
        jQuery.ajax({
            type: 'POST',
            url: 'helpers/setRecordLimit.php',
            data: {
                limit: limit,
                domain: domain
            },
            beforeSend: function (x) {
                if (x && x.overrideMimeType) {
                    x.overrideMimeType("application/j-son;charset=UTF-8");
                }
            },
            success: function () {},
            error: function (data) {
                alertify.alert(data.responseText);
            }
        });
    }
    
    function getUtcOffset() {
        return jQuery.get('helpers/getUTCMinutesOffset.php')
            .fail(function (data) {
                alertify.alert(data.responseText);
            });
    }
    //Get the max number of recordings saved for this domain
    function getRecordLimit(domain, callback, elIndex) {
        jQuery.post("helpers/getRecordLimit.php", { domain: domain })
            .done(function (data) {
                callback(elIndex, data);
            })
            .fail(function (data) {
                alertify.alert(data.responseText);
            });
    }

    
    //Get available clients
    function populateClientsList (from) {
        // We don't need this in direct playback mode
        if(window.DIRECT_PLAYBACK) return;

        // Filters
        var take = +jQuery('#numberFilter select').val();
        var startDate = jQuery('#rangeFilter input[name="from"]').val();
        var endDate = jQuery('#rangeFilter input[name="to"]').val();
        var tagFilters = jQuery('.tagFilterElement .value').map(function () {
            return jQuery(this).text();
        }).get();

        // Auxilliary arrays
        var browserCodes = ['chrome', 'opera', 'msie', 'firefox', 'mozilla', 'safari', 'mobile'];
        var browserNames = ['Google Chrome', 'Opera', 'Internet Explorer', 'Mozilla Firefox', 'Mozilla Firefox', 'Safari', 'Mobile Device'];
        var browserImages = ['chrome.png', 'opera.png', 'ie.png', 'firefox.png', 'firefox.png', 'safari.png', 'mobile.png'];

        jQuery.ajax({
            type: 'POST',
            dataType: "json",
            url: 'helpers/getClients.php',
            data: { 
                from: from, 
                take: take,
                domain: options.domain,
                startDate: startDate,
                endDate: endDate,
                tagFilters: tagFilters,
                order: localStorage.order 
            },
            beforeSend: function (x) {
                if (x && x.overrideMimeType) {
                    x.overrideMimeType("application/j-son;charset=UTF-8");
                }
            },
            success: function (data) {

                var $recordListTable = jQuery('#recordList table');

                jQuery('tr:has(td)', $recordListTable).remove();

                if (data === null || data.clients.length === 0) {
                    $recordListTable.append('<tr><td colspan="6"><h3>Database is empty.</h3></td></tr>');
                    return;
                }

                var cnt = data.count;
                data = data.clients;

                var now = new Date();
                var localTimezoneOffset = now.getTimezoneOffset();
                let timezoneOffset = -localTimezoneOffset - localStorage.serverUtcOffset;

                for (var v in data) {
                    var $tr = jQuery('<tr data-id="' + data[v].clientid + '"></tr>');

                    // If ID is null means there are no recordings, set correct number to 0
                    if(data[v].recordid == null) data[v].nr = 0;
                    if(data[v].referrer == null) data[v].referrer = '';

                    // Make sure value is number
                    data[v].nr = +data[v].nr;

                    // Remove year and seconds from date
                    var localDate = new Date(data[v].date);
                    localDate.setMinutes(localDate.getMinutes() + timezoneOffset);
                    // Add month name and day
                    data[v].date = localDate.getDate() + ' ' + localDate.toLocaleString("en", { month: "short" });
                    // Add hour and minutes (locale string without seconds)
                    data[v].date += ' <b>' + localDate.toLocaleTimeString().replace(/:\d+ /, ' ') + '</b>';

                    var n = 0;
                    var referrerMaxLength = 15;
                    for (var i in data[v]) {

                        // Do something else at column 8 (buttons column)
                        if (++n > 7)
                            break;

                        var td = jQuery('<td class="' + i + '"></td>');
                        // Use .text instead of .html to prevent XSS
                        td.text(data[v][i]);
                        $tr.append(td);

                        switch (i) {
                            case 'date':
                                // Wrap hour in bold tags
                                td.html(data[v].date);

                                // Add full date as title in case user wants to know seconds/year
                                td.attr('title', localDate.toLocaleString());
                                break;

                            // Made referrer shorter and make it a link
                            case 'referrer':
                                var referrerURL = data[v].referrer;
                                if(!referrerURL) continue;
                                // Quick XSS fixx
                                referrerURL = referrerURL.replace('javascript:', '');
                                referrerURL = referrerURL.replace('<', '&lt;');

                                var niceURL = data[v].referrer.match(/^(?:https?:\/\/)?(?:[^@\/\n]+@)?(?:www\.)?([^:\/\n]+)/im)[1];
                                if(!niceURL) continue;

                                if(niceURL.length > referrerMaxLength) {
                                    niceURL = niceURL.substring(0, referrerMaxLength - 3) + '...';
                                }

                                var $a = jQuery('<a target="_blank" href="' + referrerURL + '" class=""></span>');
                                $a.attr('title', "Open in new tab: <b>" + referrerURL + "</b>");
                                $a.text(niceURL);
                                td.html($a);
                                break;

                            // Wrap tags in spans
                            case 'tags':
                                td.html('<span class="plus addTag" data-id ="' + data[v].clientid + '">+</span>');
                                td.attr('title', '<b>Click</b> to add this tag filter. <br/> <b>Right click</b> a tag to remove it');
                                var tags = data[v][i];
                                for(var idx in tags) {
                                    var span = jQuery('<span class="tag"></span>');
                                    span.text(tags[idx]);
                                    td.append(span);
                                }
                                break;

                            // Add placeholder for flag
                            case 'ip':

                                var newIP = data[v].ip;

                                if (settings.censorIP === true) {
                                    newIP = '*' + data[v].ip.slice(-7);
                                }

                                // Check first if flag image is cached
                                if (localStorage['c' + data[v].ip] !== undefined) {
                                    var countryCode = localStorage['c' + data[v].ip];
                                    var titleInfo = countryCode;

                                    // If we have countryCode|titleInfo 
                                    if(countryCode.length > 2) {
                                        var parts = countryCode.split('|');
                                        countryCode = parts[0];
                                        titleInfo = parts[1];
                                    }
                                    td.html('<img width="16px" height="11px" src="images/flags/' + countryCode + '.png" title="' + titleInfo + '"/> ' + newIP);
                                }
                                else {
                                    // By default show the N/A flag
                                    td.html('<img width="16px" height="11px" src="images/flags/xx.png"/> ' + newIP);

                                    // Timeout delay so that the flag api doesn't break
                                    (function (ip, td, newIP) {
                                        setTimeout(function () { addCountryFlag(ip, td, newIP); }, 300 * v);
                                    })(data[v].ip, td, newIP);
                                }
                                break;

                            // Show number of records for client
                            case 'pageHistory':

                                td.empty();
                                td.append(data[v].nr + ' page' + (data[v].nr !== 1 ? 's' : ''));

                                // Compute the time spent in hours, minutes, seconds
                                var timeSpentString = '';
                                var ts = data[v].timeSpent;
                                if(ts > 3600) {
                                    var hours = ts / 3600 | 0;
                                    timeSpentString += hours + 'h ';
                                    ts -= hours * 3600;
                                }

                                if(ts > 60) {
                                    var mins = ts / 60 | 0;
                                    timeSpentString += mins + 'm ';
                                    ts -= mins * 60;
                                }

                                timeSpentString += ts + 's';

                                td.append(' in ' + timeSpentString + ':');

                                var pageList = data[v][i].split(' ');

                                for(var index in pageList) {

                                    var pageName = pageList[index];

                                    // Remove page extension
                                    // Consider that extensions are max 5 characters
                                    var dotPosition = pageName.lastIndexOf('.');
                                    if(dotPosition !== -1 && pageName.length - dotPosition - 1 < 5) {
                                        pageName = pageName.slice(0, pageName.lastIndexOf('.'));
                                    }

                                    pageList[index] = '<div class="pageEntry">' + pageName + '</div>';
                                    td.append(pageList[index]);
                                }

                                td.attr('width', '50%');
                                break;
                        }
                    }

                    // Disable the button if it has 0 recordings
                    var disabled = data[v].nr === 0 ? ' disabled title="No movements were recorded. Client may have left immediately." ' : '';

                    // Get first page visited
                    var firstPage = data[v].pageHistory;
                    if(data[v].pageHistory.indexOf(' ') !== -1) {
                        firstPage = data[v].pageHistory.split(' ')[0];
                    }

                    // Watched class
                    var watchedClass = data[v].watched && data[v].watched !== '0' ? 'watched' : '';
                    
                    // Display the play button
                    var recordColumn = jQuery(
                        `<td class="playButton ${watchedClass}">
                            <button 
                            data-recordid="${data[v].recordid}" 
                            data-page="${firstPage}" 
                            data-resolution="${data[v].resolution}"
                            ${disabled}>Play
                            </button>
                        </td>`);

                    var shareButton = jQuery('<img class="shareRecordButton" src="images/icons/share.png" title="Direct playback share link."/>');
                    
                    recordColumn.append(shareButton);
                    $tr.append(recordColumn);

                    // Display browser icon
                    var browserEl = jQuery('td.browser', $tr).get(0);
                    var br = browserEl.innerText;
                    var browserVersion = br.split(' ').pop();
                    for(var name in browserCodes) {
                        var code = browserCodes[name];
                        if(br.indexOf(code) !== -1) {
                            // Don't show the 'mobile' text next to the mobile icon
                            if(code === 'mobile') browserVersion = '';

                            var d = '<img src="images/icons/' + browserImages[name] + '" title="' + browserNames[name] + ' ' + browserVersion + '"/>';
                            d += '<span>' + browserVersion + '</span>';

                            browserEl.innerHTML = d;
                            break;
                        }
                    }

                    $recordListTable.append($tr);
                }

                // Display pagination
                var $pagination = jQuery('#pagination');
                $pagination.html('');
                if (cnt) {
                    var totalPages = (cnt / take) + (cnt % take !== 0);
                    var currentPage = (from / take) + 1;

                    // Display each page, also select the current page
                    for (var i = 1; i <= totalPages; ++i) {
                        var selected = i === currentPage ? "selected" : "";
                        $pagination.append('<span class="' + selected + '">' + i + '</span>');
                    }
                }

                updateToolTips('#recordList');
                bindClickToList();
            },
            error: function (data) {
                alertify.alert(data.responseText);
                console.log(data.responseText);
            }
        });
    }

    // Get country name by ip
    function addCountryFlag (ip, td, newIP) {

        // Use local proxy for IPV6 only
        var url = ip.length > 15 ? 'helpers/getCountry.php' : ('//geoip.nekudo.com/api/' + ip);

        jQuery.ajax({
            type: 'POST',
            url: url,
            data: { ip: ip },
            success: function (data) {
                var titleInfo = '-';

                // Try converting JSON data from string if not already converted
                // eslint-disable-next-line
                try { data = JSON.parse(data); } catch(e) {}

                // We got the data from freegeoip
                if (data.country) {
                    titleInfo = data.city + ', ' + data.country.name;
                    data = data.country.code;
                // We got the data from ipinfodb
                } else if(data.countryName) {

                    titleInfo = data.cityName + ', ' + data.countryName;
                    data = data.countryCode;
                }

                if(data === 'ZZ' || !data) data = 'xx';

                if (data.length === 2) {
                    td.html('<img width="16px" height="11px" src="images/flags/' 
                        + data.toLowerCase() + '.png" title="' + titleInfo + '"/> ' + newIP);
                    if (data.toLowerCase() !== 'xx')
                        // Separate country code from titleInfo using |
                        localStorage.setItem('c' + ip, data.toLowerCase() + '|' + titleInfo);
                }
            },
            error: function () {}
        });
    }

    // Get next record after record with ID = id
    function getNextRecord (id) {
        return jQuery.ajax({
            type: 'POST',
            dataType: "json",
            url: 'helpers/getNextRecord.php',
            data: {
                id: id, 
                domain: options.domain 
            },
            beforeSend: function (x) {
                if (x && x.overrideMimeType) {
                    x.overrideMimeType("application/j-son;charset=UTF-8");
                }
            }
        }).fail(data => {
            alertify.alert(data.responseText);
        });
    }

    // Load record data from recordID
    function getRecord (id) {
        // If we are in direct playback mode only try go get full record data
        if(window.DIRECT_PLAYBACK && options.what !== 'record') return;

        options.lastid = id;

        return jQuery.ajax({
            type: "POST",
            dataType: "text",
            data: {
                recordid: id,
                page: options.url,
                resolution: options.resolution,
                what: options.what,
                directPlayback: window.DIRECT_PLAYBACK,
                clientid: window.CLIENT_ID,
                key: window.PUBLIC_KEY
            },
            url: 'getData.php',
            beforeSend: function (x) {
                if (x && x.overrideMimeType) {
                    x.overrideMimeType("application/j-son;charset=UTF-8");
                }
            }
        }).fail(data => {
            alertify.alert("Could not load data!" + data.responseText);
        });
    }

    // Load all recorded pages based on clientID
    function getRecordList (clientID) {
        jQuery.ajax({
            type: "POST",
            dataType: "json",
            data: { clientID: clientID },
            url: 'helpers/getRecordList.php',
            beforeSend: function (x) {
                if (x && x.overrideMimeType) {
                    x.overrideMimeType("application/j-son;charset=UTF-8");
                }
            },
            success: function (data) {
                UST.Records.setRecordList(data);
            },
            error: function (data) {
                alertify.alert("Could not load data!" + data.responseText);
            }
        });
    }

    function loadHeatmapData () {
        DEBUG && console.log("loadHeatmapData");

        return jQuery.ajax({
            type: "POST",
            dataType: "json",
            data: {
                page: options.url, resolution: options.resolution,
                what: options.what, domain: options.domain
            },
            url: 'getData.php',
            beforeSend: function (x) {
                jQuery('#loading').text("Retrieving data from database...");
                if (x && x.overrideMimeType) {
                    x.overrideMimeType("application/j-son;charset=UTF-8");
                }
            }
        }).fail(data => {
            console.log(data);
            if (data.responseText.indexOf('login') !== -1)
                window.location = 'login.php';
            else
                alertify.alert("Could not load heatmap data." + data.responseText);
        });
    }

    function addTag (clientID, tag, cb) {
        if(typeof tag === 'undefined' || tag.length === 0) {
            console.log("Tag cannot be empty!");
            return 0;
        }

        jQuery.post('addTag.php', {
            clientID: clientID,
            tagContent: tag
        }).done(function (data) {
            if(data !== '') {
                alertify.error("Tag was not added. You can not have duplicate tags for the same user.");
                console.log(data);
                return;    
            }

            DEBUG && console.log('Tag ' + tag + 'added');
            if(typeof cb === 'function') cb();
        }).fail(function (data) {
            alertify.error("Something went wrong. Tag was not added.");
            console.log(data.responseText);
        });

        return 1;
    }

    function removeTag (clientID, tag, cb) {
        if(typeof tag === 'undefined' || tag.length === 0) {
            console.log("Tag cannot be empty!");
            return 0;
        }

        jQuery.post('helpers/removeTag.php', {
            clientID: clientID,
            tagContent: tag
        }).done(function (data) {
            if(data !== '') {
                alertify.error("Tag was not removed.");
                console.log(data);
                return;    
            }

            DEBUG && console.log('Tag ' + tag + 'removed');
            if(typeof cb === 'function') cb();

        }).fail(function (data) {
            alertify.error("Something went wrong. Tag was not removed.");
            console.log(data.responseText);
        });

        return 1;
    }

    function getShareToken (clientID) {
        return jQuery.post('helpers/sharing/getPublicRecordingToken.php', {
            clientID: clientID
        }).fail(function (data) {
            alertify.error("Something went wrong. Tag was not removed.");
            console.log(data.responseText);
        });
    }

    function setRecordingWatched (clientID) {
        return jQuery.post('helpers/recordings/setWatched.php', {
            clientID
        }).then(data => {
            if(!data) return;
            throw new Error(data);
        }).fail(data => {
            alertify.alert("Recording could not be marked as watched.");
            console.log(data.responseText || data);
        });
    }

    // Delete a single record (page) from a client session
    function deleteRecord (id) {

        if (id > 0) {
            jQuery.post('helpers/deleteRecord.php', { recordid: id })
                .done(function () {
                    alertify.alert('Record deleted!');
                })
                .fail(function (data) {
                    console.log(data);
                    alertify.alert("Could not delete record!" + data.responseText);
                });
        }
        else {
            alertify.alert('Incorect id format.');
            return 0;
        }
    }

    // Delete client including all data related to it
    function deleteClient (clientID, el) {
        jQuery.post('helpers/deleteClient.php', { clientID: clientID })
            .done(function () {
                jQuery(el).slideUp(200, function () { jQuery(this).remove(); });
            })
            .fail(function (data) {
                console.log(data);
                alertify.alert("Could not delete client!" + data.responseText);
            });
    }

    function cleanDataForDomain (domain) {
        jQuery.post('helpers/cleanDatabase.php', { domain: domain }, function (data) {
            if (data === '') alertify.alert('All data stored in the database has been deleted.');
            else alertify.alert("Error: " + data);
            window.location.reload();
        });
    }

    function deleteZeroRecords (domain) {
        jQuery.post('helpers/deleteZeroRecords.php', { domain: domain }, function (data) {
            if (data === '')
                alertify.alert('Sessions with 0 data have been deleted.');
            else alertify.alert("Error: " + data);
            window.location.reload();
        });
    }

    //Get users list
    function getUsersList (callback) {

        jQuery.getJSON('helpers/users/getUserList.php', function (data) {
            callback(data);
        });
    }

    // Set user name or level
    function setUserData (dataType, value, id, shouldLogout) {

        //Match variable name with database field name
        if(dataType.indexOf('name') !== -1)
            dataType = 'name';

        jQuery.post('helpers/users/setUserData.php', { dataType: dataType, value: value, userId: id })
            .done(function (data) {
                if (data !== '') {
                    alertify.alert(data);
                } else if (shouldLogout) {
                    window.location = 'helpers/users/logout.php';
                }
            }).fail(catchFail);
    }

    // Add or remove domain access for user
    function changeUserAccess (type, domain, userid) {
        jQuery.post('helpers/users/changeAccess.php', { type: type, domain: domain, userid: userid })
            .done(function (data) {
                if (data !== '') alertify.alert(data); // Show error message
                else location.reload(); // Reload the page if login was ok
            })
            .fail(catchFail);
    }

    // Add new user to the db
    function addUser (name, pass) {
        jQuery.post('helpers/users/addUser.php', { name: name, pass: pass })
            .done(function (data) {
                if (data !== '')
                    alertify.alert(data);
                else
                    //Reload the page
                    location.reload();
            })
            .fail(catchFail);
    }

    // Delete a user from the db, based on id
    function deleteUser (userId) {
        jQuery.post('helpers/users/deleteUser.php', { id: userId })
            .done(function (data) {
                if (data !== '')
                    alertify.alert(data);
                else
                    //Reload the page
                    location.reload();
            })
            .fail(catchFail);
    }

    // Index page statistics
    function getSummaryStats (domain, cb) {
        jQuery.post('helpers/statistics/getSummaryStats.php', { domain: domain })
            .then(cb)
            .fail(catchFail);
    }

    // Return public aliases
    return {
        getPages: getPages,
        populateClientsList: populateClientsList,
        loadHeatmapData: loadHeatmapData,
        getResolutions: getResolutions,
        limitRecordNumber: limitRecordNumber,
        setRecordLimit: setRecordLimit,
        getRecordLimit: getRecordLimit,
        getRecord: getRecord,
        getRecordList: getRecordList,
        getNextRecord: getNextRecord,
        setRecordingWatched: setRecordingWatched,
        deleteClient: deleteClient,
        cleanDataForDomain: cleanDataForDomain,
        deleteZeroRecords: deleteZeroRecords,
        deleteRecord: deleteRecord,
        getUsersList: getUsersList,
        setUserData: setUserData,
        changeUserAccess: changeUserAccess,
        addUser: addUser,
        deleteUser: deleteUser,
        addTag: addTag,
        removeTag: removeTag,
        getShareToken: getShareToken,
        getSummaryStats: getSummaryStats,
        getUtcOffset: getUtcOffset
    };  
}());
