/**
 * @license
 * Copyright (C) 2016 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-account-list.js';
import {stubRestApi} from '../../../test/test-utils.js';

const basicFixture = fixtureFromElement('gr-account-list');

class MockSuggestionsProvider {
  getSuggestions(input) {
    return Promise.resolve([]);
  }

  makeSuggestionItem(item) {
    return item;
  }
}

suite('gr-account-list tests', () => {
  let _nextAccountId = 0;
  const makeAccount = function() {
    const accountId = ++_nextAccountId;
    return {
      _account_id: accountId,
    };
  };
  const makeGroup = function() {
    const groupId = 'group' + (++_nextAccountId);
    return {
      id: groupId,
      _group: true,
    };
  };

  let existingAccount1;
  let existingAccount2;

  let element;
  let suggestionsProvider;

  function getChips() {
    return element.root.querySelectorAll('gr-account-chip');
  }

  setup(() => {
    existingAccount1 = makeAccount();
    existingAccount2 = makeAccount();

    stubRestApi('getConfig').returns(Promise.resolve({}));
    element = basicFixture.instantiate();
    element.accounts = [existingAccount1, existingAccount2];
    suggestionsProvider = new MockSuggestionsProvider();
    element.suggestionsProvider = suggestionsProvider;
  });

  test('account entry only appears when editable', () => {
    element.readonly = false;
    assert.isFalse(element.$.entry.hasAttribute('hidden'));
    element.readonly = true;
    assert.isTrue(element.$.entry.hasAttribute('hidden'));
  });

  test('addition and removal of account/group chips', () => {
    flush();
    sinon.stub(element, '_computeRemovable').returns(true);
    // Existing accounts are listed.
    let chips = getChips();
    assert.equal(chips.length, 2);
    assert.isFalse(chips[0].classList.contains('pendingAdd'));
    assert.isFalse(chips[1].classList.contains('pendingAdd'));

    // New accounts are added to end with pendingAdd class.
    const newAccount = makeAccount();
    element._handleAdd({
      detail: {
        value: {
          account: newAccount,
        },
      },
    });
    flush();
    chips = getChips();
    assert.equal(chips.length, 3);
    assert.isFalse(chips[0].classList.contains('pendingAdd'));
    assert.isFalse(chips[1].classList.contains('pendingAdd'));
    assert.isTrue(chips[2].classList.contains('pendingAdd'));

    // Removed accounts are taken out of the list.
    element.dispatchEvent(
        new CustomEvent('remove', {
          detail: {account: existingAccount1},
          composed: true, bubbles: true,
        }));
    flush();
    chips = getChips();
    assert.equal(chips.length, 2);
    assert.isFalse(chips[0].classList.contains('pendingAdd'));
    assert.isTrue(chips[1].classList.contains('pendingAdd'));

    // Invalid remove is ignored.
    element.dispatchEvent(
        new CustomEvent('remove', {
          detail: {account: existingAccount1},
          composed: true, bubbles: true,
        }));
    element.dispatchEvent(
        new CustomEvent('remove', {
          detail: {account: newAccount},
          composed: true, bubbles: true,
        }));
    flush();
    chips = getChips();
    assert.equal(chips.length, 1);
    assert.isFalse(chips[0].classList.contains('pendingAdd'));

    // New groups are added to end with pendingAdd and group classes.
    const newGroup = makeGroup();
    element._handleAdd({
      detail: {
        value: {
          group: newGroup,
        },
      },
    });
    flush();
    chips = getChips();
    assert.equal(chips.length, 2);
    assert.isTrue(chips[1].classList.contains('group'));
    assert.isTrue(chips[1].classList.contains('pendingAdd'));

    // Removed groups are taken out of the list.
    element.dispatchEvent(
        new CustomEvent('remove', {
          detail: {account: newGroup},
          composed: true, bubbles: true,
        }));
    flush();
    chips = getChips();
    assert.equal(chips.length, 1);
    assert.isFalse(chips[0].classList.contains('pendingAdd'));
  });

  test('_getSuggestions uses filter correctly', () => {
    const originalSuggestions = [
      {
        email: 'abc@example.com',
        text: 'abcd',
        _account_id: 3,
      },
      {
        email: 'qwe@example.com',
        text: 'qwer',
        _account_id: 1,
      },
      {
        email: 'xyz@example.com',
        text: 'aaaaa',
        _account_id: 25,
      },
    ];
    sinon.stub(suggestionsProvider, 'getSuggestions')
        .returns(Promise.resolve(originalSuggestions));
    sinon.stub(suggestionsProvider, 'makeSuggestionItem')
        .callsFake( suggestion => {
          return {
            name: suggestion.email,
            value: suggestion._account_id,
          };
        });

    return element._getSuggestions().then(suggestions => {
      // Default is no filtering.
      assert.equal(suggestions.length, 3);

      // Set up filter that only accepts suggestion1.
      const accountId = originalSuggestions[0]._account_id;
      element.filter = function(suggestion) {
        return suggestion._account_id === accountId;
      };

      return element._getSuggestions();
    })
        .then(suggestions => {
          assert.deepEqual(suggestions,
              [{name: originalSuggestions[0].email,
                value: originalSuggestions[0]._account_id}]);
        });
  });

  test('_computeChipClass', () => {
    const account = makeAccount();
    assert.equal(element._computeChipClass(account), '');
    account._pendingAdd = true;
    assert.equal(element._computeChipClass(account), 'pendingAdd');
    account._group = true;
    assert.equal(element._computeChipClass(account), 'group pendingAdd');
    account._pendingAdd = false;
    assert.equal(element._computeChipClass(account), 'group');
  });

  test('_computeRemovable', () => {
    const newAccount = makeAccount();
    newAccount._pendingAdd = true;
    element.readonly = false;
    element.removableValues = [];
    assert.isFalse(element._computeRemovable(existingAccount1, false));
    assert.isTrue(element._computeRemovable(newAccount, false));

    element.removableValues = [existingAccount1];
    assert.isTrue(element._computeRemovable(existingAccount1, false));
    assert.isTrue(element._computeRemovable(newAccount, false));
    assert.isFalse(element._computeRemovable(existingAccount2, false));

    element.readonly = true;
    assert.isFalse(element._computeRemovable(existingAccount1, true));
    assert.isFalse(element._computeRemovable(newAccount, true));
  });

  test('submitEntryText', () => {
    element.allowAnyInput = true;
    flush();

    const getTextStub = sinon.stub(element.$.entry, 'getText');
    getTextStub.onFirstCall().returns('');
    getTextStub.onSecondCall().returns('test');
    getTextStub.onThirdCall().returns('test@test');

    // When entry is empty, return true.
    const clearStub = sinon.stub(element.$.entry, 'clear');
    assert.isTrue(element.submitEntryText());
    assert.isFalse(clearStub.called);

    // When entry is invalid, return false.
    assert.isFalse(element.submitEntryText());
    assert.isFalse(clearStub.called);

    // When entry is valid, return true and clear text.
    assert.isTrue(element.submitEntryText());
    assert.isTrue(clearStub.called);
    assert.equal(element.additions()[0].account.email, 'test@test');
  });

  test('additions returns sanitized new accounts and groups', () => {
    assert.equal(element.additions().length, 0);

    const newAccount = makeAccount();
    element._handleAdd({
      detail: {
        value: {
          account: newAccount,
        },
      },
    });
    const newGroup = makeGroup();
    element._handleAdd({
      detail: {
        value: {
          group: newGroup,
        },
      },
    });

    assert.deepEqual(element.additions(), [
      {
        account: {
          _account_id: newAccount._account_id,
          _pendingAdd: true,
        },
      },
      {
        group: {
          id: newGroup.id,
          _group: true,
          _pendingAdd: true,
        },
      },
    ]);
  });

  test('large group confirmations', () => {
    assert.isNull(element.pendingConfirmation);
    assert.deepEqual(element.additions(), []);

    const group = makeGroup();
    const reviewer = {
      group,
      count: 10,
      confirm: true,
    };
    element._handleAdd({
      detail: {
        value: reviewer,
      },
    });

    assert.deepEqual(element.pendingConfirmation, reviewer);
    assert.deepEqual(element.additions(), []);

    element.confirmGroup(group);
    assert.isNull(element.pendingConfirmation);
    assert.deepEqual(element.additions(), [
      {
        group: {
          id: group.id,
          _group: true,
          _pendingAdd: true,
          confirmed: true,
        },
      },
    ]);
  });

  test('removeAccount fails if account is not removable', () => {
    element.readonly = true;
    const acct = makeAccount();
    element.accounts = [acct];
    element.removeAccount(acct);
    assert.equal(element.accounts.length, 1);
  });

  test('max-count', () => {
    element.maxCount = 1;
    const acct = makeAccount();
    element._handleAdd({
      detail: {
        value: {
          account: acct,
        },
      },
    });
    flush();
    assert.isTrue(element.$.entry.hasAttribute('hidden'));
  });

  test('enter text calls suggestions provider', async () => {
    const suggestions = [
      {
        email: 'abc@example.com',
        text: 'abcd',
      },
      {
        email: 'qwe@example.com',
        text: 'qwer',
      },
    ];
    const getSuggestionsStub =
        sinon.stub(suggestionsProvider, 'getSuggestions')
            .returns(Promise.resolve(suggestions));

    const makeSuggestionItemStub =
        sinon.stub(suggestionsProvider, 'makeSuggestionItem')
            .callsFake( item => item);

    const input = element.$.entry.$.input;

    input.text = 'newTest';
    MockInteractions.focus(input.$.input);
    input.noDebounce = true;
    await flush();
    assert.isTrue(getSuggestionsStub.calledOnce);
    assert.equal(getSuggestionsStub.lastCall.args[0], 'newTest');
    assert.equal(makeSuggestionItemStub.getCalls().length, 2);
  });

  test('suggestion on empty', async () => {
    element.skipSuggestOnEmpty = false;
    const suggestions = [
      {
        email: 'abc@example.com',
        text: 'abcd',
      },
      {
        email: 'qwe@example.com',
        text: 'qwer',
      },
    ];
    const getSuggestionsStub =
        sinon.stub(suggestionsProvider, 'getSuggestions')
            .returns(Promise.resolve(suggestions));

    const makeSuggestionItemStub =
        sinon.stub(suggestionsProvider, 'makeSuggestionItem')
            .callsFake( item => item);

    const input = element.$.entry.$.input;

    input.text = '';
    MockInteractions.focus(input.$.input);
    input.noDebounce = true;
    await flush();
    assert.isTrue(getSuggestionsStub.calledOnce);
    assert.equal(getSuggestionsStub.lastCall.args[0], '');
    assert.equal(makeSuggestionItemStub.getCalls().length, 2);
  });

  test('skip suggestion on empty', async () => {
    element.skipSuggestOnEmpty = true;
    const getSuggestionsStub =
        sinon.stub(suggestionsProvider, 'getSuggestions')
            .returns(Promise.resolve([]));

    const input = element.$.entry.$.input;

    input.text = '';
    MockInteractions.focus(input.$.input);
    input.noDebounce = true;
    await flush();
    assert.isTrue(getSuggestionsStub.notCalled);
  });

  suite('allowAnyInput', () => {
    setup(() => {
      element.allowAnyInput = true;
    });

    test('adds emails', () => {
      const accountLen = element.accounts.length;
      element._handleAdd({detail: {value: 'test@test'}});
      assert.equal(element.accounts.length, accountLen + 1);
      assert.equal(element.accounts[accountLen].email, 'test@test');
    });

    test('toasts on invalid email', () => {
      const toastHandler = sinon.stub();
      element.addEventListener('show-alert', toastHandler);
      element._handleAdd({detail: {value: 'test'}});
      assert.isTrue(toastHandler.called);
    });
  });

  test('_accountMatches', () => {
    const acct = makeAccount();

    assert.isTrue(element._accountMatches(acct, acct));
    acct.email = 'test';
    assert.isTrue(element._accountMatches(acct, acct));
    assert.isTrue(element._accountMatches({email: 'test'}, acct));

    assert.isFalse(element._accountMatches({}, acct));
    assert.isFalse(element._accountMatches({email: 'test2'}, acct));
    assert.isFalse(element._accountMatches({_account_id: -1}, acct));
  });

  suite('keyboard interactions', () => {
    test('backspace at text input start removes last account', async () => {
      const input = element.$.entry.$.input;
      sinon.stub(input, '_updateSuggestions');
      sinon.stub(element, '_computeRemovable').returns(true);
      await flush();
      // Next line is a workaround for Firefox not moving cursor
      // on input field update
      assert.equal(
          element._getNativeInput(input.$.input).selectionStart, 0);
      input.text = 'test';
      MockInteractions.focus(input.$.input);
      flush();
      assert.equal(element.accounts.length, 2);
      MockInteractions.pressAndReleaseKeyOn(
          element._getNativeInput(input.$.input), 8); // Backspace
      assert.equal(element.accounts.length, 2);
      input.text = '';
      MockInteractions.pressAndReleaseKeyOn(
          element._getNativeInput(input.$.input), 8); // Backspace
      flush();
      assert.equal(element.accounts.length, 1);
    });

    test('arrow key navigation', async () => {
      const input = element.$.entry.$.input;
      input.text = '';
      element.accounts = [makeAccount(), makeAccount()];
      flush();
      MockInteractions.focus(input.$.input);
      await flush();
      const chips = element.accountChips;
      const chipsOneSpy = sinon.spy(chips[1], 'focus');
      MockInteractions.pressAndReleaseKeyOn(input.$.input, 37); // Left
      assert.isTrue(chipsOneSpy.called);
      const chipsZeroSpy = sinon.spy(chips[0], 'focus');
      MockInteractions.pressAndReleaseKeyOn(chips[1], 37); // Left
      assert.isTrue(chipsZeroSpy.called);
      MockInteractions.pressAndReleaseKeyOn(chips[0], 37); // Left
      assert.isTrue(chipsZeroSpy.calledOnce);
      MockInteractions.pressAndReleaseKeyOn(chips[0], 39); // Right
      assert.isTrue(chipsOneSpy.calledTwice);
    });

    test('delete', () => {
      element.accounts = [makeAccount(), makeAccount()];
      flush();
      const focusSpy = sinon.spy(element.accountChips[1], 'focus');
      const removeSpy = sinon.spy(element, 'removeAccount');
      MockInteractions.pressAndReleaseKeyOn(
          element.accountChips[0], 8); // Backspace
      assert.isTrue(focusSpy.called);
      assert.isTrue(removeSpy.calledOnce);

      MockInteractions.pressAndReleaseKeyOn(
          element.accountChips[1], 46); // Delete
      assert.isTrue(removeSpy.calledTwice);
    });
  });
});

