const uuid = () =>
  ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
    ((c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & 15)) >> c / 4).toString(16))


let COUNTER = 0, s
if (localStorage.getItem("session-id") === null) {
  s = [uuid(), 0]
} else {
  s = localStorage.getItem("session-id").split(":");
  s[1] = (parseInt(s[1], 16) + 1).toString(36)
}
const SESSION = s.join(":");
localStorage.setItem("session-id", SESSION);

export function remoteService() {
  return function(url, fn, config) {
    if (config === undefined) config = {};
    if (config.headers === undefined) config.headers = {};

    const execute = function (fn, method, url, query, payload, headers) {
        if (query === undefined) query = {};
        for (var i in query) if (query.hasOwnProperty(i)) {
            var needle = ':'+i;
            if (url.search(needle)>0) {
                url = url.replace(needle, query[i]);
                delete(query[i]);
            }
        }

        config.method = method;

        if (payload !== undefined)
          if (typeof payload === 'string' || payload instanceof String)
            config.body = payload;
          else config.body = JSON.stringify(payload);

        if (fn !== undefined) config = fn(config);
        config.headers["session-id"] = SESSION+":"+(COUNTER++).toString(36)

        return fetch(url, config);
    };

    return {
        get:      function (query, headers)          { return execute(fn, 'GET',    url, query, undefined, headers); },
        put:      function (query, payload, headers) { return execute(fn, 'PUT',    url, query,   payload, headers); },
        post:     function (query, payload, headers) { return execute(fn, 'POST',   url, query,   payload, headers); },
        patch:    function (query, payload, headers) { return execute(fn, 'PATCH',  url, query,   payload, headers); },
        del:      function (query, headers)          { return execute(fn, 'DELETE', url, query, undefined, headers); },
        'delete': function (query, headers)          { return execute(fn, 'DELETE', url, query, undefined, headers); },
        'remove': function (query, headers)          { return execute(fn, 'DELETE', url, query, undefined, headers); },
    };
  };
}

export function sessionRemoteService() {
    const req = remoteService();

    return function(url) {
        var fn = function(config) {
            if (localStorage.getItem("session") !== null)
                config.headers['authorization'] = "session " + localStorage.getItem("session");

            return config;
        };

        return req(url, fn);
    };
}

export function sourisRemoteService() {
    const req = remoteService();

    return function(url, aspect) {
      if (aspect === undefined) aspect = 'default';

        var fn = function(config) {
            if (localStorage.getItem('souris_token') !== undefined)
                    config.headers['authorization'] = "souris " + aspect + " " + localStorage.getItem('souris_token');

            return config;
        };

        return req(url, fn);
    };
}

export default remoteService;
