/*
 *******************************************************************************
 * Copyright (c) 2018 Contributors to the Eclipse Foundation
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 *******************************************************************************
*/

import { Branch } from './../model/branch';
import { Injectable, EventEmitter } from '@angular/core';
import { User } from '../model/user';
import { Status } from '../model/status';
import { ToasterMessage } from '../common/banner-message';
import { Globals } from '../common/globals';
import { UserMap } from '../common/user-map';
import { JwtPayload } from '../model/jwt-payload';
import { JwtHelperService } from '@auth0/angular-jwt';
import { CostCenter } from '../model/cost-center';
import { BackendSettings } from './../model/backend-settings';
import { GridMeasure } from '../model/grid-measure';
import { UserSettings } from '../model/user-settings';
import { StatusMainFilter } from '../model/status-main-filter';
import { Territory } from '../model/territory';

@Injectable()
export class SessionContext {

    public centralHttpResultCode$: EventEmitter<number> = new EventEmitter<number>();
    public settings;
    public reminderAvailable = false;
    public importFileAvailable = false;
    public filterExpanded = false;
    public userMap: UserMap = null;
    public userAuthenticated: boolean;
    public inactiveFields: Array<string> = [];
    public collapseState: boolean;
    bannerMessage: ToasterMessage = new ToasterMessage();
    getCurrSessionId(): string { return localStorage.getItem(Globals.LOCALSTORAGE_SESSION_ID); }
    setCurrSessionId(sid: string): void { localStorage.setItem(Globals.LOCALSTORAGE_SESSION_ID, sid); }

    initBannerMessage() {
        this.bannerMessage = new ToasterMessage();
    }

    clearStorage() {
        this.initBannerMessage();
        localStorage.clear();
    }

    setGridMeasureDetail(gm: GridMeasure): void {
        localStorage.setItem(Globals.GRID_MEASURE, JSON.stringify(gm));
    }

    getGridMeasureDetail(): GridMeasure {
        const gm = localStorage.getItem(Globals.GRID_MEASURE);
        return JSON.parse(gm);
    }

    setCancelStage(flag: boolean): void {
        localStorage.setItem(Globals.CANCEL_STAGE, JSON.stringify(flag));
    }

    isInCancelPage(): boolean {
        const flag = localStorage.getItem(Globals.CANCEL_STAGE);
        return JSON.parse(flag);
    }

    getBackendsettings(): BackendSettings {
        return this.getSaveFromLocalStorage(Globals.BACKEND_SETTINGS);
    }

    setBackendsettings(settings: any): void {
        localStorage.setItem(Globals.BACKEND_SETTINGS, JSON.stringify(settings));
    }

    getCurrUser(): User {
        return this.getSaveFromLocalStorage(Globals.CURRENT_USER);
    }

    setCurrUser(usr: any): void {
        localStorage.setItem(Globals.CURRENT_USER, JSON.stringify(usr));
    }

    getAllUsers(): User[] {
        return this.getSaveFromLocalStorage(Globals.ALL_USERS);
    }

    setAllUsers(allUsr: User[]) {
        localStorage.setItem(Globals.ALL_USERS, JSON.stringify(allUsr));
    }

    setTabFilteringState(filterSearchText: any): void {
        localStorage.setItem(Globals.TAB_FILTERING_TEXT, JSON.stringify(filterSearchText));
    }

    getTabFilteringState(): any {
        const filterSearchText = localStorage.getItem(Globals.TAB_FILTERING_TEXT);
        return JSON.parse(filterSearchText);
    }

    getUserMap(): UserMap {
        if (this.userMap == null) {
            this.userMap = new UserMap(this.getAllUsers());
        }
        return this.userMap;
    }

    getSaveFromLocalStorage(key: string): any {
        const retValue = localStorage.getItem(key);
        if (!retValue) {
            console.log('WARNING: Try to access LocalStorage key [' + key + '] which is empty!');
            return null;
        }
        return JSON.parse(retValue);
    }

    setFilterExpansionState(filterExpanded: boolean): void {
        this.filterExpanded = filterExpanded;
    }

    getFilterExpansionState(): boolean {
        return this.filterExpanded;
    }

