/*
 Copyright 2020 TATA ELXSI

 Licensed under the Apache License, Version 2.0 (the 'License');
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.

 Author: SANDHYA JS (sandhya.j@tataelxsi.co.in)
*/
/**
 * @file Healing Component
 */
import { isNullOrUndefined } from 'util';
import { HttpHeaders } from '@angular/common/http';
import { Component, Injector, Input, OnInit } from '@angular/core';
import { AbstractControl, FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { TranslateService } from '@ngx-translate/core';
import { APIURLHEADER, ERRORDATA, MODALCLOSERESPONSEDATA, URLPARAMS } from 'CommonModel';
import { environment } from 'environment';
import { VDUMAP, VDUMAPPINGS } from 'NSInstanceModel';
import { RestService } from 'RestService';
import { SharedService } from 'SharedService';
import { InstanceData, VDUR, VNFInstanceDetails } from 'VNFInstanceModel';
/**
 * Creating component
 * @Component takes HealingComponent.html as template url
 */
@Component({
    selector: 'app-healing',
    templateUrl: './HealingComponent.html',
    styleUrls: ['./HealingComponent.scss']
})
export class HealingComponent implements OnInit {
    /** To inject services @public */
    public injector: Injector;
    /** Instance for active modal service @public */
    public activeModal: NgbActiveModal;
    /** Check the loading results @public */
    public isLoadingResults: Boolean = false;
    /** Give the message for the loading @public */
    public message: string = 'PLEASEWAIT';
    /** Member index of the NS @public */
    public memberVNFIndex: {}[] = [];
    /** Items for the memberVNFIndex @public */
    public memberTypes: {}[];
    /** Items for the Day1 operation  @public */
    public day1Operation: {}[];
    /** Items for the vdu-Id and count-index @public */
    public vdu: {}[];
    /** Selected VNFInstanceId @public */
    public selectedvnfId: string = '';
    /** Contains vduId @public */
    public vduId: {};
    /** VDU Mapping @public */
    public vduMap: VDUMAP = {};
    /** Items for countIndex @public */
    public countIndex: {}[];
    /** Contains vnfInstanceId of the selected MemberVnfIndex  @public */
    public instanceId: string;
    /** FormGroup instance added to the form @ html @public */
    public healingForm: FormGroup;
    /** Form valid on submit trigger @public */
    public submitted: boolean = false;
    /** VDU Form array @private */
    private vduFormArray: FormArray;
    /** Array holds VNFR Data filtered with nsr ID @private */
    private nsIdFilteredData: {}[] = [];
    /** FormBuilder instance added to the formBuilder @private */
    private formBuilder: FormBuilder;
    /** Instance of the rest service @private */
    private restService: RestService;
    /** Controls the header form @private */
    private headers: HttpHeaders;
    /** Contains tranlsate instance @private */
    private translateService: TranslateService;
    /** Input contains component objects @private */
    @Input() private params: URLPARAMS;
    /** Contains all methods related to shared @private */
    private sharedService: SharedService;
    /** Holds teh instance of AuthService class of type AuthService @private */
    private router: Router;

    constructor(injector: Injector) {
        this.injector = injector;
        this.restService = this.injector.get(RestService);
        this.activeModal = this.injector.get(NgbActiveModal);
        this.translateService = this.injector.get(TranslateService);
        this.formBuilder = this.injector.get(FormBuilder);
        this.sharedService = this.injector.get(SharedService);
        this.router = this.injector.get(Router);
    }

    /** convenience getter for easy access to form fields */
    get f(): FormGroup['controls'] { return this.healingForm.controls; }

    /**
     * Lifecyle Hooks the trigger before component is instantiate
     */
    public ngOnInit(): void {
        this.initializeForm();
        this.getmemberIndex();
        this.day1Operation = [
            { id: 'true', name: this.translateService.instant('True') },
            { id: '', name: this.translateService.instant('False') }
        ];
        this.headers = new HttpHeaders({
            'Content-Type': 'application/json',
            Accept: 'application/json',
            'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
        });
    }

    /** Generate primitive params @public */
    get vduParamsBuilder(): FormGroup {
        return this.formBuilder.group({
            vduId: [null],
            countIndex: [null],
            runDay1: [null]
        });
    }

    /** Initialize Healing Forms @public */
    public initializeForm(): void {
        this.healingForm = this.formBuilder.group({
            memberIndex: [null, [Validators.required]],
            run_day1: [null],
            vdu: this.formBuilder.array([])
        });
    }

    /** Handle FormArray Controls @public */
    public getControls(): AbstractControl[] {
        return (this.healingForm.get('vdu') as FormArray).controls;
    }

    /** Get the member-vnf-index from NS Package -> vnf-profile @private */
    private getmemberIndex(): void {
        this.isLoadingResults = true;
        const vnfInstanceData: {}[] = [];
        this.restService.getResource(environment.VNFINSTANCES_URL).subscribe((vnfInstancesData: VNFInstanceDetails[]): void => {
            vnfInstancesData.forEach((vnfData: VNFInstanceDetails): void => {
                const nsrId: string = 'nsr-id-ref';
                const memberIndex: string = 'member-vnf-index-ref';
                const vnfDataObj: {} =
                {
                    VNFInstanceId: vnfData._id,
                    // eslint-disable-next-line security/detect-object-injection
                    MemberIndex: vnfData[memberIndex],
                    // eslint-disable-next-line security/detect-object-injection
                    NS: vnfData[nsrId]
                };
                vnfInstanceData.push(vnfDataObj);
            });
            const nsId: string = 'NS';
            // eslint-disable-next-line security/detect-object-injection
            this.nsIdFilteredData = vnfInstanceData.filter((vnfdData: {}[]): boolean => vnfdData[nsId] === this.params.id);
            this.nsIdFilteredData.forEach((resVNF: InstanceData): void => {
                const assignMemberIndex: {} = {
                    id: resVNF.MemberIndex,
                    vnfinstanceId: resVNF.VNFInstanceId
                };
                this.memberVNFIndex.push(assignMemberIndex);
            });
            this.memberTypes = this.memberVNFIndex;
            this.isLoadingResults = false;
        }, (error: ERRORDATA): void => {
            this.restService.handleError(error, 'get');
            this.isLoadingResults = false;
        });
    }

    /** Getting vdu-id & count-index from VNFInstance API */
    public getVdu(id: string): void {
        this.isLoadingResults = true;
        this.vdu = [];
        const vnfInstanceData: {}[] = [];
        this.instanceId = id;
        if (!isNullOrUndefined(id)) {
            this.restService.getResource(environment.VNFINSTANCES_URL + '/' + id).
                subscribe((vnfInstanceDetail: VNFInstanceDetails): void => {
                    this.selectedvnfId = vnfInstanceDetail['vnfd-ref'];
                    if (!isNullOrUndefined(vnfInstanceDetail.vdur)) {
                        vnfInstanceDetail.vdur.forEach((vdu: VDUR): void => {
                            const vnfInstanceDataObj: {} =
                            {
                                'count-index': vdu['count-index'],
                                VDU: vdu['vdu-id-ref']
                            };
                            vnfInstanceData.push(vnfInstanceDataObj);
                        });
                        this.vdu = vnfInstanceData;
                        this.vduId = this.vdu.filter((vdu: { VDU?: string }, index: number, self: {}[]): {} =>
                            index === self.findIndex((t: { VDU?: string }): {} => (
                                // eslint-disable-next-line security/detect-object-injection
                                t.VDU === vdu.VDU
                            ))
                        );
                        this.isLoadingResults = false;
                    }
                }
                    , (error: ERRORDATA): void => {
                        this.restService.handleError(error, 'get');
                        this.isLoadingResults = false;
                    });
        }
    }

    /** Getting count-index by filtering id  */
    public getCountIndex(id: string): void {
        const VDU: string = 'VDU';
        // eslint-disable-next-line security/detect-object-injection
        this.countIndex = this.vdu.filter((vnfdData: {}[]): boolean => vnfdData[VDU] === id);
    }


    /** Add vdu @public */
    public addVdu(): void {
        this.vduFormArray = this.healingForm.get('vdu') as FormArray;
        this.vduFormArray.push(this.vduParamsBuilder);
    }

    /** Remove vdu @public */
    public removeMapping(index: number): void {
        this.vduFormArray.removeAt(index);
    }

    /** If form is valid and call healInstances method to initialize healing @public */
    public manualHealingTrigger(): void {
        this.submitted = true;
        let healingPayload: object = {};
        this.sharedService.cleanForm(this.healingForm);
        if (this.healingForm.invalid) { return; } // Proceed, onces form is valid
        this.vduMap.vdu_mappings = [];
        this.healingForm.value.vdu.forEach((res: VDUMAPPINGS): void => {
            this.vduMap.vdu_mappings.push({ 'vdu-id': res.vduId, 'count-index': res.countIndex, 'run-day1': Boolean(res.runDay1) });
        });
        if (this.vduMap.vdu_mappings.length !== 0) {
            healingPayload = {
                healVnfData:
                    [{
                        vnfInstanceId: this.instanceId,
                        cause: 'manual',
                        additionalParams: {
                            'run-day1': false,
                            vdu: this.vduMap.vdu_mappings
                        }
                    }]
            };
        } else {
            healingPayload = {
                healVnfData:
                    [{
                        vnfInstanceId: this.instanceId,
                        cause: 'manual',
                        additionalParams: {
                            'run-day1': Boolean(this.getFormControl('run_day1').value)
                        }
                    }]
            };
        }
        this.healInstances(healingPayload);
    }

    /** Initialize the healing @public */
    public healInstances(healingPayload: object): void {
        this.isLoadingResults = true;
        const apiURLHeader: APIURLHEADER = {
            url: environment.NSDINSTANCES_URL + '/' + this.params.id + '/heal',
            httpOptions: { headers: this.headers }
        };
        const modalData: MODALCLOSERESPONSEDATA = {
            message: 'Done'
        };
        this.restService.postResource(apiURLHeader, healingPayload).subscribe((result: {}): void => {
            this.activeModal.close(modalData);
            this.router.navigate(['/instances/ns/history-operations/' + this.params.id]).catch((): void => {
                // Catch Navigation Error
            });
        }, (error: ERRORDATA): void => {
            this.restService.handleError(error, 'post');
            this.isLoadingResults = false;
        });
    }

    /** Used to get the AbstractControl of controlName passed @private */
    private getFormControl(controlName: string): AbstractControl {
        // eslint-disable-next-line security/detect-object-injection
        return this.healingForm.controls[controlName];
    }
}
