import { Dictionary, File, IAddRedactionRequest, IEntityLogEntryPosition, SuperType } from '@red/domain';
import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
import { LegalBasisOption, RectangleRedactOption, RectangleRedactOptions } from './dialog-types';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { DetailsRadioOption } from '@common-ui/inputs/details-radio/details-radio-option';

export interface EnhanceRequestData {
    readonly type: SuperType | null;
    readonly selectedText: string;
    readonly reason: LegalBasisOption;
    readonly dictionaries: Dictionary[];
    readonly dictionaryRequest: boolean;
    readonly comment: string;
    readonly isApprover: boolean;
    readonly applyToAllDossiers: boolean;
    readonly bulkLocal: boolean;
}

interface MultiplePagesRectangleData {
    manualRedactionEntryWrapper: ManualRedactionEntryWrapper;
    pages: string;
    file: File;
}

export const enhanceManualRedactionRequest = (addRedactionRequest: IAddRedactionRequest, data: EnhanceRequestData) => {
    addRedactionRequest.type = data.type;
    addRedactionRequest.section = null;
    addRedactionRequest.value = data.selectedText;

    const legalOption: LegalBasisOption = data.reason;
    if (legalOption) {
        addRedactionRequest.reason = legalOption.description;
        addRedactionRequest.legalBasis = legalOption.legalBasis;
    }

    const selectedType = data.dictionaries.find(d => d.type === addRedactionRequest.type);

    if (selectedType) {
        addRedactionRequest.addToDictionary = selectedType.hasDictionary;
    } else {
        addRedactionRequest.addToDictionary = data.dictionaryRequest && addRedactionRequest.type !== 'dossier_redaction';
    }

    if (!addRedactionRequest.reason) {
        addRedactionRequest.reason = 'Dictionary Request';
    }
    const commentValue = data.comment;
    addRedactionRequest.comment = commentValue ? (data.bulkLocal ? commentValue : { text: commentValue }) : null;
    addRedactionRequest.addToAllDossiers = data.isApprover && data.dictionaryRequest && data.applyToAllDossiers;
};

export const parseSelectedPageNumbers = (inputValue: string, file: File, annotation: AnnotationWrapper) => {
    if (!inputValue) {
        return [];
    }

    inputValue = inputValue.replace(/[^0-9-,]/g, '');
    const pageNumbers = [];

    inputValue.split(',').forEach(range => {
        const splitted = range.split('-');
        const startPage = parseInt(splitted[0], 10);
        const endPage = splitted.length > 1 ? parseInt(splitted[1], 10) : startPage;
        if (!startPage || !endPage || startPage > file.numberOfPages || endPage > file.numberOfPages) {
            throw new Error();
        }

        for (let page = startPage; page <= endPage; page++) {
            pageNumbers.push(page);
        }
    });

    return pageNumbers;
};

export const parseRectanglePosition = (annotation: AnnotationWrapper) => {
    const position = annotation.positions[0];
    return {
        rectangle: [position.topLeft.x, position.topLeft.y, position.width, position.height],
        pageNumber: position.page,
    } as IEntityLogEntryPosition;
};

export const prefillPageRange = (
    annotation: AnnotationWrapper,
    allFileAnnotations: AnnotationWrapper[],
    options: DetailsRadioOption<RectangleRedactOption>[],
) => {
    const option = options.find(o => o.value === RectangleRedactOptions.MULTIPLE_PAGES);
    const pages = extractPages(annotation, allFileAnnotations);
    option.additionalInput.value = toRangeString(pages);
};

const extractPages = (annotation: AnnotationWrapper, allFileAnnotations: AnnotationWrapper[]): number[] => {
    return allFileAnnotations.reduce((pages, a) => {
        const position = a.positions[0];
        const annotationPosition = annotation.positions[0];
        if (
            position.height === annotationPosition.height &&
            position.width === annotationPosition.width &&
            position.topLeft.x === annotationPosition.topLeft.x &&
            position.topLeft.y === annotationPosition.topLeft.y
        ) {
            pages.push(position.page);
        }
        return pages;
    }, []);
};

const toRangeString = (pages: number[]): string => {
    if (pages.length === 0) {
        return '';
    }

    let ranges = [];
    let start = pages[0];
    let end = pages[0];

    for (let i = 1; i < pages.length; i++) {
        if (pages[i] === end + 1) {
            end = pages[i];
        } else {
            if (start === end) {
                ranges.push(`${start}`);
            } else {
                ranges.push(`${start}-${end}`);
            }
            start = end = pages[i];
        }
    }

    if (start === end) {
        ranges.push(`${start}`);
    } else {
        ranges.push(`${start}-${end}`);
    }

    return ranges.join(',');
};
