/**
 * This file is part of Anis Client.
 *
 * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

import { Component, Input } from '@angular/core';
import { TestBed, waitForAsync, ComponentFixture  } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { RouterTestingModule } from '@angular/router/testing';

import { provideMockStore, MockStore } from '@ngrx/store/testing';
import { of } from 'rxjs';

import { InstanceComponent } from './instance.component';
import { AppConfigService } from 'src/app/app-config.service';
import { StyleService } from 'src/app/shared/services/style.service';
import * as authActions from 'src/app/auth/auth.actions';
import { Instance, WebpageFamily, Webpage } from '../metamodel/models';
import { UserProfile } from '../auth/user-profile.model';
import * as datasetFamilyActions from '../metamodel/actions/dataset-family.actions';
import * as datasetActions from '../metamodel/actions/dataset.actions';
import * as datasetGroupActions from 'src/app/metamodel/actions/dataset-group.actions';
import * as webpageFamilyActions from 'src/app/metamodel/actions/webpage-family.actions';
import * as webpageActions from 'src/app/metamodel/actions/webpage.actions';

describe('[Instance] InstanceComponent', () => {
    @Component({ selector: 'app-instance-navbar', template: '' })
    class NavbarStubComponent {
        @Input() isAuthenticated: boolean;
        @Input() userProfile: UserProfile = null;
        @Input() userRoles: string[];
        @Input() authenticationEnabled: boolean;
        @Input() apiUrl: string;
        @Input() adminRoles: string[];
        @Input() instance: Instance;
        @Input() webpageFamilyList: WebpageFamily[] = null;
        @Input() webpageList: Webpage[] = null;
        @Input() firstWebpage: Webpage = null;
    }

    let component: InstanceComponent;
    let fixture: ComponentFixture<InstanceComponent>;
    let store: MockStore;
    let appConfigServiceStub = new AppConfigService();
    let styleServiceStub = new StyleService();

    beforeEach(waitForAsync(() => {
        TestBed.configureTestingModule({
            imports: [RouterTestingModule, HttpClientTestingModule],
            declarations: [
                InstanceComponent,
                NavbarStubComponent
            ],
            providers: [
                provideMockStore({ }),
                { provide: AppConfigService, useValue: appConfigServiceStub },
                { provide: StyleService, useValue: styleServiceStub }
            ]
        }).compileComponents();
        fixture = TestBed.createComponent(InstanceComponent);
        component = fixture.componentInstance;
        store = TestBed.inject(MockStore);
        document.body.innerHTML =
            '<title id="title">Default title</title>' +
            '<link id="favicon" href="">';
    }));

    it('should create the component', () => {
        expect(component).toBeDefined();
    });

    it('should execute ngOnInit lifecycle', (done) => {
        const instance: Instance = {
            name: 'myInstance',
            label: 'My Instance',
            description: 'My Instance description',
            scientific_manager: 'M. Dupont',
            instrument: 'Multiple',
            wavelength_domain: 'Visible',
            display: 10,
            data_path: 'data/path',
            files_path: 'files',
            public: true,
            portal_logo: 'logo.png',
            design_color: 'green',
            design_background_color: 'darker green',
            design_logo: '/path/to/logo',
            design_favicon: '/path/to/favicon',
            navbar_background_color: '#F8F9FA',
            navbar_border_bottom_color: '#DEE2E6',
            navbar_color_href: '#000000',
            navbar_font_family: 'Roboto, sans-serif',
            navbar_sign_in_btn_color: '#28A745',
            navbar_user_btn_color: '#7AC29A',
            footer_background_color: '#F8F9FA',
            footer_border_top_color: '#DEE2E6',
            footer_text_color: '#000000',
            footer_logos: null,
            family_border_color: '#DFDFDF',
            family_header_background_color: '#F7F7F7',
            family_title_color: '#007BFF',
            family_title_bold: false,
            family_background_color: '#FFFFFF',
            family_color: '#212529',
            progress_bar_title: 'Dataset search',
            progress_bar_title_color: '#000000',
            progress_bar_subtitle: 'Select a dataset, add criteria, select output columns and display the result.',
            progress_bar_subtitle_color: '#6C757D',
            progress_bar_step_dataset_title: 'Dataset selection',
            progress_bar_step_criteria_title: 'Search criteria',
            progress_bar_step_output_title: 'Output columns',
            progress_bar_step_result_title: 'Result table',
            progress_bar_color: '#E9ECEF',
            progress_bar_active_color: '#7AC29A',
            progress_bar_circle_color: '#FFFFFF',
            progress_bar_circle_icon_color: '#CCCCCC',
            progress_bar_circle_icon_active_color: '#FFFFFF',
            progress_bar_text_color: '#91B2BF',
            result_header_background_color: '#E9ECEF',
            result_header_text_color: '#000000',
            result_header_btn_color: '#007BFF',
            result_header_btn_hover_color: '#0069D9',
            result_header_btn_text_color: '#FFFFFF',
            result_datatable_bordered: true,
            result_datatable_border_color: '#DEE2E6',
            result_datatable_header_background_color: '#FFFFFF',
            result_datatable_header_text_color: '#000000',
            result_datatable_rows_background_color: '#FFFFFF',
            result_datatable_rows_text_color: '#000000',
            result_datatable_sorted_color: '#C5C5C5',
            result_datatable_sorted_active_color: '#000000',
            result_datatable_link_color: '#007BFF',
            result_datatable_link_hover_color: '#0056B3',
            result_datatable_rows_selected_color: '#7AC29A',
            samp_enabled: true,
            back_to_portal: true,
            user_menu_enabled: true,
            search_by_criteria_allowed: true,
            search_by_criteria_label: 'Search',
            search_multiple_allowed: true,
            search_multiple_label: 'Search multiple',
            search_multiple_all_datasets_selected: false,
            documentation_allowed: true,
            documentation_label: 'Documentation',
            nb_dataset_families: 1,
            nb_datasets: 2
        };

        const webpage: Webpage = {
            id: 1,
            name: 'home',
            label: 'Home',
            title: 'Home',
            display: 10,
            icon: 'fas fa-home',
            content: '<p>Hello</p>',
            style_sheet: '',
            id_webpage_family: 1
        }

        component.instance = of(instance);
        component.firstWebpage = of(webpage);
        const spy = jest.spyOn(store, 'dispatch');
        component.ngOnInit();
        Promise.resolve(null).then(function() {
            expect(spy).toHaveBeenCalledTimes(5);
            expect(spy).toHaveBeenCalledWith(datasetFamilyActions.loadDatasetFamilyList());
            expect(spy).toHaveBeenCalledWith(datasetActions.loadDatasetList());
            expect(spy).toHaveBeenCalledWith(datasetGroupActions.loadDatasetGroupList());
            expect(spy).toHaveBeenCalledWith(webpageFamilyActions.loadWebpageFamilyList());
            expect(spy).toHaveBeenCalledWith(webpageActions.loadWebpageList());
            expect(component.favIcon.href).toEqual('http://localhost/undefined/instance/myInstance/file-explorer/path/to/favicon');
            done();
        });
    });

    it('#authenticationEnabled() should return authentication enabled config key value', () => {
        appConfigServiceStub.authenticationEnabled = true;
        expect(component.getAuthenticationEnabled()).toBeTruthy();
    });

    it('#getApiUrl() should return API URL', () => {
        appConfigServiceStub.apiUrl = 'http:test.com';
        expect(component.getApiUrl()).toEqual('http:test.com');
    });

    it('#login() should dispatch login action', () => {
        const spy = jest.spyOn(store, 'dispatch');
        component.login();
        expect(spy).toHaveBeenCalledTimes(1);
        expect(spy).toHaveBeenCalledWith(authActions.login({ redirectUri: window.location.toString() }));
    });

    it('#logout() should dispatch logout action', () => {
        const spy = jest.spyOn(store, 'dispatch');
        component.logout();
        expect(spy).toHaveBeenCalledTimes(1);
        expect(spy).toHaveBeenCalledWith(authActions.logout());
    });

    it('#openEditProfile() should dispatch open edit profile action', () => {
        const spy = jest.spyOn(store, 'dispatch');
        component.openEditProfile();
        expect(spy).toHaveBeenCalledTimes(1);
        expect(spy).toHaveBeenCalledWith(authActions.openEditProfile());
    });

    it('should unsubscribe to instance when component is destroyed', () => {
        component.instanceSubscription = of().subscribe();
        const spy = jest.spyOn(component.instanceSubscription, 'unsubscribe');
        component.ngOnDestroy();
        expect(spy).toHaveBeenCalledTimes(1);
    });
});