/* Copyright CloudLinux Zug GmbH 2010-2018 All Rights Reserved
 *
 * Licensed under CLOUD LINUX LICENSE AGREEMENT
 * http://cloudlinux.com/docs/LICENSE.TXT
 */

import { ConfigRepo } from '../app/repository/config_repo';
import { AppState } from '../app/app.service';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { XHR } from '../app/utils/xhr';
import { NotificationsService } from '../app/services/notifiaction_service';

let configRepo: ConfigRepo;
let xhr: XHR;
let sequence;

const res1 = {
    a: '2',
    b: 3
};

const res2 = {
    options: {show: true}
};

function* postResponseGenerator() {
    yield res1;
    return res2;
}

class XHRMock {
    post(params: Object, mockJson = ''): Promise<any>{
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(sequence.next());
            }, 100);
        });
    }
}

class NotificationsMock {}


describe('Config Repo saving promise tests', () => {

    beforeEach(async () => {
       TestBed.configureTestingModule({
           declarations: [ ],
           providers: [
               {provide: XHR, useClass: XHRMock},
               {provide: NotificationsService, useClass: NotificationsMock},
               AppState
           ],
           schemas: [ NO_ERRORS_SCHEMA ]
       }).compileComponents();
    });

    beforeEach( () => {
        xhr = TestBed.get(XHR);
        sequence = postResponseGenerator();
        configRepo = new ConfigRepo(
            TestBed.get(AppState),
            xhr,
            TestBed.get(NotificationsService)
        );
    });

    it('Should return correct value', async done => {
        spyOn(xhr, 'post').and.callThrough();
        let result = await configRepo.getConfig();
        expect(result.value).toEqual(res1);
        expect(xhr.post).toHaveBeenCalledTimes(1);
        done();
    });

    it('Should return same value when called multiple times', async done => {
        spyOn(xhr, 'post').and.callThrough();
        let results = await Promise.all([
            configRepo.getConfig(),
            configRepo.getConfig(),
            configRepo.getConfig()
        ]);
        expect(results[0].value).toEqual(res1);
        expect(results[1].value).toEqual(res1);
        expect(results[2].value).toEqual(res1);
        expect(xhr.post).toHaveBeenCalledTimes(1);
        done();
    });

    // TODO change this test if caching for requests will be implemented
    it('Should return different values if called after promise resolving', async done => {
        spyOn(xhr, 'post').and.callThrough();
        let result1 = await configRepo.getConfig();
        let results2 = await Promise.all([
            configRepo.getConfig(),
            configRepo.getConfig()
        ]);
        expect(result1.value).toEqual(res1);
        expect(results2[0].value).toEqual(res2);
        expect(results2[0].value).toEqual(res2);
        expect(xhr.post).toHaveBeenCalledTimes(2);
        done();
    });
});

