import { shallow } from 'enzyme';
import React from 'react';
import { dissoc } from 'ramda';

import { FEATURED_IMAGE_FIXTURE } from '../../../tests/fixtures/media';
import { Site } from '../../../tests/storyshare';
import { MediaImage } from './MediaImage';
import DefaultItem from '../Item/Item';

describe('MediaImage component', () => {
  let wrapper;
  const site = new Site();

  beforeAll(() => {
    jest.spyOn(site, 'objectToResponse').mockReturnValue({
      offline: () => FEATURED_IMAGE_FIXTURE,
    });
    jest.spyOn(site, 'isOnline').mockReturnValue(true);
    jest.spyOn(console, 'error').mockReturnValue();
  });

  beforeEach(() => {
    site.objectToResponse.mockClear();
    wrapper = shallow(
      <MediaImage
        id={ 42 }
        site={ site }
        width={ 640 }
      />
    );
  });

  const getImageItem = (imageFixture) => {
    const children = wrapper.find(DefaultItem).prop('children');
    return shallow(<div>{ children(imageFixture) }</div>);
  };

  it('renders', () => {
    expect(wrapper).toExist();
  });

  it('renders an Item to retrieve image', () => {
    const imageItem = wrapper.find(DefaultItem);

    expect(imageItem).toExist();
    expect(imageItem).toHaveProp('id', 42);
    expect(imageItem).toHaveProp('typeSlug', 'media');
  });

  it('renders an SUI Image', () => {
    expect(getImageItem(FEATURED_IMAGE_FIXTURE).find('Image')).toExist();
  });

  it('passes unknown props through to the Image', () => {
    wrapper.setProps({ unknown: 'value' });
    expect(getImageItem(FEATURED_IMAGE_FIXTURE).find('Image'))
      .toHaveProp('unknown', 'value');
  });

  it('avoids passing internal props through to the Image', () => {
    const image = getImageItem(FEATURED_IMAGE_FIXTURE).find('Image');
    expect(image).not.toHaveProp('id');
    expect(image).not.toHaveProp('medium');
    expect(image).not.toHaveProp('site');
  });

  it('avoids passing react-redux dispatch to the Image', () => {
    wrapper.setProps({ dispatch: () => null });
    expect(wrapper.find('Select')).not.toHaveProp('dispatch');
  });

  it('suppresses rendering completely if the supplied ID is 0', () => {
    wrapper.setProps({ id: 0 });
    expect(wrapper).toBeEmptyRender();
  });

  it('renders custom Placeholder if provided', () => {
    wrapper.setProps({
      placeholder: (
        <div>Custom placeholder test</div>
      ),
    });

    jest.spyOn(site, 'objectToResponse').mockReturnValueOnce({
      offline: jest.fn().mockReturnValueOnce(
        dissoc('media_details', FEATURED_IMAGE_FIXTURE)
      ),
    });
    const imageItem = getImageItem();

    expect(wrapper.name()).not.toBe('Image');
    expect(imageItem.find('Placeholder')).not.toExist();
    expect(imageItem.find('div')).toExist();
    expect(imageItem.find('div').children().find('div'))
      .toHaveText('Custom placeholder test');
  });

  it('suppresses rendering if no images match the aspect ratio', () => {
    wrapper.setProps({ aspectRatio: '1000:1' });
    expect(getImageItem(FEATURED_IMAGE_FIXTURE).find('Image')).not.toExist();
  });

  it('renders Placeholder in case of an error', () => {
    getImageItem(FEATURED_IMAGE_FIXTURE).find('Image').simulate('error');
    expect(getImageItem().find('Image')).not.toExist();
    expect(getImageItem(FEATURED_IMAGE_FIXTURE).find('Placeholder')).toExist();
    expect(getImageItem(FEATURED_IMAGE_FIXTURE)
      .find('PlaceholderImage')).toHaveProp('rectangular');
  });

  it('does have srcset attribute', () => {
    const image = getImageItem(FEATURED_IMAGE_FIXTURE).find('Image');
    expect(image).toHaveProp('srcSet');
  });

  it('does contain correct values in srcset', () => {
    const image = getImageItem(FEATURED_IMAGE_FIXTURE).find('Image');
    expect(image).toHaveProp(
      'srcSet',
      'path/to/1028x600 1028w'
      + ', path/to/640x360 640w'
      + ', path/to/1024x576 1024w'
      + ', path/to/1024x574 1024w'
      + ', path/to/1024x579 1024w'
    );
  });

  it('does render correct srcset values when aspect ratio is 2:1', () => {
    wrapper.setProps({ aspectRatio: '2:1', width: 1024 });
    wrapper.update();
    const image = getImageItem(FEATURED_IMAGE_FIXTURE).find('Image');
    expect(image).toHaveProp(
      'srcSet',
      'path/to/1024x510 1024w'
      + ', path/to/1024x512 1024w'
      + ', path/to/1024x514 1024w'
    );
  });

  it('does render correct srcset values when aspect ratio is 42:29', () => {
    wrapper.setProps({ aspectRatio: '42:29', width: 1024 });
    wrapper.update();
    const image = getImageItem(FEATURED_IMAGE_FIXTURE).find('Image');
    expect(image).toHaveProp(
      'srcSet',
      'path/to/1024x674 1024w'
      + ', path/to/1024x707 1024w'
      + ', path/to/1024x744 1024w'
    );
  });

  it('does render correct srcset values when aspect ratio is 4:3', () => {
    wrapper.setProps({ aspectRatio: '4:3', width: 1024 });
    wrapper.update();
    const image = getImageItem(FEATURED_IMAGE_FIXTURE).find('Image');
    expect(image).toHaveProp(
      'srcSet',
      'path/to/1024x744 1024w'
      + ', path/to/1024x745 1024w'
      + ', path/to/1024x768 1024w'
      + ', path/to/1024x766 1024w'
      + ', path/to/1024x770 1024w'
    );
  });

  it('does render correct srcset values when aspect ratio is 1:1', () => {
    wrapper.setProps({ aspectRatio: '1:1', width: 1024 });
    wrapper.update();
    const image = getImageItem(FEATURED_IMAGE_FIXTURE).find('Image');
    expect(image).toHaveProp(
      'srcSet',
      'path/to/1024x1022 1024w'
      + ', path/to/1024x1024 1024w'
      + ', path/to/1024x1026 1024w'
    );
  });

  it('does render correct srcset values when aspect ratio is 1:2', () => {
    wrapper.setProps({ aspectRatio: '1:2', width: 1024 });
    wrapper.update();
    const image = getImageItem(FEATURED_IMAGE_FIXTURE).find('Image');
    expect(image).toHaveProp(
      'srcSet',
      'path/to/1024x2046 1024w'
      + ', path/to/1024x2048 1024w'
      + ', path/to/1024x2050 1024w'
    );
  });

  it('can find an URL based on width with default aspect ratio', () => {
    expect(getImageItem(FEATURED_IMAGE_FIXTURE).find('Image'))
      .toHaveProp('src', 'path/to/640x360');
  });

  it('can find first URL that matches provided width and aspect ratio', () => {
    wrapper.setProps({ width: 1024, aspectRatio: '1:1' });
    expect(getImageItem(FEATURED_IMAGE_FIXTURE).find('Image'))
      .toHaveProp('src', 'path/to/1024x1022');
  });

  it('renders title and alt text if provided', () => {
    const image = getImageItem(FEATURED_IMAGE_FIXTURE).find('Image');
    expect(image).toHaveProp('alt', '');
    expect(image).toHaveProp('title', '');
  });

  it('returns null if image width does not fit aspect ratio', () => {
    wrapper.setProps({ width: 500, aspectRatio: '' });
    expect(getImageItem(FEATURED_IMAGE_FIXTURE).find('Image')).not.toExist();
  });

  it('gets offline version of medium', () => {
    const offline = jest.fn().mockReturnValue(FEATURED_IMAGE_FIXTURE);
    site.objectToResponse.mockReturnValue({ offline });
    getImageItem(FEATURED_IMAGE_FIXTURE);
    expect(site.objectToResponse).toHaveBeenCalledWith(FEATURED_IMAGE_FIXTURE);
    expect(offline).toHaveBeenCalled();
  });

  it('does not set srcset when offline', () => {
    site.isOnline.mockReturnValue(false);
    const image = getImageItem(FEATURED_IMAGE_FIXTURE).find('Image');
    expect(image).toHaveProp('srcSet', false);
  });
});
