import { TestBed } from '@angular/core/testing';

import { BaseRequestOptions, Http, HttpModule, Response, ResponseOptions, XHRBackend } from '@angular/http';
import { MockBackend, MockConnection } from '@angular/http/testing';

import { IToken } from './token.model';
import { TokenService } from './token.service';

import { LdiStorage } from '../storage';

describe('Token server tests', () => {
    let tokenService: TokenService;
    let mockBackend: MockBackend;
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [HttpModule],
            providers: [TokenService,
                MockBackend, BaseRequestOptions,
                {
                    provide: Http,
                    deps: [MockBackend, BaseRequestOptions],
                    useFactory: (backend: XHRBackend, defaultOptions: BaseRequestOptions) => {
                        return new Http(backend, defaultOptions);
                    }
                }]
        });
        tokenService = TestBed.get(TokenService);
        // tokenService.authorizationToken = null;
        LdiStorage.Clear();
        mockBackend = TestBed.get(MockBackend);
    });

    it('Get correct api consumer token service', () => {
        mockBackend.connections.subscribe((connection: MockConnection) => {
            connection.mockRespond(new Response(new ResponseOptions({
                body: {
                    result: {
                        token: 'correct token',
                        expiry: new Date()
                    }
                }
            })));
        });
        expect(tokenService).not.toBeNull('this not null');
        tokenService.apiConsumerToken().subscribe((token: IToken) => {
            expect(token.token).toEqual('correct token');
        });

    });

    it('Get fail api consumer token service', () => {
        let error: { id: number, msg: string } = {
            id: 1,
            msg: 'error'
        };
        mockBackend.connections.subscribe((connection: MockConnection) => {
            connection.mockRespond(new Response(new ResponseOptions({ body: { error } })));
        });
        expect(tokenService).not.toBeNull('this not null');
        tokenService.apiConsumerToken().subscribe(
            (token: IToken) => expect(token.token).toBe(undefined, 'should not be resolved'),
            err => expect(err).toEqual(jasmine.objectContaining(error)));

    });

    const testUser: { userName: string, password: string } = { userName: 'user', password: 'pass' };
    const apiUserTokenConnectionSubscribe: (connection: MockConnection) => void = (connection: MockConnection) => {

        let user: { userName: string, password: string } = connection.request.json();
        if (user.userName === 'user' && user.password === 'pass') {
            connection.mockRespond(new Response(new ResponseOptions({
                body: {
                    result: {
                        token: 'correct token',
                        expiry: new Date()
                    }
                }
            })));
        } else {
            connection.mockRespond(new Response(new ResponseOptions({
                body: {
                    error: {
                        id: 3,
                        msg: 'invalid username or password'
                    }
                }
            })));
        }
    };

    it('Get correct api user token service', () => {
        mockBackend.connections.subscribe(apiUserTokenConnectionSubscribe);
        expect(tokenService).not.toBeNull('this not null');

        tokenService.apiUserToken(testUser).subscribe((token: IToken) => {
            expect(token.token).toEqual('correct token');
        });

    });

    it('Get fail api consumer token service', () => {
        let error: { id: number, msg: string } = {
            id: 3,
            msg: 'invalid username or password'
        };
        mockBackend.connections.subscribe(apiUserTokenConnectionSubscribe);
        tokenService.apiUserToken({ userName: 'user', password: 'p' }).subscribe(
            (token: IToken) => expect(token.token).toBe(undefined, 'should not be resolved'),
            err => expect(err).toEqual(jasmine.objectContaining(error)));

    });
});
