import { Component, Input } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { CriteriaByFamilyComponent } from './criteria-by-family.component';
import { Option } from '../../../../metamodel/models';
import { Criterion, FieldCriterion, SvomKeyword } from '../../../store/models';

describe('[Instance][Search][Component][Criteria] CriteriaByFamilyComponent', () => {
    @Component({ selector: 'app-field', template: '' })
    class FieldStubComponent {
        @Input() id: number;
        @Input() operator: string;
        @Input() label: string;
        @Input() placeholder: string;
        @Input() attributeType: string;
        @Input() criterion: Criterion;
        @Input() advancedForm: boolean;
    }

    @Component({ selector: 'app-between', template: '' })
    class BetweenStubComponent {
        @Input() id: number;
        @Input() label: string;
        @Input() placeholderMin: string;
        @Input() placeholderMax: string;
        @Input() criterion: Criterion;
    }

    @Component({ selector: 'app-select', template: '' })
    class SelectStubComponent {
        @Input() id: number;
        @Input() operator: string;
        @Input() label: string;
        @Input() options: Option[];
        @Input() criterion: Criterion;
        @Input() advancedForm: boolean;
    }

    @Component({ selector: 'app-select-multiple', template: '' })
    class SelectMultipleStubComponent {
        @Input() id: number;
        @Input() label: string;
        @Input() options: Option[];
        @Input() criterion: Criterion;
    }

    @Component({ selector: 'app-datalist', template: '' })
    class DatalistStubComponent {
        @Input() id: number;
        @Input() operator: string;
        @Input() label: string;
        @Input() placeholder: string;
        @Input() options: Option[];
        @Input() criterion: Criterion;
        @Input() advancedForm: boolean;
    }

    @Component({ selector: 'app-list', template: '' })
    class ListStubComponent {
        @Input() id: number;
        @Input() label: string;
        @Input() placeholder: string;
        @Input() criterion: Criterion;
    }

    @Component({ selector: 'app-radio', template: '' })
    class RadioStubComponent {
        @Input() id: number;
        @Input() operator: string;
        @Input() label: string;
        @Input() options: Option[];
        @Input() criterion: Criterion;
    }

    @Component({ selector: 'app-checkbox', template: '' })
    class CheckboxStubComponent {
        @Input() id: number;
        @Input() label: string;
        @Input() options: Option[];
        @Input() criterion: Criterion;
    }

    @Component({ selector: 'app-date', template: '' })
    class DateStubComponent {
        @Input() id: number;
        @Input() operator: string;
        @Input() label: string;
        @Input() placeholder: string;
        @Input() criterion: Criterion;
        @Input() advancedForm: boolean;
    }

    @Component({ selector: 'app-between-date', template: '' })
    class BetweenDateStubComponent {
        @Input() id: number;
        @Input() operator: string;
        @Input() label: string;
        @Input() criterion: Criterion;
    }

    @Component({ selector: 'app-time', template: '' })
    class TimeStubComponent {
        @Input() id: number;
        @Input() operator: string;
        @Input() label: string;
        @Input() criterion: Criterion;
        @Input() advancedForm: boolean;
    }

    @Component({ selector: 'app-datetime', template: '' })
    class DatetimeStubComponent {
        @Input() id: number;
        @Input() operator: string;
        @Input() label: string;
        @Input() criterion: Criterion;
        @Input() advancedForm: boolean;
    }

    @Component({ selector: 'app-json-criteria', template: '' })
    class JsonStubComponent {
        @Input() id: number;
        @Input() label: string;
        @Input() criterion: Criterion;
    }

    @Component({ selector: 'app-svom-json-kw-criteria', template: '' })
    class SvomJsonStubKwComponent {
        @Input() id: number;
        @Input() label: string;
        @Input() criterion: Criterion;
        @Input() criteriaList: Criterion[];
        @Input() svomKeywords: SvomKeyword[];
    }

    let component: CriteriaByFamilyComponent;
    let fixture: ComponentFixture<CriteriaByFamilyComponent>;

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [
                CriteriaByFamilyComponent,
                FieldStubComponent,
                BetweenStubComponent,
                SelectStubComponent,
                SelectMultipleStubComponent,
                DatalistStubComponent,
                ListStubComponent,
                RadioStubComponent,
                CheckboxStubComponent,
                DateStubComponent,
                BetweenDateStubComponent,
                TimeStubComponent,
                DatetimeStubComponent,
                JsonStubComponent,
                SvomJsonStubKwComponent
            ]
        });
        fixture = TestBed.createComponent(CriteriaByFamilyComponent);
        component = fixture.componentInstance;
    });

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

    it('#getOptions(attribute) should return options of attribute', () => {
        component.attributeList = [
            {
                id: 1,
                name: 'name_one',
                label: 'label_one',
                form_label: 'form_label_one',
                description: 'description_one',
                output_display: 2,
                criteria_display: 2,
                search_flag: 'ID',
                search_type: 'field',
                operator: '=',
                type: 'integer',
                display_detail: 2,
                options: [
                    { label: 'Three', value: 'three', display: 3 },
                    { label: 'One', value: 'one', display: 1 },
                    { label: 'Two', value: 'two', display: 2 }
                ]
            }
        ];
        const attributeId = 1;
        const options: Option[] = component.getOptions(attributeId);
        expect(options.length).toBe(3)
    });

    it('#getCriterion(criterionId) should return correct criterion', () => {
        component.criteriaList = [
            { 'id': 1, 'type': 'field', 'operator': 'eq', 'value': 'one' } as FieldCriterion,
            { 'id': 2, 'type': 'field', 'operator': 'eq', 'value': 'two' } as FieldCriterion
        ];
        const criterionId = 1;
        const criterion = component.getCriterion(criterionId) as FieldCriterion;
        expect(criterion.value).toBe('one');
    });

    it('raises the add criterion event when clicked', () => {
        const criterion = { id: 1, type: 'field', operator: 'eq', value: 'test' } as FieldCriterion;
        component.addCriterion.subscribe((event: FieldCriterion) => expect(event).toEqual(criterion));
        component.emitAdd(criterion);
    });

    it('raises the delete criterion event when clicked', () => {
        const criterionId = 1;
        component.deleteCriterion.subscribe((event: number) => expect(event).toEqual(1));
        component.emitDelete(criterionId);
    });
});