/* exported loadFromKinto */
/* exported saveToKinto */

let syncDebounce = null;


const cryptographer = new Jose.WebCryptographer();
cryptographer.setKeyEncryptionAlgorithm('A256KW');
cryptographer.setContentEncryptionAlgorithm('A256GCM');

function shared_key(key) {
  return crypto.subtle.importKey(
    'jwk',
    { kty: key.kty, k: key.k.replace(/=/, '') },
    'AES-KW',
    true,
    ['wrapKey', 'unwrapKey']
  );
}

function encrypt(key, content) {
  const encrypter = new JoseJWE.Encrypter(cryptographer, shared_key(key));
  return encrypter.encrypt(JSON.stringify(content));
}

function decrypt(key, encrypted) {
  const decrypter = new JoseJWE.Decrypter(cryptographer, shared_key(key));
  return decrypter.decrypt(encrypted).then(result => {
    return JSON.parse(result);
  });
}


function loadFromKinto(client) {
  // Get credentials and lastmodified
  browser.storage.local.get(['credentials', 'contentWasSynced', 'last_modified'])
    .then((data) => {
      // XXX: Ask for an refresh token
      // Query Kinto with the Bearer Token
      if (!data.hasOwnProperty('credentials')) return;

      client
        .bucket('default')
        .collection('notes')
        .getRecord('singleNote', {
          headers: { Authorization: `Bearer ${data.credentials.access_token}` }
        })
        .then(result => {
          if (!data.hasOwnProperty('last_modified') ||
              result.data.last_modified > data.last_modified) {
            // If there is something in Kinto send unencrypted content to the sidebar
            return decrypt(data.credentials.key, result['data']['content'])
              .then(content => {
                browser.runtime.sendMessage({
                  action: 'kinto-loaded',
                  data: content,
                  contentWasSynced: data.contentWasSynced,
                  last_modified: result.data.last_modified
                });
              })
              .catch(() => {
                // In case we cannot decrypt the message
                if (data.credentials.key.kid < result.data.kid) {
                  // If the key date is greater than current one, log the user out.
                  return browser.storage.local.remove('credentials');
                } else {
                  // If the key date is older than the current one, we can't help
                  // because there is no way we get the previous key.
                  // Flush the server ALA sync
                  return client
                    .bucket('default')
                    .collection('notes')
                    .deleteRecord('singleNote', {
                      headers: { Authorization: `Bearer ${data.credentials.access_token}` }
                    });
                }
              });
          }
        })
        .catch(error => {
          if (/HTTP 404/.test(error.message)) {
            // If there is nothing in Kinto send null to the sidebar
            console.log('Kinto is emtpy');
            browser.runtime.sendMessage({
              action: 'kinto-loaded',
              data: null
            });
          } else if (/HTTP 401/.test(error.message)) {
            // In case of 401 log the user out.
            return browser.storage.local.remove('credentials');
          } else {
            console.error(error);
          }
        });
    });
}

function saveToKinto(client) {
  // XXX: Debounce the call and set the status to Editing
  browser.runtime.sendMessage('notes@mozilla.com', {
    action: 'text-editing'
  });

  const later = function() {
    syncDebounce = null;

    browser.storage.local.get(['credentials', 'notes', 'contentWasSynced', 'last_modified'])
      .then(data => {
        if (!data.contentWasSynced && data.hasOwnProperty('credentials')) {
          return encrypt(data.credentials.key, data.notes)
            .then(encrypted => {
              console.log(data.last_modified, "'" + data.last_modified);
              const headers = { Authorization: `Bearer ${data.credentials.access_token}`};
              if (data.hasOwnProperty('last_modified') && data.last_modified) {
                headers['If-Match'] = '"' + data.last_modified + '"';
              }
              console.log(headers);
              return client
                .bucket('default')
                .collection('notes')
                .updateRecord(
                  { id: 'singleNote', content: encrypted, kid: data.credentials.key.kid },
                  { headers }
                );
            })
            .then((body) => {
              console.log('Content was synced at ' + body.data.last_modified);
              return browser.storage.local.set({ contentWasSynced: true,
                                                 last_modified: body.data.last_modified })
                .then(() => {
                  // Set the status to syncing
                  browser.runtime.sendMessage('notes@mozilla.com', {
                    action: 'text-synced',
                    last_modified: body.data.last_modified,
                  });
                });
            })
            .catch(error => {
              if (/HTTP 401/.test(error.message)) {
                // In case of 401 log the user out.
                return   browser.storage.local.remove(['credentials']).then(() => {
                  return browser.storage.local.set({ contentWasSynced: false });
                });
              } else if (/HTTP 412/.test(error.message)) {
                // In case of 412 handle merge conflict
                console.log(error);
                browser.storage.local.set({ contentWasSynced: false }).then(() => {
                  loadFromKinto(client);
                });
              } else {
                console.error(error);
              }
            });
        } else {
          browser.runtime.sendMessage('notes@mozilla.com', {
            action: 'text-saved'
          });
        }
      });
  };

  clearTimeout(syncDebounce);
  syncDebounce = setTimeout(later, 1000);
  // Try to save the new content with the previous last_modified value
  // If it failed loadFromKinto and handle merge
}

@@ -3859,81 +3859,8 @@
 %3E %7B%0A
-              console.log(data.last_modified, %22'%22 + data.last_modified);%0A
     
@@ -4003,16 +4003,23 @@
 ied') &&
+ typeof
  data.la
@@ -4021,32 +4021,45 @@
 ta.last_modified
+ !== %22object%22
 ) %7B%0A            

Fix @vladikoff bug.