import { IRecommendation } from '@rh-support/api';
import { IApiResponseDetails, IMarkdownCallback, IMarkedownOptions, IPortalJwtToken } from '@rh-support/types';
import { Markdown } from 'js-markdown-extra';
import assign from 'lodash/assign';
import get from 'lodash/get';
import includes from 'lodash/includes';
import isEmpty from 'lodash/isEmpty';
import isString from 'lodash/isString';
import marked from 'marked';
import qs from 'qs';

export default class CaseUtils {
    static defaultMarkdownOptions: IMarkedownOptions = { gfm: true, breaks: true, jsMarkdownExtra: false, openLinksInNewTab: false };

    static getApiResourceObject<T>(
        data: T,
        isFetching: boolean = false,
        isError: boolean = false,
        errorMessage: string = ''
    ): IApiResponseDetails<T> {
        return { data, isFetching, isError, errorMessage };
    }

    static getRecommendationTitle(doc: IRecommendation) {
        return !isEmpty(doc.publishedTitle) ? doc.publishedTitle : doc.allTitle;
    }

    // parses url query params to an obj
    static getUrlParsedParams(urlParams: string) {
        return qs.parse(urlParams, { ignoreQueryPrefix: true });
    }
    static canManageCase(loggedInUserJwtToken: Partial<IPortalJwtToken>): boolean {
        return includes(get(loggedInUserJwtToken, 'realm_access.roles', []), 'portal_manage_cases');
    }

    static scrollIntoSection(sectionRef: React.MutableRefObject<HTMLDivElement>) {
        // Adding setTimeout so that scrolling occures only after width is added/removed from active and previouly active section respectively.
        setTimeout(() => {
            if (isEmpty(sectionRef) || isEmpty(sectionRef.current)) { return; }
            sectionRef.current.scrollIntoView({behavior: 'smooth' });
        }, 100);
    }

    // converts an obj to url query params
    static getStringifiedParams<T>(object: T) {
        return qs.stringify(object, { arrayFormat: 'repeat', encode: false });
    }

    static humanizeSize(fileSize: number): string {
        let i = -1;
        let size = fileSize;
        const byteUnits = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
        do {
            size = size / 1024;
            i++;
        } while (size >= 1024 && byteUnits[i + 1]);

        return `${Math.max(size, 0.1).toFixed(1)} ${byteUnits[i]}`;
    }

    static markdownToHTML(md: string, options = CaseUtils.defaultMarkdownOptions, callback?: IMarkdownCallback): string {
        if (!isString(md)) { return ''; }
        // Important Note: jsMarkdownExtra option is depricated to use
        // Eventually we will get rid of js-markdown-extra library because it is not longer maintained and has bugs while parsing huge data and special chars
        // when jsMarkdownExtra is true, MarkedOptions will not get applied
        const parsedHtml = get(options, 'jsMarkdownExtra', false) ? Markdown(md.replace(/```/gi, '')) : marked(md, assign({}, CaseUtils.defaultMarkdownOptions, options), callback);
        return get(options, 'openLinksInNewTab', false) ? parsedHtml.replace(`<a href`, '<a target="blank" href') : parsedHtml;
    }

    static showFts(sla: string, severity: string): boolean {
        return CaseUtils.isPremiumEntitlement(sla) && CaseUtils.isSev1(severity);
    }
    static isPremiumEntitlement(sla: string): boolean {
        return sla === 'PREMIUM' || sla === 'AMC' || sla === 'PREMIUMPLUS' || sla === 'PREMIUM PLUS';
    }
    static isSev1(severity: string): boolean {
        const firstChar = severity && severity.charAt(0);
        return firstChar === '1';
    }
}
