import { ValuesOf } from '@iqser/common-ui/lib/utils';
import { EntityType, EntityTypes, EntryState, EntryStates, IEntityLogEntry } from '../redaction-log';

export const SuperTypes = {
    TextHighlight: 'text-highlight',
    IgnoredHint: 'hint-ignored',
    Skipped: 'skipped',
    Redaction: 'redaction',
    ManualRedaction: 'manual',
    ManualHint: 'manual-hint',
    Recommendation: 'recommendation',
    Hint: 'hint',
} as const;

export type SuperType = ValuesOf<typeof SuperTypes>;

function wrongSuperTypeHandler(): never | undefined {
    return undefined;
}

function resolveRedactionType(entry: IEntityLogEntry, hint = false) {
    if (entry.state === EntryStates.PENDING && entry.oldState) {
        const oldState = entry.oldState;
        delete entry.oldState;
        return SuperTypeMapper[entry.entryType][oldState](entry);
    }

    const redaction = hint ? SuperTypes.Hint : SuperTypes.Redaction;
    const manualRedaction = hint ? SuperTypes.ManualHint : SuperTypes.ManualRedaction;

    if (!entry.engines.length) {
        return entry.state === EntryStates.PENDING && entry.dictionaryEntry ? redaction : manualRedaction;
    }
    return redaction;
}

/**
 * https://knecon.atlassian.net/wiki/spaces/RED/pages/102072322/EntityLog+-+Enum+combinations
 */
export const SuperTypeMapper: Record<EntityType, Record<EntryState, (entry: IEntityLogEntry) => SuperType | undefined>> = {
    [EntityTypes.ENTITY]: {
        [EntryStates.APPLIED]: entry => resolveRedactionType(entry),
        [EntryStates.SKIPPED]: () => SuperTypes.Skipped,
        [EntryStates.IGNORED]: () => SuperTypes.Skipped,
        [EntryStates.REMOVED]: wrongSuperTypeHandler,
        [EntryStates.PENDING]: entry => resolveRedactionType(entry),
    },
    [EntityTypes.HINT]: {
        [EntryStates.APPLIED]: wrongSuperTypeHandler,
        [EntryStates.SKIPPED]: entry => resolveRedactionType(entry, true),
        [EntryStates.IGNORED]: () => SuperTypes.IgnoredHint,
        [EntryStates.REMOVED]: wrongSuperTypeHandler,
        [EntryStates.PENDING]: entry => resolveRedactionType(entry),
    },
    [EntityTypes.FALSE_POSITIVE]: {
        [EntryStates.APPLIED]: wrongSuperTypeHandler,
        [EntryStates.SKIPPED]: wrongSuperTypeHandler,
        [EntryStates.IGNORED]: wrongSuperTypeHandler,
        [EntryStates.REMOVED]: wrongSuperTypeHandler,
        [EntryStates.PENDING]: entry => resolveRedactionType(entry),
    },
    [EntityTypes.RECOMMENDATION]: {
        [EntryStates.APPLIED]: wrongSuperTypeHandler,
        [EntryStates.SKIPPED]: () => SuperTypes.Recommendation,
        [EntryStates.IGNORED]: wrongSuperTypeHandler,
        [EntryStates.REMOVED]: wrongSuperTypeHandler,
        [EntryStates.PENDING]: entry => resolveRedactionType(entry),
    },
    [EntityTypes.FALSE_RECOMMENDATION]: {
        [EntryStates.APPLIED]: wrongSuperTypeHandler,
        [EntryStates.SKIPPED]: wrongSuperTypeHandler,
        [EntryStates.IGNORED]: wrongSuperTypeHandler,
        [EntryStates.REMOVED]: wrongSuperTypeHandler,
        [EntryStates.PENDING]: entry => resolveRedactionType(entry),
    },
    [EntityTypes.AREA]: {
        [EntryStates.APPLIED]: () => SuperTypes.Redaction,
        [EntryStates.SKIPPED]: wrongSuperTypeHandler,
        [EntryStates.IGNORED]: wrongSuperTypeHandler,
        [EntryStates.REMOVED]: wrongSuperTypeHandler,
        [EntryStates.PENDING]: entry => resolveRedactionType(entry),
    },
    [EntityTypes.IMAGE]: {
        [EntryStates.APPLIED]: () => SuperTypes.Redaction,
        [EntryStates.SKIPPED]: () => SuperTypes.Skipped,
        [EntryStates.IGNORED]: () => SuperTypes.Skipped,
        [EntryStates.REMOVED]: wrongSuperTypeHandler,
        [EntryStates.PENDING]: entry => resolveRedactionType(entry),
    },
    [EntityTypes.IMAGE_HINT]: {
        [EntryStates.APPLIED]: entry => resolveRedactionType(entry),
        [EntryStates.SKIPPED]: () => SuperTypes.Hint,
        [EntryStates.IGNORED]: () => SuperTypes.Hint,
        [EntryStates.REMOVED]: wrongSuperTypeHandler,
        [EntryStates.PENDING]: entry => resolveRedactionType(entry),
    },
};

export const LowLevelFilterTypes = {
    [SuperTypes.Hint]: true,
    [SuperTypes.Redaction]: true,
    [SuperTypes.Recommendation]: true,
    [SuperTypes.IgnoredHint]: true,
    [SuperTypes.Skipped]: true,
} as const;

export const FalsePositiveSuperTypes = {
    [SuperTypes.Hint]: true,
    [SuperTypes.Redaction]: true,
    [SuperTypes.IgnoredHint]: true,
    [SuperTypes.Skipped]: true,
} as const;
