/**
 * @license
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import '../../../test/common-test-setup-karma.js';
import './gr-gpg-editor.js';

const basicFixture = fixtureFromElement('gr-gpg-editor');

suite('gr-gpg-editor tests', () => {
  let element;
  let keys;

  setup(done => {
    const fingerprint1 = '0192 723D 42D1 0C5B 32A6  E1E0 9350 9E4B AFC8 A49B';
    const fingerprint2 = '0196 723D 42D1 0C5B 32A6  E1E0 9350 9E4B AFC8 A49B';
    keys = {
      AFC8A49B: {
        fingerprint: fingerprint1,
        user_ids: [
          'John Doe john.doe@example.com',
        ],
        key: '-----BEGIN PGP PUBLIC KEY BLOCK-----' +
             '\nVersion: BCPG v1.52\n\t<key 1>',
        status: 'TRUSTED',
        problems: [],
      },
      AED9B59C: {
        fingerprint: fingerprint2,
        user_ids: [
          'Gerrit gerrit@example.com',
        ],
        key: '-----BEGIN PGP PUBLIC KEY BLOCK-----' +
             '\nVersion: BCPG v1.52\n\t<key 2>',
        status: 'TRUSTED',
        problems: [],
      },
    };

    stub('gr-rest-api-interface', {
      getAccountGPGKeys() { return Promise.resolve(keys); },
    });

    element = basicFixture.instantiate();

    element.loadData().then(() => { flush(done); });
  });

  test('renders', () => {
    const rows = element.root.querySelectorAll('tbody tr');

    assert.equal(rows.length, 2);

    let cells = rows[0].querySelectorAll('td');
    assert.equal(cells[0].textContent, 'AFC8A49B');

    cells = rows[1].querySelectorAll('td');
    assert.equal(cells[0].textContent, 'AED9B59C');
  });

  test('remove key', done => {
    const lastKey = keys[Object.keys(keys)[1]];

    const saveStub = sinon.stub(element.$.restAPI, 'deleteAccountGPGKey')
        .callsFake(() => Promise.resolve());

    assert.equal(element._keysToRemove.length, 0);
    assert.isFalse(element.hasUnsavedChanges);

    // Get the delete button for the last row.
    const button = element.root.querySelector(
        'tbody tr:last-of-type td:nth-child(6) gr-button');

    MockInteractions.tap(button);

    assert.equal(element._keys.length, 1);
    assert.equal(element._keysToRemove.length, 1);
    assert.equal(element._keysToRemove[0], lastKey);
    assert.isTrue(element.hasUnsavedChanges);
    assert.isFalse(saveStub.called);

    element.save().then(() => {
      assert.isTrue(saveStub.called);
      assert.equal(saveStub.lastCall.args[0], Object.keys(keys)[1]);
      assert.equal(element._keysToRemove.length, 0);
      assert.isFalse(element.hasUnsavedChanges);
      done();
    });
  });

  test('show key', () => {
    const openSpy = sinon.spy(element.$.viewKeyOverlay, 'open');

    // Get the show button for the last row.
    const button = element.root.querySelector(
        'tbody tr:last-of-type td:nth-child(4) gr-button');

    MockInteractions.tap(button);

    assert.equal(element._keyToView, keys[Object.keys(keys)[1]]);
    assert.isTrue(openSpy.called);
  });

  test('add key', done => {
    const newKeyString =
        '-----BEGIN PGP PUBLIC KEY BLOCK-----' +
        '\nVersion: BCPG v1.52\n\t<key 3>';
    const newKeyObject = {
      ADE8A59B: {
        fingerprint: '0194 723D 42D1 0C5B 32A6  E1E0 9350 9E4B AFC8 A49B',
        user_ids: [
          'John john@example.com',
        ],
        key: newKeyString,
        status: 'TRUSTED',
        problems: [],
      },
    };

    const addStub = sinon.stub(element.$.restAPI, 'addAccountGPGKey').callsFake(
        () => Promise.resolve(newKeyObject));

    element._newKey = newKeyString;

    assert.isFalse(element.$.addButton.disabled);
    assert.isFalse(element.$.newKey.disabled);

    element._handleAddKey().then(() => {
      assert.isTrue(element.$.addButton.disabled);
      assert.isFalse(element.$.newKey.disabled);
      assert.equal(element._keys.length, 2);
      done();
    });

    assert.isTrue(element.$.addButton.disabled);
    assert.isTrue(element.$.newKey.disabled);

    assert.isTrue(addStub.called);
    assert.deepEqual(addStub.lastCall.args[0], {add: [newKeyString]});
  });

  test('add invalid key', done => {
    const newKeyString = 'not even close to valid';

    const addStub = sinon.stub(element.$.restAPI, 'addAccountGPGKey').callsFake(
        () => Promise.reject(new Error('error')));

    element._newKey = newKeyString;

    assert.isFalse(element.$.addButton.disabled);
    assert.isFalse(element.$.newKey.disabled);

    element._handleAddKey().then(() => {
      assert.isFalse(element.$.addButton.disabled);
      assert.isFalse(element.$.newKey.disabled);
      assert.equal(element._keys.length, 2);
      done();
    });

    assert.isTrue(element.$.addButton.disabled);
    assert.isTrue(element.$.newKey.disabled);

    assert.isTrue(addStub.called);
    assert.deepEqual(addStub.lastCall.args[0], {add: [newKeyString]});
  });
});

