import React, { Component } from 'react';
import TestUtils from 'react-addons-test-utils';
import { findDOMNode } from 'react-dom';

import UserAvatar, { ProjectAvatar } from 'bitbucket/internal/bbui/aui-react/avatar';

import mockModels from 'mocks/models';
import urls from 'mocks/urls';

const person = mockModels.user(null, 'tester');
const project = mockModels.project(null, 'Cat Pictures');

QUnit.module('bitbucket-avatars', {
    beforeEach: function() {
        const render = component => {
            // react-stateless-wrapper loses the defaultProps and would cause these tests to fail.
            class Wrapped extends Component {
                static get displayName() {
                    return component.name;
                }
                static get propTypes() {
                    return component.propTypes;
                }
                static get defaultProps() {
                    return component.defaultProps;
                }
                render() {
                    return component(this.props);
                }
            }
            return props => {
                this.component = TestUtils.renderIntoDocument(<Wrapped {...props} />);
                this.el = findDOMNode(this.component);
            };
        };

        this.renderUser = render(UserAvatar);
        this.renderProject = render(ProjectAvatar);
    },
});

QUnit.test('default size is small', function(assert) {
    this.renderUser({ person });
    assert.ok(this.el.classList.contains('aui-avatar-small'));
});

QUnit.test('can pass a size', function(assert) {
    this.renderUser({
        person,
        size: 'medium',
    });
    assert.ok(this.el.classList.contains('aui-avatar-medium'));
});

QUnit.test('uses the proper AUI avatar markup', function(assert) {
    this.renderUser({ person });
    assert.ok(this.el.classList.contains('aui-avatar'));

    assert.equal(this.el.children.length, 1);
    const inner = this.el.children.item(0);
    assert.ok(inner.classList.contains('aui-avatar-inner'));

    assert.equal(inner.children.length, 1);
    const img = inner.children.item(0);
    assert.equal(img.tagName, 'IMG');
});

QUnit.test('avatar image uses display name for alternate text', function(assert) {
    this.renderUser({ person });
    const img = this.el.querySelector('img');
    assert.equal(img.getAttribute('alt'), person.display_name);
});

QUnit.test('avatar image uses avatarUrl for src', function(assert) {
    this.renderUser({ person });
    const img = this.el.querySelector('img');
    assert.equal(img.getAttribute('src'), urls.avatarUrl(person, 24));
});

QUnit.test('avatar image uses the proper pixel size for the avatarUrl', function(assert) {
    this.renderUser({
        person,
        size: 'xlarge',
    });
    const img = this.el.querySelector('img');
    assert.equal(img.getAttribute('src'), urls.avatarUrl(person, 64));
});

QUnit.test('avatar element contains the username', function(assert) {
    this.renderUser({ person });
    assert.equal(this.el.dataset.username, person.name);
});

QUnit.test('can render a project avatar', function(assert) {
    this.renderProject({ project });
    assert.ok(this.el.classList.contains('aui-avatar-project'));
});

QUnit.test('project avatar displays the project name', function(assert) {
    this.renderProject({ project });
    const img = this.el.querySelector('img');
    assert.equal(img.getAttribute('alt'), project.name);
});

QUnit.test('class name is set on the top element when there is no name', function(assert) {
    this.renderUser({
        person,
        className: 'testing',
    });
    assert.ok(this.el.classList.contains('testing'));
});

QUnit.test('can pass a class name to the avatar when there is no name', function(assert) {
    this.renderUser({
        person,
        avatarClassName: 'testing',
    });
    assert.ok(this.el.classList.contains('testing'));
});

QUnit.test('can pass a class name to the avatar when the name is shown', function(assert) {
    this.renderUser({
        person,
        avatarClassName: 'testing',
        withName: true,
    });
    assert.notOk(this.el.classList.contains('testing'));
    const avatar = this.el.querySelector('.aui-avatar');
    assert.ok(avatar.classList.contains('testing'));
});

QUnit.test('class name is set on the top element when the name is shown', function(assert) {
    this.renderUser({
        person,
        className: 'testing',
        withName: true,
    });
    assert.ok(this.el.classList.contains('testing'));
});

QUnit.test('class name is not set on the avatar when the name is shown', function(assert) {
    this.renderUser({
        person,
        className: 'testing',
        withName: true,
    });
    const avatar = this.el.querySelector('.aui-avatar');
    assert.notOk(avatar.classList.contains('testing'));
});

QUnit.test('can display a badge', function(assert) {
    this.renderUser({
        person,
        badges: [{
            className: 'approved',
            text: 'test',
        }],
    });
    assert.ok(this.el.classList.contains('aui-avatar-badged'));
    const badge = this.el.children.item(1);
    assert.equal(badge.tagName, 'SPAN');
    assert.ok(badge.classList.contains('badge'));
    assert.ok(badge.classList.contains('approved'));
    assert.equal(badge.textContent, 'test');
});

QUnit.test('badges are hidden by default', function(assert) {
    this.renderUser({
        person,
        badges: [{ className: 'approved' }],
    });
    const badge = this.el.children.item(1);
    assert.ok(badge.classList.contains('badge-hidden'));
});

QUnit.test('can display multiple badges', function(assert) {
    this.renderUser({
        person,
        badges: [{ className: 'approved' }, { className: 'needs-work' }],
    });
    assert.ok(this.el.classList.contains('aui-avatar-badged'));
    const approvedBadge = this.el.children.item(1);
    assert.equal(approvedBadge.tagName, 'SPAN');
    assert.ok(approvedBadge.classList.contains('badge'));
    assert.ok(approvedBadge.classList.contains('approved'));
    const reviewedBadge = this.el.children.item(2);
    assert.equal(reviewedBadge.tagName, 'SPAN');
    assert.ok(reviewedBadge.classList.contains('badge'));
    assert.ok(reviewedBadge.classList.contains('needs-work'));
});

QUnit.test('can display a single visible badge', function(assert) {
    this.renderUser({
        person,
        badges: [{ className: 'approved' }, { className: 'needs-work' }],
        visibleBadge: 'needs-work',
    });
    assert.ok(this.el.classList.contains('aui-avatar-badged'));
    const approvedBadge = this.el.children.item(1);
    assert.ok(approvedBadge.classList.contains('badge-hidden'));
    const reviewedBadge = this.el.children.item(2);
    assert.notOk(reviewedBadge.classList.contains('badge-hidden'));
});
