import _ from 'lodash'
import React from 'react'
import shallowEqual from 'shallowequal'

window._ = _;
window.React = React;

export var Key = {
    UP: 38,
    DOWN: 40,
    PAGE_UP: 33,
    PAGE_DOWN: 34,
    HOME: 36,
    END: 35,
    LEFT: 37,
    RIGHT: 39,
    ENTER: 13,
    ESC: 27,
    TAB: 9,
    SPACE: 32,
    BACKSPACE: 8,
    SHIFT: 16
};
// Add A-Z
for (var i = 65; i <= 90; i++) {
    Key[String.fromCharCode(i)] = i;
}


export var formatSize = function (bytes) {
    if (bytes === 0)
        return "0";
    var prefix = ["b", "kb", "mb", "gb", "tb"];
    for (var i = 0; i < prefix.length; i++) {
        if (Math.pow(1024, i + 1) > bytes) {
            break;
        }
    }
    var precision;
    if (bytes % Math.pow(1024, i) === 0)
        precision = 0;
    else
        precision = 1;
    return (bytes / Math.pow(1024, i)).toFixed(precision) + prefix[i];
};


export var formatTimeDelta = function (milliseconds) {
    var time = milliseconds;
    var prefix = ["ms", "s", "min", "h"];
    var div = [1000, 60, 60];
    var i = 0;
    while (Math.abs(time) >= div[i] && i < div.length) {
        time = time / div[i];
        i++;
    }
    return Math.round(time) + prefix[i];
};


export var formatTimeStamp = function (seconds) {
    var ts = (new Date(seconds * 1000)).toISOString();
    return ts.replace("T", " ").replace("Z", "");
};

// At some places, we need to sort strings alphabetically descending,
// but we can only provide a key function.
// This beauty "reverses" a JS string.
var end = String.fromCharCode(0xffff);
export function reverseString(s) {
    return String.fromCharCode.apply(String,
            _.map(s.split(""), function (c) {
                return 0xffff - c.charCodeAt(0);
            })
        ) + end;
}

function getCookie(name) {
    var r = document.cookie.match(new RegExp("\\b" + name + "=([^;]*)\\b"));
    return r ? r[1] : undefined;
}
const xsrf = `_xsrf=${getCookie("_xsrf")}`;

export function fetchApi(url, options={}) {
    if (options.method && options.method !== "GET") {
        if (url.indexOf("?") === -1) {
            url += "?" + xsrf;
        } else {
            url += "&" + xsrf;
        }
    }

    return fetch(url, {
        credentials: 'same-origin',
        ...options
    });
}

fetchApi.put = (url, json, options) => fetchApi(
    url,
    {
        method: "PUT",
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(json),
        ...options
    }
)
// deep comparison of two json objects (dicts). arrays are handeled as a single value.
// return: json object including only the changed keys value pairs.
export function getDiff(obj1, obj2) {
    let result = {...obj2};
    for(let key in obj1) {
        if(_.isEqual(obj2[key], obj1[key]))
            result[key] = undefined
        else if(Object.prototype.toString.call(obj2[key]) === '[object Object]' &&
                Object.prototype.toString.call(obj1[key]) === '[object Object]' )
            result[key] = getDiff(obj1[key], obj2[key])
    }
    return result
}

export const pure = renderFn => class extends React.Component {
    static displayName = renderFn.name

    shouldComponentUpdate(nextProps) {
        return !shallowEqual(this.props, nextProps)
    }

    render() {
        return renderFn(this.props)
    }
}