import { Directive, OnInit, Input, SimpleChanges } from '@angular/core';

import { AbstractControl, Validator, NgControl, NG_VALIDATORS, ValidatorFn, FormControl } from '@angular/forms';

@Directive({
    selector: '[atleastOneRequired][ngModel]',
    providers: [
        {
            provide: NG_VALIDATORS,
            useExisting: AtleastOneRequiredValidatorDirective,
            multi: true
        }
    ]
})

// Use this when one field is mandatory from multiple fields. 
// You can use it like this 
// e.g. [atleastOneRequired]="[prmMobile]" allFieldLabels="Phone, Mobile"

// Example:
// <input [(ngModel)]="customer.Mobile"    name="Mobile{{customer.ObjectID}}" fieldLabel="Mobile" type="text" pInputText 
//         #prmMobile="ngModel" [atleastOneRequired]="[prmPhone]" allFieldLabels="Phone, Mobile">
// <input [(ngModel)]="customer.Phone"     name="Phone{{customer.ObjectID}}"   fieldLabel="Phone" type="text" pInputText
//         #prmPhone="ngModel">

export class AtleastOneRequiredValidatorDirective implements Validator, OnInit {

    @Input('atleastOneRequired') otherControls: FormControl[];
    @Input() allFieldLabels: string;

    validator: ValidatorFn;
    currentControl: AbstractControl;

    constructor() {
        this.validator = this.requiredValidator();
    }

    ngOnInit() {
        if (this.otherControls) {
            for (let otherControl of this.otherControls) {
                otherControl.statusChanges.subscribe(
                    data => {
                        if (this.currentControl) {
                            this.currentControl.updateValueAndValidity();   //Manually call validate when other field is changed
                        }
                    }
                )
            }
        }
    }

    validate(c: AbstractControl) {
        this.currentControl = c;
        return this.validator(c);
    }

    requiredValidator(): ValidatorFn {
        return (c: AbstractControl) => {
            if (c.value) {
                return null;
            }

            if (this.otherControls) {
                for (let otherControl of this.otherControls) {
                    if (otherControl.value) {
                        return null;
                    }
                }
            }

            return {
                atleastOneRequired: {
                    valid: false,
                    additionalMsg: this.allFieldLabels
                }
            };
        }
    }
}