/*
 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: KUMARAN M (kumaran.m@tataelxsi.co.in), RAJESH S (rajesh.s@tataelxsi.co.in), BARATH KUMAR R (barath.r@tataelxsi.co.in)
 */
/**
 * @file Provider for Shared Service
 */
import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { EventEmitter, Injectable, Output } from '@angular/core';
import { FormArray, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import {
    CONSTANTNUMBER,
    DOMAINS,
    ERRORDATA,
    FILESETTINGS,
    GETAPIURLHEADER,
    PACKAGEINFO,
    PAGERSMARTTABLE,
    SMARTTABLECLASS,
    TARSETTINGS,
    TYPESECTION
} from 'CommonModel';
import { environment } from 'environment';
import * as HttpStatus from 'http-status-codes';
import * as untar from 'js-untar';
import { ActiveToast, ToastrService } from 'ngx-toastr';
import * as pako from 'pako';
import { RestService } from 'RestService';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

/** This is added globally by the tar.js library */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
declare const Tar: any;

/**
 * An Injectable is a class adorned with the @Injectable decorator function.
 * @Injectable takes a metadata object that tells Angular how to compile and run module code
 */
@Injectable({
    providedIn: 'root'
})
/** Exporting a class @exports SharedService */
export class SharedService {
    /** call the parent using event information @private */
    @Output() public dataEvent: EventEmitter<{}> = new EventEmitter<{}>();

    /** Variables to hold regexp pattern for URL */
    public REGX_URL_PATTERN: RegExp = new RegExp(/^(http?|ftp|https):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z0-9]{2,15})(:((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4})))*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/);

    /** Variables to hold regexp pattern for IP Address */
    public REGX_IP_PATTERN: RegExp = new RegExp(/^(?:(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(?!$)|$)){4}$/);

    /** Variables to hold regexp pattern for Port Number */
    public REGX_PORT_PATTERN: RegExp = new RegExp(/^((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4}))$/);

    /** Variables to hold regexp pattern for DPID */
    public REGX_DPID_PATTERN: RegExp = new RegExp(/^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){7}$/);

    /** Variable to hold regexp pattern for password */
    public REGX_PASSWORD_PATTERN: RegExp = new RegExp(/^.*(?=.{8,})((?=.*[!@#$%^&*()\-_=+{};:,<.>]){1})(?=.*\d)((?=.*[a-z]){1})((?=.*[A-Z]){1}).*$/);

    /** Variables to hold regexp pattern for Latitude */
    public REGX_LAT_PATTERN: RegExp = new RegExp(/^(\+|-)?(?:90(?:(?:\.0{1,6})?)|(?:[0-9]|[1-8][0-9])(?:(?:\.[0-9]{1,15})?))$/);

    /** Variables to hold regexp pattern for Longitude */
    public REGX_LONG_PATTERN: RegExp = new RegExp(/^(\+|-)?(?:180(?:(?:\.0{1,6})?)|(?:[0-9]|[1-9][0-9]|1[0-7][0-9])(?:(?:\.[0-9]{1,15})?))$/);

    /** Variable to hold regexp pattern for EMAIL */
    public REGX_EMAIL_PATTERN: RegExp = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

    /** Variables to hold maxlength for the description @public */
    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
    public MAX_LENGTH_DESCRIPTION: number = 500;

    /** Variables to hold maxlength for the name @public */
    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
    public MAX_LENGTH_NAME: number = 50;

    /** FormGroup instance added to the form @ html @public */
    public formGroup: FormGroup;

    /** Controls the go to top button on scroll  @public */
    public showGotoTop: boolean;

    /** Holds OSM Version value @public */
    public osmVersion: string;

    /** Holds Last Login Toaster Message @public */
    public lastLoginMessage: string;

    /** Holds Failed Attempts Toaster Message @public */
    public failedAttemptsMessage: string;

    /** Holds No Of Days Toaster Message @public */
    public daysMessage: string;

    /** express number for time manupulation -2 */
    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
    private epochTimeMinus2: number = -2;

    /** express number for time manupulation 1000 */
    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
    private epochTime1000: number = 1000;

    /** express number for time manupulation 60 */
    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
    private epochTime60: number = 60;

    /** express number for time manupulation 24 */
    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
    private epochTime24: number = 24;

    /** Random string generator length */
    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
    private randomStringLength: number = 4;

    /** express number for rgb manipulation */
    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
    private colourHour: number = 10;

    /** express number for rgb manipulation*/
    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
    private colourMin: number = 5;

    /** Instance of the rest service @private */
    private restService: RestService;

    /** Service holds the router information @private */
    private router: Router;

    /** Check for the root directory @private */
    // eslint-disable-next-line @typescript-eslint/no-magic-numbers
    private directoryCount: number = 2;

    /** express number for time manupulation 1000 */
    private toasterSettings: {} = {
        enableHtml: true,
        closeButton: true,
        timeOut: 2000
    };

    /** Contains tranlsate instance @private */
    private translateService: TranslateService;

    /** Contains toaster instance @private */
    private toaster: ToastrService;

    constructor(restService: RestService, router: Router, translateService: TranslateService, toaster: ToastrService) {
        this.restService = restService;
        this.router = router;
        this.translateService = translateService;
        this.toaster = toaster;
    }

    /** convert epoch time function @public */
    public convertEpochTime(unixtimestamp: number): string {
        if (!isNullOrUndefined(unixtimestamp)) {
            const monthsArr: string[] = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
            const date: Date = new Date(unixtimestamp * this.epochTime1000);
            const year: number = date.getFullYear();
            const month: string = monthsArr[date.getMonth()];
            const day: number = date.getDate();
            const hours: number = date.getHours();
            const minutes: string = '0' + date.getMinutes();
            const seconds: string = '0' + date.getSeconds();
            // eslint-disable-next-line deprecation/deprecation
            return month + '-' + day + '-' + year + ' ' + hours + ':' + minutes.substr(this.epochTimeMinus2) + ':'
                // eslint-disable-next-line deprecation/deprecation
                + seconds.substr(this.epochTimeMinus2);
        }
        return this.translateService.instant('NODATE');
    }

    /** convert epoch time function to No of days @public */
    public converEpochToDays(date: string): number {
        if (!isNullOrUndefined(date)) {
            const today: Date = new Date();
            const accountDate: Date = new Date(date);
            const toasterDate: number = (accountDate.getTime() -
                today.getTime()) / this.epochTime1000 / this.epochTime60 / this.epochTime60 / this.epochTime24;
            if (toasterDate >= 0 || toasterDate < 1) {
                return Math.round(toasterDate);
            }
            return Math.floor(toasterDate);
        }
        return this.translateService.instant('N/A');
    }

    /** show toaster for password & account expiry @public */
    public showToaster(lastLogin: string, failedAttempts: string, passwordNoOfDays: string,
        accountNoOfDays: string, passwordExpireMessage: string, accountExpireMessage: string,
        passwordMessage: string, accountMessage: string): ActiveToast<string> {
        this.lastLoginMessage = this.translateService.instant('PAGE.LOGIN.LASTACCESS');
        this.failedAttemptsMessage = this.translateService.instant('PAGE.LOGIN.FAILED');
        return this.toaster.info(this.lastLoginMessage + ':' + '&nbsp' + lastLogin +
            '</br>' + this.failedAttemptsMessage + ':' + '&nbsp' + failedAttempts +
            '</br>' + passwordExpireMessage + '&nbsp' + passwordNoOfDays + '&nbsp' + passwordMessage +
            '</br>' + accountExpireMessage + '&nbsp' + accountNoOfDays + '&nbsp' + accountMessage,
            this.translateService.instant('PAGE.LOGIN.LOGINHISTORY'), this.toasterSettings);
    }

    /** show toaster for password expiry @public */
    public passwordToaster(lastLogin: string, failedAttempts: string, passwordNoOfDays: string,
        passwordExpireMessage: string, passwordMessage: string): ActiveToast<string> {
        this.lastLoginMessage = this.translateService.instant('PAGE.LOGIN.LASTACCESS');
        this.failedAttemptsMessage = this.translateService.instant('PAGE.LOGIN.FAILED');
        return this.toaster.info(this.lastLoginMessage + ':' + '&nbsp' + lastLogin +
            '</br>' + this.failedAttemptsMessage + ':' + '&nbsp' + failedAttempts +
            '</br>' + passwordExpireMessage + '&nbsp' + passwordNoOfDays + '&nbsp' + passwordMessage,
            this.translateService.instant('PAGE.LOGIN.LOGINHISTORY'), this.toasterSettings);
    }

    /** show toaster for account expiry @public */
    public accountToaster(lastLogin: string, failedAttempts: string,
        accountNoOfDays: string, accountExpireMessage: string, accountMessage: string): ActiveToast<string> {
        this.lastLoginMessage = this.translateService.instant('PAGE.LOGIN.LASTACCESS');
        this.failedAttemptsMessage = this.translateService.instant('PAGE.LOGIN.FAILED');
        return this.toaster.info(this.lastLoginMessage + ':' + '&nbsp' + lastLogin +
            '</br>' + this.failedAttemptsMessage + ':' + '&nbsp' + failedAttempts +
            '</br>' + accountExpireMessage + '&nbsp' + accountNoOfDays + '&nbsp' + accountMessage,
            this.translateService.instant('PAGE.LOGIN.LOGINHISTORY'), this.toasterSettings);
    }

    /** Download Files function @public */
    public downloadFiles(name: string, binaryData: Blob[], filetype: string): void {
        const downloadLink: HTMLAnchorElement = document.createElement('a');
        downloadLink.href = window.URL.createObjectURL(new Blob(binaryData, { type: filetype }));
        if (name !== undefined) {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            const newVariable: any = window.navigator;
            if (newVariable.msSaveOrOpenBlob) {
                newVariable.msSaveBlob(new Blob(binaryData, { type: filetype }), 'OSM_Export_' + name + '.tar.gz');
            } else {
                downloadLink.setAttribute('download', 'OSM_Export_' + name + '.tar.gz');
                document.body.appendChild(downloadLink);
                downloadLink.click();
            }
        }
    }

    /** Call this method after delete perform action is completed in the ng-smart-table data @public */
    public callData(): void {
        this.dataEvent.emit();
    }

    /** Generate random string @public */
    public randomString(): string {
        let result: string = '';
        for (let randomStringRef: number = this.randomStringLength; randomStringRef > 0; --randomStringRef) {
            result += new Date().getSeconds();
        }
        return result;
    }

    /** Function to read uploaded file String @public */
    public async getFileString(files: FileList, fileType: string): Promise<string | ArrayBuffer> {
        const reader: FileReader = new FileReader();
        return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
            if (this.vaildataFileInfo(files[0], fileType)) {
                this.readFileContent(reader, files[0], fileType);
            } else {
                reject('typeError');
            }
            reader.onload = (): void => {
                if (reader.result === null) {
                    reject('contentError');
                }
                resolve(reader.result);
            };
            reader.onerror = (event: Event): void => {
                reject('contentError');
            };
        });
    }

    /** Method to handle tar and tar.gz file for shared YAML file content @public */
    public async targzFile(packageInfo: PACKAGEINFO): Promise<string | ArrayBuffer> {
        return new Promise<string | ArrayBuffer>((resolve: Function, reject: Function): void => {
            const httpOptions: GETAPIURLHEADER = this.getHttpOptions();
            let apiUrl: string = '';
            apiUrl = packageInfo.packageType === 'nsd' ? environment.NSDESCRIPTORS_URL + '/' + packageInfo.id + '/nsd_content' :
                environment.VNFPACKAGES_URL + '/' + packageInfo.id + '/package_content';
            this.restService.getResource(apiUrl, httpOptions).subscribe((response: ArrayBuffer): void => {
                try {
                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
                    const tar: any = new Tar();
                    const originalInput: Uint8Array = pako.inflate(response, { to: 'Uint8Array' });
                    untar(originalInput.buffer).then((extractedFiles: TARSETTINGS[]): void => {
                        const getFoldersFiles: {}[] = extractedFiles;
                        const folderNameStr: string = extractedFiles[0].name;
                        getFoldersFiles.forEach((value: TARSETTINGS): void => {
                            const fileValueObj: FILESETTINGS = this.createFileValueObject(value);
                            const getRootFolder: string[] = value.name.split('/');
                            if (value.name.startsWith(folderNameStr) &&
                                (value.name.endsWith('.yaml') || value.name.endsWith('.yml')) &&
                                getRootFolder.length === this.directoryCount) {
                                tar.append(value.name, packageInfo.descriptor, fileValueObj);
                            } else {
                                if (value.type !== 'L') {
                                    tar.append(value.name, new Uint8Array(value.buffer), fileValueObj);
                                }
                            }
                        });
                        const out: Uint8Array = tar.out;
                        const originalOutput: Uint8Array = pako.gzip(out);
                        resolve(originalOutput.buffer);
                    }, (err: string): void => {
                        reject('');
                    });
                } catch (e) {
                    reject('');
                }
            }, (error: HttpErrorResponse): void => {
                if (error.status === HttpStatus.NOT_FOUND || error.status === HttpStatus.UNAUTHORIZED) {
                    this.router.navigateByUrl('404', { skipLocationChange: true }).catch((): void => {
                        // Catch Navigation Error
                    });
                } else {
                    this.restService.handleError(error, 'get');
                    reject('');
                }
            });
        });
    }

    /** Method to return the file information @public */
    public createFileValueObject(value: TARSETTINGS): FILESETTINGS {
        return {
            type: value.type,
            linkname: value.linkname,
            owner: value.uname,
            group: value.gname
        };
    }

    /** Method to check given string is JSON or not @public */
    public checkJson(jsonString: string): boolean {
        jsonString = jsonString.replace(/'/g, '"');
        try {
            JSON.parse(jsonString);
        } catch (e) {
            return false;
        }
        return true;
    }

    /** Clean the form before submit @public */
    public cleanForm(formGroup: FormGroup, formName?: String): void {
        Object.keys(formGroup.controls).forEach((key: string) => {
            if ((!isNullOrUndefined((formGroup.get(key) as FormArray | FormGroup).controls)) && key !== 'config') {
                // eslint-disable-next-line @typescript-eslint/no-shadow
                for (const { item, index } of (formGroup.get(key).value).map((item: {}, index: number) => ({ item, index }))) {
                    // eslint-disable-next-line security/detect-object-injection
                    const newFormGroup: FormGroup = (formGroup.get(key) as FormArray).controls[index] as FormGroup;
                    this.cleanForm(newFormGroup);
                }
            } else if (formGroup.get(key).value !== undefined && formGroup.get(key).value !== null && key !== 'config') {
                if (!Array.isArray(formGroup.get(key).value)) {
                    if (typeof formGroup.get(key).value === 'string') {
                        formGroup.get(key).setValue(formGroup.get(key).value.trim());
                    }
                }
            } else if (key === 'config' && formName === 'vim') {
                const newFormGroup: FormGroup = formGroup.get(key) as FormGroup;
                this.cleanForm(newFormGroup);
            }
        });
    }

    /** Method to return the config of pager value for ngSmarttable @public */
    public paginationPagerConfig(): PAGERSMARTTABLE {
        return {
            display: true,
            perPage: environment.paginationNumber
        };
    }

    /** Method to return the class for the table for ngSmarttable @public */
    public tableClassConfig(): SMARTTABLECLASS {
        return {
            class: 'table list-data'
        };
    }

    /** Method to return all languages name and its code @public */
    public languageCodeList(): {}[] {
        return [
            { code: 'en', language: 'English' },
            { code: 'es', language: 'Spanish' },
            { code: 'pt', language: 'Portuguese' },
            { code: 'de', language: 'German' }
        ];
    }

    /** Fetch OSM Version @public */
    public fetchOSMVersion(): void {
        this.restService.getResource(environment.OSM_VERSION_URL).subscribe((res: { version: string }): void => {
            const version: string[] = res.version.split('+');
            if (!isNullOrUndefined(version[0])) {
                this.osmVersion = version[0];
                sessionStorage.setItem('version', version[0]);
            } else {
                this.osmVersion = null;
            }
        }, (error: ERRORDATA): void => {
            this.osmVersion = null;
            this.restService.handleError(error, 'get');
        });
    }

    /** Random RGB color code generator @public */
    public generateColor(): string {
        const x: number = Math.floor((new Date().getHours()) * this.colourHour);
        const y: number = Math.floor((new Date().getMinutes()) * this.colourMin);
        const z: number = Math.floor((new Date().getSeconds()) * this.colourMin);
        return 'rgb(' + x + ',' + y + ',' + z + ')';
    }

    /** Add custom name/tag to the dropdown @public */
    public addCustomTag(tag: string): string {
        return tag;
    }

    /** Fetch file extension @public */
    public fetchFileExtension(fileInfo: FileList): string {
        return fileInfo[0].name.substring(fileInfo[0].name.lastIndexOf('.') + 1);
    }

    /** Get domain name @private */
    public getDomainName(): Observable<TYPESECTION[]> {
        return this.restService.getResource(environment.DOMAIN_URL).pipe(map((domains: DOMAINS): TYPESECTION[] => {
            const domainList: TYPESECTION[] = [];
            try {
                let domainNames: string[] = [];
                if (!isNullOrUndefined(domains.project_domain_name)) {
                    domainNames = domainNames.concat(domains.project_domain_name.split(','));
                }
                if (!isNullOrUndefined(domains.user_domain_name)) {
                    domainNames = domainNames.concat(domains.user_domain_name.split(','));
                }
                domainNames = Array.from(new Set(domainNames));
                if (domainNames.length > 0) {
                    domainNames.forEach((domainName: string): void => {
                        if (!domainName.endsWith(':ro')) {
                            domainList.push({ title: domainName, value: domainName });
                        }
                    });
                }
                return domainList;
            } catch (e) {
                return domainList;
            }
        }));
    }

    /** Sorting the list based on date @public */
    public compareFunction = (dir: number, a: string, b: string): number => {
        const first: number = new Date(a).getTime();
        const second: number = new Date(b).getTime();
        if (first < second) {
            return -1 * dir;
        }
        if (first > second) {
            return dir;
        }
        return 0;
    };

    /** Method to validate file extension and size @private */
    private vaildataFileInfo(fileInfo: File, fileType: string): boolean {
        const extension: string = fileInfo.name.substring(fileInfo.name.lastIndexOf('.') + 1);
        const packageSize: number = CONSTANTNUMBER.oneMB * environment.packageSize;
        if (fileType === 'yaml' && (extension.toLowerCase() === 'yaml' || extension.toLowerCase() === 'yml')
            && fileInfo.size <= packageSize) {
            return true;
        } else if (extension.toLowerCase() === fileType && fileInfo.size <= packageSize) {
            return true;
        }
        return false;
    }

    /** Method to read file content based on type @private */
    private readFileContent(reader: FileReader, fileInfo: File, fileType: string): void {
        if (fileType === 'gz') {
            reader.readAsArrayBuffer(fileInfo);
        } else {
            reader.readAsText(fileInfo);
        }
    }

    /** Method to handle http options @public */
    private getHttpOptions(): GETAPIURLHEADER {
        return {
            headers: new HttpHeaders({
                Accept: 'application/gzip, application/json',
                'Cache-Control': 'no-cache, no-store, must-revalidate, max-age=0'
            }),
            responseType: 'arraybuffer'
        };
    }
}

/** Method to handle null or undefined @public */
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
export const isNullOrUndefined = (data: any): boolean => data === null || data === undefined;