    setBranches(branches: Branch[]): void {
        localStorage.setItem(Globals.BRANCHESNAME, JSON.stringify(branches));
    }

    getBranches(): Branch[] {
        const branches = localStorage.getItem(Globals.BRANCHESNAME);
        return JSON.parse(branches);
    }

    setStatuses(statuses: Status[]): void {
        localStorage.setItem(Globals.STATUSES, JSON.stringify(statuses));
    }
    setCostCenters(costCenters: CostCenter[]): void {
        localStorage.setItem(Globals.COSTCENTERS, JSON.stringify(costCenters));
    }
    getCostCenters(): CostCenter[] {
        const costCenter = localStorage.getItem(Globals.COSTCENTERS);
        return JSON.parse(costCenter);
    }
    setEmailAddressesFromTemplates(emailAddresses: string[]): void {
        localStorage.setItem(Globals.EMAILADDRESSES_FROM_TEMPLATE, JSON.stringify(emailAddresses));
    }
    getEmailAddressesFromTemplates(): string[] {
        const emailAddresses = localStorage.getItem(Globals.EMAILADDRESSES_FROM_TEMPLATE);
        return JSON.parse(emailAddresses);
    }

    setTerritories(ter: Territory[]): void {
        localStorage.setItem(Globals.TERRITORY, JSON.stringify(ter));
    }

    getTerritories(): Territory[] {
        const ter = localStorage.getItem(Globals.TERRITORY);
        return JSON.parse(ter);
    }

    getStatuses(): Status[] {
        const statuses = localStorage.getItem(Globals.STATUSES);
        return JSON.parse(statuses);
    }
    getCostCenterById(id: number): CostCenter {
        const costCenters = this.getCostCenters();
        if (costCenters) {
            const costCenter = costCenters.filter(s => s.id === id)[0];
            if (costCenter) {
                return costCenter;
            } else {
                return null;
            }
        }
        return { id: 0, name: 'NOCOSTCENTER' };
    }
    getStatusById(id: number): Status {
        const statuses = this.getStatuses();
        if (statuses) {
            const status = statuses.filter(s => s.id === id)[0];
            if (status) {
                return status;
            } else {
                return null;
            }
        }
        return { id: 0, name: 'NOSTATUS', colorCode: 'NOCOLOR' };
    }

    getBranchById(id: number): Branch {
        const bracnh = this.getBranches();
        if (bracnh) {
            // tslint:disable-next-line:triple-equals
            const branch = bracnh.filter(s => s.id == id)[0];
            if (branch) {
                return branch;
            } else {
                return null;
            }
        }
        return { id: 0, name: 'NOBRANCHES', description: 'nobranches', colorCode: '' };
    }
    public getAccessToken(): string {
        return localStorage.getItem(Globals.ACCESS_TOKEN);
    }

    public setAccessToken(accessToken: string): void {
        localStorage.setItem(Globals.ACCESS_TOKEN, accessToken);
    }
    public getAccessTokenDecoded(): JwtPayload {
        const jwtHelper: JwtHelperService = new JwtHelperService();
        const jwtPayload: JwtPayload = new JwtPayload();
        const decoded: any = jwtHelper.decodeToken(this.getAccessToken());
        jwtPayload.name = decoded ? decoded.name : '';
        return jwtPayload || new JwtPayload();
    }

    public isUserAuthenticated(): boolean {
        return this.userAuthenticated;
    }

    public setUserAuthenticated(flag: boolean) {
        this.userAuthenticated = flag;
    }

    public getOverdueReminder(): boolean {
        return JSON.parse(localStorage.getItem(Globals.OVERDUE_REMINDERS));
    }

    public setOverdueReminder(flag: boolean) {
        localStorage.setItem(Globals.OVERDUE_REMINDERS, JSON.stringify(flag));
    }

    public getUpcomingReminder(): boolean {
        return JSON.parse(localStorage.getItem(Globals.UPCOMING_REMINDERS));
    }

    public setUpcomingReminder(flag: boolean) {
        localStorage.setItem(Globals.UPCOMING_REMINDERS, JSON.stringify(flag));
    }

