import { test } from 'qunit';
import moduleForAcceptance from 'web-client/tests/helpers/module-for-acceptance';
import subscriptionDashScenario from 'web-client/mirage/scenarios/subscription-dash';
import { BadgesPage } from 'web-client/tests/pages/dashboards/subscription-dash';
import { stubLogin } from 'web-client/tests/helpers/stub-login';

import { POSSIBLE_BADGES } from 'web-client/controllers/dashboards/subscription-dash/badges';

const USERNAME = 'twitch';
const PNG_18_X_18 = 'iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAQAAAD8x0bcAAAAFUlEQVR42mNk+M9AEDCOKhpVRG9FAJcmEgHjoEpiAAAAAElFTkSuQmCC';
const PNG_36_X_36 = 'iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAQAAABLCVATAAAAJElEQVR42u3MMQEAAAgDoK1/aC3hJwSgmZyoSCQSiUQikehLtLefJAGAigazAAAAAElFTkSuQmCC';
const PNG_72_X_72 = 'iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAQAAAD/5HvMAAAARElEQVR42u3OAQ0AAAgDoL9/aK3hJiSgmZxSISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISGhL6EFdIhIAccIVp4AAAAASUVORK5CYII=';

function newMockPNG(dataURI) {
  let byteCharacters = atob(dataURI);
  let byteNumbers = new Array(byteCharacters.length);

  for (let i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i);
  }

  let byteArray = new Uint8Array(byteNumbers); // eslint-disable-line no-undef

  return new Blob([byteArray], { type: 'image/png' });
}

moduleForAcceptance('Acceptance | dashboard/subscription/badges', {
  beforeEach() {
    this.page = BadgesPage.create({ username: USERNAME });

    subscriptionDashScenario(this.server, { name: USERNAME });
    stubLogin({ login: USERNAME });
  }
});

test('renders expected elements, uploads a badge, deletes a badge, and goes back to /dashboard/subscription index page', function (assert) {
  assert.expect(34 + POSSIBLE_BADGES.length);

  let $badgeDisplays, $badgeImages, $badgeTabs, $form, $imagePickers, $submitButton;

  visit(this.page.url());

  andThen(() => {
    $badgeDisplays = find(this.page.subBadgeDisplay());
    $badgeImages = find(this.page.subBadgeDisplayImage());
    $badgeTabs = find(this.page.subBadgeTab());
    $form = find(this.page.form());
    $imagePickers = find(this.page.subBadgeImagePickerInput());
    $submitButton = find(this.page.formSubmitButton());

    assert.equal(currentURL(), '/twitch/dashboard/subscription/badges', '"Loyalty Badges" page is visited');
    assert.elementText(find(this.page.pageTitle()), 'Loyalty Badges', 'page title is present');

    assert.equal(
      $badgeDisplays.length,
      POSSIBLE_BADGES.length,
      'number of badge displays matches number of possible badges'
    );

    assert.elementCount($badgeImages, 3, 'three badge images are displayed');

    assert.equal(
      $badgeImages.eq(0).attr('src'),
      POSSIBLE_BADGES[0].image_2x_url,
      'first badge image is the default subscriber badge'
    );

    assert.equal($badgeImages.eq(1).attr('src'), '#', 'second badge image "src" is set');
    assert.equal($badgeImages.eq(2).attr('src'), '#', 'third badge image "src" is set');
    assert.equal($badgeTabs.length, POSSIBLE_BADGES.length, 'number of tabs matches number of possible badges');

    for (let i = 0; i < POSSIBLE_BADGES.length; i++) {
      assert.elementText($badgeTabs.eq(i), POSSIBLE_BADGES[i].name, 'tab has the correct name');
    }

    assert.elementCount($form, 1, '<form> element is rendered');
    assert.elementCount($imagePickers, 3, 'three <input type="file"> elements are rendered');
    assert.ok($submitButton.prop('disabled'), 'upload button is disabled');
    assert.elementText($submitButton, 'Save Images', 'upload button text is correct');
  });

  chooseFile(this.page.subBadgeImagePickerInputByIndex(0), newMockPNG(PNG_18_X_18));
  chooseFile(this.page.subBadgeImagePickerInputByIndex(1), newMockPNG(PNG_36_X_36));
  chooseFile(this.page.subBadgeImagePickerInputByIndex(2), newMockPNG(PNG_72_X_72));

  andThen(() => {
    assert.notOk($submitButton.prop('disabled'), 'upload button is enabled');
  });

  click(this.page.formSubmitButton());

  andThen(() => {
    assert.elementCount(find(this.page.modal()), 1, 'confirmation modal is rendered');
    assert.elementCount(find(this.page.modalCancelButton()), 1, 'cancel button is rendered');
    assert.elementCount(find(this.page.modalConfirmButton()), 1, 'confirm button is rendered');
  });

  click(this.page.modalConfirmButton());

  andThen(() => {
    $badgeImages = find(this.page.subBadgeDisplayImage());
    $form = find(this.page.form());
    $imagePickers = find(this.page.subBadgeImagePickerInput());
    $submitButton = find(this.page.formSubmitButton());

    assert.elementCount($badgeImages, 3, 'three badge images are still displayed');
    assert.equal($badgeImages.eq(0).attr('src'), '#', 'first badge image is updated');

    assert.elementCount($form, 1, '<form> element is rendered');
    assert.elementCount($imagePickers, 0, 'no <input type="file"> elements are rendered');
    assert.notOk($submitButton.prop('disabled'), 'delete button is not disabled');
    assert.elementText($submitButton, 'Delete Badge', 'delete button text is correct');
  });

  click(this.page.formSubmitButton());

  andThen(() => {
    assert.elementCount(find(this.page.modal()), 1, 'confirmation modal is rendered');
    assert.elementCount(find(this.page.modalCancelButton()), 1, 'cancel button is rendered');
    assert.elementCount(find(this.page.modalConfirmButton()), 1, 'confirm button is rendered');
  });

  click(this.page.modalConfirmButton());

  andThen(() => {
    $badgeImages = find(this.page.subBadgeDisplayImage());
    $form = find(this.page.form());
    $imagePickers = find(this.page.subBadgeImagePickerInput());
    $submitButton = find(this.page.formSubmitButton());

    assert.elementCount(find(this.page.modal()), 0, 'confirmation modal is not rendered');

    assert.elementCount($badgeImages, 3, 'three badge images are still displayed');

    assert.equal(
      $badgeImages.eq(0).attr('src'),
      POSSIBLE_BADGES[0].image_2x_url,
      'first badge image is back to the default subscriber badge'
    );

    assert.elementCount($form, 1, '<form> element is rendered');
    assert.elementCount($imagePickers, 3, 'three <input type="file"> elements are once again rendered');
    assert.ok($submitButton.prop('disabled'), 'upload button is once again disabled');
    assert.elementText($submitButton, 'Save Images', 'upload button text is once again correct');
  });

  click(this.page.backToIndex());

  andThen(() => {
    assert.equal(currentURL(), '/twitch/dashboard/subscription', 'index page is visited');
    assert.equal(this.page.headTitle(), `${USERNAME}'s Dashboard - Twitch`, 'has title tag in head');
  });
});
