import Ember from 'ember';
import moduleForComponent from 'web-client/tests/helpers/module-for-component';
import { test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import wait from 'ember-test-helpers/wait';

const { ArrayProxy } = Ember;
const { Object } = Ember;

moduleForComponent('panels-list', 'Integration | Component | panels-list');

function setPanels(self, kind, teespringCampaignEnabled, isExtensionsEnabled, noExtensions, noPanels) {
  let panelObject = {
    rollback(){},
    _id: 1,
    data: {
      image: '',
      link: 'link',
      title: 'this is a title'
    },
    display_order: 1,
    isLoaded: true,
    kind,
    user_id: 1
  };
  let panels = ArrayProxy.create({
    content:[panelObject],
    load() {},
    user: 'twitch',
    isLoading: false
  });

  let extensionInstallations = self.server.schema.extensionInstallations.all().models;
  let installedExtensions = extensionInstallations.map(extensionInstallation => {
    let result = Object.create(extensionInstallation.attrs);
    result.set('extension', Object.create(extensionInstallation.extension.attrs));
    return result;
  });

  self.set('panels', noPanels ? null : panels);
  self.set('installedExtensions', noExtensions ? [] : installedExtensions);
  self.set('teespringCampaignEnabled', teespringCampaignEnabled);
  self.set('isExtensionsEnabled', isExtensionsEnabled);

  self.render(hbs`
    {{panels-list
      showEmptyMessage=true
      panels=panels
      isEditable=true
      isLeftColumnClosed=false
      isRightColumnClosed=false
      teespringCampaignEnabled=teespringCampaignEnabled
      isExtensionsEnabled=isExtensionsEnabled
      installedExtensions=installedExtensions
      onLinkClick=null
      visible=true
    }}
  `);
}

// Test that extensions and teespring do not render when disabled.
//--------------------------------------------------------------------------------

test('renders no interstitial when extensions and teespring are disabled', function(assert) {
  assert.expect(3);
  let done = assert.async();
  setPanels(this, 'default', false, false);

  // Into edit mode
  return wait().then(() => {
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    // Click on the new panel button
    this.$('.js-new_panel_btn').click();
    return wait();
  }).then(() => {
    assert.elementCount('button :contains(Add a Text or Image Panel):visible', 0, 'interstitial form should be visible');
    assert.elementCount('button :contains(Create a Teespring Panel):visible', 0, 'interstitial form should not have teespring option');
    assert.elementCount('a:contains(More Extensions):visible', 0, 'interstitial form should not have extensions option');
    return done();
  });
});

test('renders default panel in edit mode without teespring nor extensions', function(assert) {
  assert.expect(5);
  let done = assert.async();
  setPanels(this, 'default', false, false);

  // Out of edit mode
  let title = this.$('.js-panel-content .title:visible').text();
  assert.equal(title, 'this is a title', 'default panel should show');

  // Go into edit mode
  return wait().then(() => {
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    assert.elementCount('.js-new_panel_btn', 1, 'new panel selector should render');
    assert.elementCount('.new-panel-default_view:visible', 1, 'default panel form should be visible');
    assert.elementCount('.new-panel-extension_view:visible', 0, 'extensions panel form should not be visible');
    assert.elementCount('.new-panel-teespring_view:visible', 0, 'teespring panel form should not be visible');
    return done();
  });
});

// Test that interstitial renders when teespring or extensions are enabled
//--------------------------------------------------------------------------------

test('renders interstitial with teespring enabled but extensions disabled', function(assert) {
  assert.expect(3);
  let done = assert.async();
  setPanels(this, 'default', true, false);

  // Into edit mode
  return wait().then(() => {
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    // Click on the new panel button
    this.$('.js-new_panel_btn').click();
    return wait();
  }).then(() => {
    assert.elementCount('button :contains(Add a Text or Image Panel):visible', 1, 'interstitial form should be visible');
    assert.elementCount('button :contains(Create a Teespring Panel):visible', 1, 'interstitial form should have teespring option');
    assert.elementCount('a:contains(More Extensions):visible', 0, 'interstitial form should not have extensions option');
    return done();
  });
});

test('renders interstitial with teespring disabled but extensions enabled', function(assert) {
  assert.expect(3);
  let done = assert.async();
  setPanels(this, 'default', false, true);

  // Into edit mode
  return wait().then(() => {
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    // Click on the new panel button
    this.$('.js-new_panel_btn').click();
    return wait();
  }).then(() => {
    assert.elementCount('button :contains(Add a Text or Image Panel):visible', 1, 'interstitial form should be visible');
    assert.elementCount('button :contains(Create a Teespring Panel):visible', 0, 'interstitial form should not have teespring option');
    assert.elementCount('a:contains(More Extensions):visible', 1, 'interstitial form should have extensions option');
    return done();
  });
});

// Test that edit panels for teespring and extensions
//--------------------------------------------------------------------------------

test('renders extension panel in edit mode', function(assert) {
  assert.expect(5);
  let done = assert.async();
  let extensionInstallation = this.server.create('extension-installation');
  let extension = this.server.db.extensions.find(extensionInstallation.extensionId);
  this.name = extension.name;

  return wait().then(() => {
    setPanels(this, 'ext-1', false, true);
    return wait();
  }).then(() => {
    // Out of edit mode
    let title = this.$('.qa-panel-extension-name:visible').text().trim();
    assert.equal(title, this.name, 'extension panel should show');
    return wait();
  }).then(() => {
    // Go into edit mode
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    assert.elementCount('.js-new_panel_btn:visible', 1, 'new panel selector should render');
    assert.elementCount('.new-panel-default_view:visible', 0, 'default panel form should not be visible');
    assert.elementCount('.new-panel-extension_view:visible', 1, 'extensions panel form should be visible');
    assert.elementCount('.new-panel-teespring_view:visible', 0, 'teespring panel form should not be visible');
    return done();
  });
});

test('does not render extension panel in edit mode in extensions disabled', function(assert) {
  assert.expect(4);
  let done = assert.async();
  let extensionInstallation = this.server.create('extension-installation');
  let extension = this.server.db.extensions.find(extensionInstallation.extensionId);
  this.name = extension.name;

  return wait().then(() => {
    setPanels(this, 'ext-1', false, false);
    return wait();
  }).then(() => {
    // Go into edit mode
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    assert.elementCount('.js-new_panel_btn:visible', 1, 'new panel selector should render');
    assert.elementCount('.new-panel-default_view:visible', 0, 'default panel form should not be visible');
    assert.elementCount('.new-panel-extension_view:visible', 0, 'extensions panel form should be visible');
    assert.elementCount('.new-panel-teespring_view:visible', 0, 'teespring panel form should not be visible');
    return done();
  });
});

test('renders extensions in edit mode', function(assert) {
  assert.expect(5);
  let done = assert.async();
  let extensionInstallation = this.server.create('extension-installation');
  let extension = this.server.db.extensions.find(extensionInstallation.extensionId);
  this.name = extension.name;

  return wait().then(() => {
    setPanels(this, 'default', false, true);
    return wait();
  }).then(() => {
    // Go into edit mode
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    this.$('.js-new_panel_btn').click();
    return wait();
  }).then(() => {
    assert.elementCount('.js-new_panel_btn:visible', 1, 'new panel selector should render');
    assert.elementCount('.new-panel-default_view:visible', 1, 'default panel form should not be visible');
    assert.elementCount('.new-panel-extension_view:visible', 0, 'extensions panel form should be visible');
    assert.elementCount('.new-panel-teespring_view:visible', 0, 'teespring panel form should not be visible');
    assert.elementCount(`.qa-extensions-installed-list .extensions-name:contains(${this.name}):visible`, 1, 'extension picker should be visible');
    return done();
  });
});

test('renders no extensions in edit mode', function(assert) {
  assert.expect(5);
  let done = assert.async();

  return wait().then(() => {
    setPanels(this, 'default', false, true, true);
    return wait();
  }).then(() => {
    // Go into edit mode
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    this.$('.js-new_panel_btn').click();
    return wait();
  }).then(() => {
    assert.elementCount('.js-new_panel_btn:visible', 1, 'new panel selector should render');
    assert.elementCount('.new-panel-default_view:visible', 1, 'default panel form should not be visible');
    assert.elementCount('.new-panel-extension_view:visible', 0, 'extensions panel form should be visible');
    assert.elementCount('.new-panel-teespring_view:visible', 0, 'teespring panel form should not be visible');
    assert.elementCount('.qa-extensions-none-installed:contains(No extensions installed):visible', 1, 'no extensions installed message should not be visible');
    return done();
  });
});

test('renders teespring panel in edit mode', function(assert) {
  assert.expect(5);
  let done = assert.async();
  setPanels(this, 'teespring', true, false);

  // Out of edit mode
  let title = this.$('.teespring-panel-buy:visible');
  assert.equal(title.length, 1, 'teespring panel should show');

  // Go into edit mode
  return wait().then(() => {
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    assert.elementCount('.js-new_panel_btn', 1, 'new panel selector should render');
    assert.elementCount('.new-panel-default_view:visible', 0, 'default panel form should not be visible');
    assert.elementCount('.new-panel-extension_view:visible', 0, 'extensions panel form should be visible');
    assert.elementCount('.new-panel-teespring_view:visible', 1, 'teespring panel form should not be visible');
    return done();
  });
});

// zacksim 20 Dec 2016. This test is failing because, it appears, there seems
// to be something wrong with teespring submission in general that predates
// extensions work.
// (Rolled back to a 10 November commit and tested manually and there were
// problems wuth new teespring panels disappearing). Until time is found
// to hunt down the underlieing problem this test is skipped as it is
// causing a test failure in ember 2.10
test('teespring panel that is submitable', function(assert) {
  assert.expect(4);
  let done = assert.async();
  setPanels(this, 'default', true, false);

  return wait().then(() => {
    // Into edit mode
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    // Click on the new panel button
    this.$('.js-new_panel_btn').click();
    return wait();
  }).then(() => {
    assert.elementCount('button :contains(Add a Text or Image Panel):visible', 1, 'interstitial form should be visible');
    let teespringButton = 'button :contains(Create a Teespring Panel):visible';
    assert.elementCount(teespringButton, 1, 'interstitial form should have teespring option');
    this.$(teespringButton).click();
    return wait();
  }).then(() => {
    assert.elementCount('.new-panel-teespring_view', 1, 'teespring edit panel should show');
    // Clicking on submit will try to post
    this.$('.teespring-submit-button').click();
    return wait();
  }).then(() => {
    // Out of edit mode
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    // Look for the teespring panel buy button
    assert.elementCount('.teespring-panel-buy:visible', 1, 'teespring buy button should be visible');
    return done();
  });
});

test('extension panel is selectable', function(assert) {
  assert.expect(6);
  let done = assert.async();
  let extensionInstallation = this.server.create('extension-installation');
  let extension = this.server.db.extensions.find(extensionInstallation.extensionId);
  this.name = extension.name;
  this.summary = extension.summary;

  return wait().then(() => {
    setPanels(this, 'default', false, true);
    return wait();
  }).then(() => {
    // Into edit mode
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    // Click on the new panel button
    this.$('.js-new_panel_btn').click();
    return wait();
  }).then(() => {
    assert.elementCount('button :contains(Add a Text or Image Panel):visible', 1, 'interstitial form should be visible');
    assert.elementCount('button :contains(Create a Teespring Panel):visible', 0, 'interstitial form should have teespring option');
    assert.elementCount('a:contains(More Extensions):visible', 1, 'interstitial form should have extensions option');
    let extensionSelect = `.extensions-name:contains(${this.name}):visible`;
    assert.elementCount(extensionSelect, 1, 'extension select should be visible');
    this.$(extensionSelect).click();
    return wait();
  }).then(() => {
    assert.elementCount(`.new-panel-extension_view:contains(${this.name}):visible`, 1, 'extension panel should be visible');
    // Out of edit mode
    this.$('.edit-panels-toggle').click();
    return wait();
  }).then(() => {
    // Look for the extension panel
    assert.elementCount(`.qa-panel-extension-name:contains(${this.name})`, 1, 'non edit extension panel should be visible');
    return done();
  });
});

// Test iframe appears
//--------------------------------------------------------------------------------

test('renders extension iframe in non-edit mode', function(assert) {
  assert.expect(2);
  let done = assert.async();
  let extensionInstallation = this.server.create('extension-installation');
  let extension = this.server.db.extensions.find(extensionInstallation.extensionId);
  this.name = extension.name;
  this.viewerUrl = extension.viewerUrl;

  return wait().then(() => {
    setPanels(this, 'ext-1', false, true);
    return wait();
  }).then(() => {
    let title = this.$('.qa-panel-extension-name:visible').text().trim();
    assert.equal(title, this.name, 'extension panel should show');
    assert.elementCount(`iframe[src='${this.viewerUrl}']`, 1, 'iframe should have viewer src');
    return done();
  });
});

// Test iframe does not appear for non-staff, non-experiment
//--------------------------------------------------------------------------------

test('does not render extension iframe in non-edit mode if extensions disabled', function(assert) {
  assert.expect(1);
  let done = assert.async();
  let extensionInstallation = this.server.create('extension-installation');
  let extension = this.server.db.extensions.find(extensionInstallation.extensionId);
  this.name = extension.name;
  this.viewerUrl = extension.viewerUrl;

  return wait().then(() => {
    setPanels(this, 'ext-1', false, false);
    return wait();
  }).then(() => {
    assert.elementCount(`iframe[src='${this.viewerUrl}']`, 0, 'iframe should not be visible if extensions disabled');
    return done();
  });
});

// Test no panel shows "Empty in here"
//--------------------------------------------------------------------------------

test('shows empty in here when no panels', function(assert) {
  assert.expect(1);
  let done = assert.async();
  setPanels(this, 'default', true, true, true, true);
  return wait().then(() => {
    assert.elementCount('.empty-grid:contains(empty in here)', 1, 'empty message should show');
    return done();
  });
});