    public setBellColor(): string {
        const error = this.getOverdueReminder();
        const warning = this.getUpcomingReminder();
        if (error) {
            return 'red';
        } else if (warning) {
            return '#f79e60';
        } else {
            return 'grey';
        }
    }


    public getCurrentReminders(): number[] {
        return JSON.parse(localStorage.getItem(Globals.CURRENT_REMINDERS));
    }

    public setCurrentReminders(currentReminders: number[]) {
        const tmpCurrentReminders = currentReminders ? currentReminders : [];
        localStorage.setItem(Globals.CURRENT_REMINDERS, JSON.stringify(tmpCurrentReminders));
    }

    public getExpiredReminders(): number[] {
        return JSON.parse(localStorage.getItem(Globals.EXPIRED_REMINDERS));
    }

    public setExpiredReminders(expiredReminders: number[]) {
        const tmpExpiredReminders = expiredReminders ? expiredReminders : [];
        localStorage.setItem(Globals.EXPIRED_REMINDERS, JSON.stringify(tmpExpiredReminders));
    }

    public isShorttermNotification(ind: number): boolean {
        const tmpCurrentReminders = this.getCurrentReminders();
        if (tmpCurrentReminders) {
            const status = tmpCurrentReminders.filter(s => s === ind)[0];
            if (status && status.valueOf() > 0) {
                return true;
            }
            return false;
        }
        this.setCurrentReminders([]);
        return false;
    }
    public isOverdueNotification(ind: number): boolean {
        const tmpExpiredReminders = this.getExpiredReminders();
        if (tmpExpiredReminders) {
            const status = tmpExpiredReminders.filter(s => s === ind)[0];
            if (status && status.valueOf() > 0) {
                return true;
            }
            return false;
        }
        this.setExpiredReminders([]);
        return false;
    }

    public setInactiveFieldsArray(fields: Array<string>) {
        this.inactiveFields = fields;
    }

    public getInactiveFields() {
        return this.inactiveFields;
    }

    public isReadOnlyForStatus(gm: GridMeasure) {
        const status = gm.statusId;
        if (status !== Globals.STATUS.NEW && status !== Globals.STATUS.APPLIED) {
            return true;
        }
    }


    getUserSettings(): UserSettings {
        return JSON.parse(localStorage.getItem(Globals.USER_SETTINGS));
    }

    setUserSettings(sett: any): void {
        localStorage.setItem(Globals.USER_SETTINGS, JSON.stringify(sett));
    }

    getSortingState(): any {
        return JSON.parse(localStorage.getItem(Globals.SORTING_STATE));
    }

    setSortingState(state: any): void {
        localStorage.setItem(Globals.SORTING_STATE, state);
    }

    getFilteringSearchText(): any {
        return JSON.parse(localStorage.getItem(Globals.FILTERING_SEARCH_TEXT));
    }

    setFilteringSearchText(txt: any): void {
        localStorage.setItem(Globals.FILTERING_SEARCH_TEXT, txt);
    }

    getColumnState(): any {
        return JSON.parse(localStorage.getItem(Globals.COLUMN_STATE));
    }

    setColumnState(state: any): void {
        localStorage.setItem(Globals.COLUMN_STATE, state);
    }

    getStatusMainFilter(): StatusMainFilter {
        return JSON.parse(localStorage.getItem(Globals.STATUS_MAIN_FILTER));
    }

    setStatusMainFilter(state: StatusMainFilter): void {
        localStorage.setItem(Globals.STATUS_MAIN_FILTER, JSON.stringify(state));
    }

    getFilterDirtyState(): boolean {
        return JSON.parse(localStorage.getItem(Globals.DIRTY_STATE_FILTER));
    }

    setFilterDirtyState(state: boolean): void {
        localStorage.setItem(Globals.DIRTY_STATE_FILTER, JSON.stringify(state));
    }

    isLocked(): boolean {
        return JSON.parse(localStorage.getItem(Globals.READ_ONLY_FORM));
    }

    setIsLocked(state: boolean): void {
        localStorage.setItem(Globals.READ_ONLY_FORM, JSON.stringify(state));
    }

}
