UNPKG

@hmcts/media-viewer

Version:
7,407 lines 523 kB
import * as i5$1 from 'rpx-xui-translation';
import { RpxTranslationModule } from 'rpx-xui-translation';
import * as i0 from '@angular/core';
import { Injectable, Component, ViewChild, HostListener, Directive, Input, ViewEncapsulation, Pipe, EventEmitter, Output, ViewChildren, NgModule } from '@angular/core';
import * as i5 from '@angular/common';
import { DatePipe, CommonModule } from '@angular/common';
import * as i2 from '@angular/forms';
import { UntypedFormControl, FormGroup, FormControl, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
import * as i1$1 from '@angular/common/http';
import { HttpClientModule } from '@angular/common/http';
import { BehaviorSubject, Subject, of, combineLatest, asyncScheduler } from 'rxjs';
import { take, distinctUntilChanged, filter, auditTime, tap, throttleTime, map, catchError, switchMap, concatMap, exhaustMap, withLatestFrom } from 'rxjs/operators';
import * as i1 from '@ngrx/store';
import { createFeatureSelector, createSelector, select, StoreModule } from '@ngrx/store';
import { v4 } from 'uuid';
import moment from 'moment-timezone';
import 'pdfjs-dist/build/pdf.mjs';
import * as pdfjsViewer from 'pdfjs-dist/web/pdf_viewer.mjs';
import { PDFLinkService } from 'pdfjs-dist/web/pdf_viewer.mjs';
import * as pdfjs from 'pdfjs-dist';
import 'pdfjs-dist/build/pdf.worker';
import { some } from 'lodash';
import * as i4 from 'ngx-chips';
import { TagInputModule } from 'ngx-chips';
import * as i3 from '@angular/router';
import { RouterModule } from '@angular/router';
import * as i4$1 from 'mutable-div';
import { MutableDivModule } from 'mutable-div';
import { SelectionModel, ArrayDataSource } from '@angular/cdk/collections';
import * as i3$1 from '@angular/cdk/tree';
import { NestedTreeControl, CdkTreeModule } from '@angular/cdk/tree';
import * as i4$2 from '@angular/cdk/drag-drop';
import { DragDropModule } from '@angular/cdk/drag-drop';
import * as i5$2 from '@angular/cdk/scrolling';
import * as i7 from '@angular/cdk/overlay';
import { ConnectionPositionPair, OverlayModule } from '@angular/cdk/overlay';
import * as i5$3 from '@angular/cdk/a11y';
import { A11yModule } from '@angular/cdk/a11y';
import * as i8 from '@swimlane/ngx-datatable';
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
import * as i1$2 from '@ngrx/effects';
import { createEffect, ofType, EffectsModule } from '@ngrx/effects';

var ResponseType;
(function (ResponseType) {
    ResponseType["SUCCESS"] = "SUCCESS";
    ResponseType["FAILURE"] = "FAILURE";
    ResponseType["UNSUPPORTED"] = "UNSUPPORTED";
})(ResponseType || (ResponseType = {}));
class ViewerException {
    constructor(exceptionType, detail) {
        this.exceptionType = exceptionType;
        this.detail = detail;
    }
}

const SET_DOCUMENT_ID = '[Document] Set Document Id';
const POSITION_UPDATED = '[Document] Position Updated';
const ADD_PAGES = '[Document] Add Pages';
const CONVERT = '[Document] Convert';
const CONVERT_SUCCESS = '[Document] Convert Success';
const CONVERT_FAIL = '[Document] Convert Fail';
const CLEAR_CONVERT_DOC_URL = '[Document] Clear Convert Doc Url';
const LOAD_ROTATION = '[Document] Load Rotation';
const LOAD_ROTATION_SUCCESS = '[Document] Load Rotation Success';
const LOAD_ROTATION_FAIL = '[Document] Load Rotation Fail';
const SAVE_ROTATION = '[Document] Save Rotation';
const SAVE_ROTATION_SUCCESS = '[Document] Save Rotation Success';
const SAVE_ROTATION_FAIL = '[Document] Save Rotation Fail';
class SetDocumentId {
    constructor(payload) {
        this.payload = payload;
        this.type = SET_DOCUMENT_ID;
    }
}
class AddPages {
    constructor(payload) {
        this.payload = payload;
        this.type = ADD_PAGES;
    }
}
class PdfPositionUpdate {
    constructor(payload) {
        this.payload = payload;
        this.type = POSITION_UPDATED;
    }
}
class Convert {
    constructor(payload) {
        this.payload = payload;
        this.type = CONVERT;
    }
}
class ConvertSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = CONVERT_SUCCESS;
    }
}
class ConvertFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = CONVERT_FAIL;
    }
}
class ClearConvertDocUrl {
    constructor() {
        this.type = CLEAR_CONVERT_DOC_URL;
    }
}
class LoadRotation {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_ROTATION;
    }
}
class LoadRotationSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_ROTATION_SUCCESS;
    }
}
class LoadRotationFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_ROTATION_FAIL;
    }
}
class SaveRotation {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_ROTATION;
    }
}
class SaveRotationSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_ROTATION_SUCCESS;
    }
}
class SaveRotationFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_ROTATION_FAIL;
    }
}

const UPDATE_TAGS = '[Tags] Update Tags';
const ADD_FILTER_TAGS = '[Tags] Add Filter Tags';
const CLEAR_FILTER_TAGS = '[Tags] Clear Filter Tags';
class UpdateTags {
    constructor(payload) {
        this.payload = payload;
        this.type = UPDATE_TAGS;
    }
}
class AddFilterTags {
    constructor(payload) {
        this.payload = payload;
        this.type = ADD_FILTER_TAGS;
    }
}
class ClearFilterTags {
    constructor() {
        this.type = CLEAR_FILTER_TAGS;
    }
}

const SET_CASE_ID = '[Icp] Set Case Id';
const LOAD_ICP_SESSION = '[Icp] Load Session';
const LOAD_ICP_SESSION_FAIL = '[Icp] Load Session Failure';
const JOIN_ICP_SOCKET_SESSION = '[Icp] Join Socket Session';
const ICP_SOCKET_SESSION_JOINED = '[Icp] Socket Session Joined';
const LEAVE_ICP_SOCKET_SESSION = '[Icp] Leave Socket Session';
const ICP_PRESENTER_UPDATED = '[Icp] Presenter Updated';
const ICP_PARTICIPANT_LIST_UPDATED = '[Icp] Participant List Updated';
class SetCaseId {
    constructor(payload) {
        this.payload = payload;
        this.type = SET_CASE_ID;
    }
}
class LoadIcpSession {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_ICP_SESSION;
    }
}
class LoadIcpSessionFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_ICP_SESSION_FAIL;
    }
}
class JoinIcpSocketSession {
    constructor(payload) {
        this.payload = payload;
        this.type = JOIN_ICP_SOCKET_SESSION;
    }
}
class IcpSocketSessionJoined {
    constructor(payload) {
        this.payload = payload;
        this.type = ICP_SOCKET_SESSION_JOINED;
    }
}
class LeaveIcpSocketSession {
    constructor() {
        this.type = LEAVE_ICP_SOCKET_SESSION;
    }
}
class IcpPresenterUpdated {
    constructor(payload) {
        this.payload = payload;
        this.type = ICP_PRESENTER_UPDATED;
    }
}
class IcpParticipantListUpdated {
    constructor(payload) {
        this.payload = payload;
        this.type = ICP_PARTICIPANT_LIST_UPDATED;
    }
}

const initialDocumentState = {
    convertedDocument: undefined,
    documentId: undefined,
    pdfPosition: undefined,
    pages: {},
    hasDifferentPageSize: false,
    rotation: undefined,
    rotationLoaded: false,
    loading: false,
    loaded: false
};
function docReducer(state = initialDocumentState, action) {
    switch (action.type) {
        case CONVERT_SUCCESS: {
            const convertedDocument = {
                url: action.payload,
                error: undefined
            };
            return {
                ...state,
                convertedDocument
            };
        }
        case CONVERT_FAIL: {
            const convertedDocument = {
                url: undefined,
                error: action.payload
            };
            return {
                ...state,
                convertedDocument
            };
        }
        case CLEAR_CONVERT_DOC_URL: {
            const convertedDocument = undefined;
            return {
                ...state,
                convertedDocument
            };
        }
        case LOAD_ROTATION: {
            return {
                ...state,
                rotationLoaded: false
            };
        }
        case LOAD_ROTATION_SUCCESS: {
            const metadata = action.payload;
            const rotation = metadata ? metadata.rotationAngle : 0;
            return {
                ...state,
                rotation,
                rotationLoaded: true
            };
        }
        case LOAD_ROTATION_FAIL: {
            return {
                ...state,
                rotation: 0,
                rotationLoaded: true
            };
        }
        case SAVE_ROTATION_SUCCESS: {
            const metadata = action.payload;
            const rotation = metadata.rotationAngle;
            return {
                ...state,
                rotation
            };
        }
        case SET_DOCUMENT_ID: {
            return {
                ...state,
                documentId: action.payload
            };
        }
        case ADD_PAGES: {
            const payload = action.payload;
            let pages = {};
            let pageHeight;
            let pageWidth;
            let hasDifferentPageSize = state.hasDifferentPageSize;
            payload.forEach(page => {
                if (!hasDifferentPageSize && pageHeight && pageWidth &&
                    (pageHeight !== page.div['clientHeight'] || pageWidth !== page.div['clientWidth'])) {
                    hasDifferentPageSize = true;
                }
                else {
                    pageHeight = page.div['clientHeight'];
                    pageWidth = page.div['clientWidth'];
                }
                const styles = {
                    left: page.div['offsetLeft'],
                    height: page.div['clientHeight'],
                    width: page.div['clientWidth']
                };
                const scaleRotation = {
                    scale: page.scale,
                    rotation: page.rotation
                };
                const p = {
                    styles,
                    scaleRotation,
                    viewportScale: page.viewportScale
                };
                pages = {
                    ...pages,
                    [page.id]: p
                };
            });
            return {
                ...state,
                pages,
                hasDifferentPageSize
            };
        }
        case POSITION_UPDATED: {
            const pdfPosition = action.payload;
            return {
                ...state,
                pdfPosition
            };
        }
    }
    return state;
}
const getDocPages = (state) => state.pages;
const getDocId = (state) => state.documentId;
const getPdfPos = (state) => state.pdfPosition;
const getHasDifferentPageSizes = (state) => state.hasDifferentPageSize;
const getRotation$1 = (state) => state.rotation;
const rotationLoaded$1 = (state) => state.rotationLoaded;
const getConvertedDocument$1 = (state) => state.convertedDocument;

const LOAD_ANNOTATION_SET = '[Annotations] Load Annotation Set';
const LOAD_ANNOTATION_SET_SUCCESS = '[Annotations] Load Annotation Set Success';
const LOAD_ANNOTATION_SET_FAIL = '[Annotations] Load Annotation Set Fail';
const SAVE_ANNOTATION_SET = '[Annotations] Save Annotation Set';
const SAVE_ANNOTATION_SET_SUCCESS = '[Annotations] Save Annotation Set Success';
const SAVE_ANNOTATION_SET_FAIL = '[Annotations] Save Annotation Set Fail';
const SAVE_ANNOTATION = '[Annotations] Save Annotation';
const SAVE_ANNOTATION_SUCCESS = '[Annotations] Save Annotation Success';
const SAVE_ANNOTATION_FAIL = '[Annotations] Save Annotation Fail';
const ADD_OR_EDIT_COMMENT = '[Annotations] Add or Edit Comment';
const DELETE_ANNOTATION = '[Annotations] Delete Annotation';
const DELETE_ANNOTATION_SUCCESS = '[Annotations] Delete Annotation Success';
const DELETE_ANNOTATION_FAIL = '[Annotations] Delete Annotation Fail';
const SELECT_ANNOTATION = '[Annotations] Select Annotation';
const SEARCH_COMMENT = '[Comments] Search Comments';
const APPLY_COMMENT_SUMMARY_FILTER = '[Comments] Apply Comment Summary Filter';
const CLEAR_COMMENT_SUMMARY_FILTER = '[Comments] Clear Comment Summary Filter';
class LoadAnnotationSet {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_ANNOTATION_SET;
    }
}
class SaveAnnotationSet {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_ANNOTATION_SET;
    }
}
class LoadAnnotationSetSucess {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_ANNOTATION_SET_SUCCESS;
    }
}
class SaveAnnotationSetSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_ANNOTATION_SET_SUCCESS;
    }
}
class LoadAnnotationSetFail {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_ANNOTATION_SET_FAIL;
    }
}
class SaveAnnotationSetFail {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_ANNOTATION_SET_FAIL;
    }
}
class SaveAnnotation {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_ANNOTATION;
    }
}
class SaveAnnotationSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_ANNOTATION_SUCCESS;
    }
}
class SaveAnnotationFail {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_ANNOTATION_FAIL;
    }
}
class AddOrEditComment {
    constructor(payload) {
        this.payload = payload;
        this.type = ADD_OR_EDIT_COMMENT;
    }
}
class DeleteAnnotation {
    constructor(payload) {
        this.payload = payload;
        this.type = DELETE_ANNOTATION;
    }
}
class DeleteAnnotationSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = DELETE_ANNOTATION_SUCCESS;
    }
}
class DeleteAnnotationFail {
    constructor(payload) {
        this.payload = payload;
        this.type = DELETE_ANNOTATION_FAIL;
    }
}
class SelectedAnnotation {
    constructor(payload) {
        this.payload = payload;
        this.type = SELECT_ANNOTATION;
    }
}
class SearchComment {
    constructor(payload) {
        this.payload = payload;
        this.type = SEARCH_COMMENT;
    }
}
class ApplyCommentSymmaryFilter {
    constructor(payload) {
        this.payload = payload;
        this.type = APPLY_COMMENT_SUMMARY_FILTER;
    }
}
class ClearCommentSummaryFilters {
    constructor() {
        this.type = CLEAR_COMMENT_SUMMARY_FILTER;
    }
}

/*
  @dynamic
  marking class as dynamic to stop compiler throwing error for lambda in static function
  see https://github.com/angular/angular/issues/19698#issuecomment-338340211
 */
class StoreUtils {
    static groupByKeyEntities(annotations, key) {
        return annotations.reduce((h, obj) => Object.assign(h, { [obj[key]]: (h[obj[key]] || []).concat(obj) }), {});
    }
    static generateCommentsEntities(annotations) {
        return annotations.reduce((commentEntities, annotation) => {
            if (annotation.comments.length) {
                const comment = {
                    ...annotation.comments[0] || '',
                    tags: [...annotation.tags || []]
                };
                return {
                    ...commentEntities,
                    [annotation.id]: comment
                };
            }
            return {
                ...commentEntities
            };
        }, {});
    }
    static genTagNameEntities(annotations) {
        const filterAnnoWithoutCommentsTags = annotations.filter(a => (a.comments.length && a.tags.length));
        const allTags = filterAnnoWithoutCommentsTags.map(anno => this.groupByKeyEntities(anno.tags, 'name'));
        const groupedByName = allTags.reduce((tagEntitiy, tagItem) => {
            return {
                ...tagEntitiy,
                ...tagItem
            };
        }, {});
        return this.genNameEnt(annotations, groupedByName);
    }
    static genNameEnt(annos, groupedByName) {
        return Object.keys(groupedByName).reduce((tagNameEnt, key) => {
            const readyAnno = annos.filter(anno => anno.tags.find(tag => tag.name === key))
                .map(anno => anno.id)
                .reduce((obj, anno) => ({ ...obj, [anno]: anno }), {});
            return {
                ...tagNameEnt,
                [key]: readyAnno
            };
        }, {});
    }
    static generateAnnotationEntities(anno) {
        return anno.reduce((annoEntities, annotation) => {
            const annot = {
                ...annotation,
                positionTop: annotation.rectangles[0].y // todo remove this
            };
            return {
                ...annoEntities,
                [annotation.id]: annot
            };
        }, {});
    }
    static generateRedactionEntities(redactions) {
        return redactions.reduce((redactEntities, redaction) => {
            return {
                ...redactEntities,
                [redaction.redactionId]: redaction
            };
        }, {});
    }
    static resetCommentEntSelect(ent) {
        return Object.keys(ent).reduce((object, key) => {
            object[key] = {
                ...ent[key],
                editable: false,
                selected: false
            };
            return object;
        }, {});
    }
    static filterCommentsSummary(comments, filters) {
        if (Object.keys(filters).length) {
            const tagFilterApplied = Object.keys(filters.tagFilters)
                .filter(key => filters.tagFilters[key] === true).length;
            const dateFilterApplied = (filters.dateRangeFrom || filters.dateRangeTo);
            const filteredComments = comments.filter(comment => {
                let hasTagFilter = false;
                let hasDateFilter = false;
                // check tags
                if (filters.hasOwnProperty('tagFilters')) {
                    Object.keys(filters.tagFilters).forEach(filter => {
                        const label = filters.tagFilters[filter];
                        if (label) {
                            return comment.tags.forEach(tag => {
                                if (tag.name === filter && !hasTagFilter) {
                                    hasTagFilter = true;
                                }
                            });
                        }
                    });
                }
                // check for dates
                if (dateFilterApplied) {
                    const commentDate = moment(comment.lastModifiedDate);
                    const dateFrom = filters.dateRangeFrom !== null ? moment(filters.dateRangeFrom) : undefined;
                    const dateTo = filters.dateRangeTo !== null ? moment(filters.dateRangeTo) : undefined;
                    if (dateTo && dateFrom) {
                        if (commentDate > dateFrom && commentDate < dateTo) {
                            hasDateFilter = true;
                        }
                    }
                    if (dateTo && !dateFrom) {
                        if (commentDate <= dateTo) {
                            hasDateFilter = true;
                        }
                    }
                    if (dateFrom && !dateTo) {
                        if (commentDate > dateFrom) {
                            hasDateFilter = true;
                        }
                    }
                }
                return (hasTagFilter || hasDateFilter);
            });
            return (tagFilterApplied || dateFilterApplied) ? filteredComments : comments;
        }
        else {
            return comments;
        }
    }
}

const initialState = {
    annotationSet: {},
    annotationEntities: {},
    commentEntities: {},
    annotationPageEntities: {},
    selectedAnnotation: null,
    commentSearchQueries: { commentSearch: '' },
    commentSummaryFilters: { hasFilter: false, filters: {} },
    loading: false,
    loaded: false,
};
function reducer(state = initialState, action) {
    switch (action.type) {
        case LOAD_ANNOTATION_SET: {
            const annotationSet = {
                ...state.annotationSet,
                documentId: action.payload
            };
            return {
                ...initialState,
                annotationSet,
                loading: true
            };
        }
        case LOAD_ANNOTATION_SET_SUCCESS:
        case LOAD_ANNOTATION_SET_FAIL: {
            const annotationSet = action.payload.status === 200 ? action.payload.body :
                {
                    ...state.annotationSet,
                    annotations: [],
                    id: v4()
                };
            const annotationEntities = StoreUtils.generateAnnotationEntities(annotationSet.annotations);
            const annotationPageEntities = StoreUtils.groupByKeyEntities(annotationSet.annotations, 'page');
            const commentEntities = StoreUtils.generateCommentsEntities(annotationSet.annotations);
            return {
                ...state,
                annotationSet,
                annotationEntities,
                annotationPageEntities,
                commentEntities,
                loading: false,
                loaded: true
            };
        }
        case SAVE_ANNOTATION_SET_SUCCESS: {
            const anno = action.payload.annotations;
            const annEntities = {
                ...state.annotationEntities,
                ...anno
            };
            const annotArray = Object.keys(annEntities).map(key => annEntities[key]);
            const annotationEntities = StoreUtils.generateAnnotationEntities(annotArray);
            const annotationPageEntities = StoreUtils.groupByKeyEntities(annotArray, 'page');
            const commentEntities = StoreUtils.generateCommentsEntities(annotArray);
            const selectedAnnotation = {
                ...state.selectedAnnotation,
                ...anno,
                editable: false
            };
            return {
                ...state,
                annotationEntities,
                annotationPageEntities,
                commentEntities,
                selectedAnnotation,
                loading: false,
                loaded: true
            };
        }
        case SAVE_ANNOTATION_SUCCESS: {
            const anno = action.payload;
            const annEntities = {
                ...state.annotationEntities,
                [anno.id]: anno
            };
            const annotArray = Object.keys(annEntities).map(key => annEntities[key]);
            const annotationEntities = StoreUtils.generateAnnotationEntities(annotArray);
            const annotationPageEntities = StoreUtils.groupByKeyEntities(annotArray, 'page');
            const commentEntities = StoreUtils.generateCommentsEntities(annotArray);
            const selectedAnnotation = {
                ...state.selectedAnnotation,
                annotationId: anno.id,
                editable: false
            };
            return {
                ...state,
                annotationEntities,
                annotationPageEntities,
                commentEntities,
                selectedAnnotation,
                loading: false,
                loaded: true
            };
        }
        case DELETE_ANNOTATION_SUCCESS: {
            const id = action.payload;
            const page = state.annotationEntities[id].page;
            const annotationEntities = {
                ...state.annotationEntities
            };
            delete annotationEntities[id];
            const pageAnnotationsRemoved = [
                ...state.annotationPageEntities[page].filter(anno => anno.id !== id)
            ];
            const annotationPageEntities = {
                ...state.annotationPageEntities,
                [page]: pageAnnotationsRemoved
            };
            const commentEntities = {
                ...state.commentEntities
            };
            if (state.commentEntities[id]) {
                delete commentEntities[id];
            }
            return {
                ...state,
                annotationEntities,
                annotationPageEntities,
                commentEntities
            };
        }
        case ADD_OR_EDIT_COMMENT: {
            const comment = {
                [action.payload.annotationId]: action.payload
            };
            const comments = {
                ...state.commentEntities,
                ...comment
            };
            return {
                ...state,
                commentEntities: comments
            };
        }
        case SELECT_ANNOTATION: {
            const payload = action.payload;
            const commentEntity = {
                ...state.commentEntities[payload.annotationId],
                editable: payload.editable,
                selected: payload.selected
            };
            const resetCommentEntSelect = StoreUtils.resetCommentEntSelect({ ...state.commentEntities });
            const commentEntities = payload.annotationId && state.commentEntities[payload.annotationId] ? {
                ...resetCommentEntSelect,
                [payload.annotationId]: commentEntity
            } : { ...resetCommentEntSelect };
            return {
                ...state,
                commentEntities,
                selectedAnnotation: action.payload
            };
        }
        case SEARCH_COMMENT: {
            const commentSearchQueries = {
                ...state.commentSearchQueries,
                commentSearch: action.payload
            };
            const commentEntities = StoreUtils.resetCommentEntSelect({ ...state.commentEntities });
            return {
                ...state,
                commentEntities,
                commentSearchQueries
            };
        }
        case APPLY_COMMENT_SUMMARY_FILTER: {
            const payload = action.payload;
            const hasTagFilter = () => {
                let isFiltered = false;
                if (payload.tagFilters) {
                    Object.keys(payload.tagFilters).map(filter => {
                        if (payload.tagFilters[filter] && !isFiltered) {
                            isFiltered = true;
                        }
                    });
                }
                return isFiltered;
            };
            const hasFilter = (hasTagFilter() || !!payload.dateRangeFrom || !!payload.dateRangeTo);
            const commentSummaryFilters = {
                hasFilter,
                filters: payload
            };
            return {
                ...state,
                commentSummaryFilters: commentSummaryFilters
            };
        }
        case CLEAR_COMMENT_SUMMARY_FILTER: {
            return {
                ...state,
                commentSummaryFilters: { ...initialState.commentSummaryFilters }
            };
        }
    }
    return state;
}
const getAnnoSet = (state) => state.annotationSet;
const getCommentEnts = (state) => state.commentEntities;
const getAnnoPageEnt = (state) => state.annotationPageEntities;
const getAnnoEnt = (state) => state.annotationEntities;
const getSelectedAnno = (state) => state.selectedAnnotation;
const commentSearchQ = (state) => state.commentSearchQueries;
const getSummaryFilters = (state) => state.commentSummaryFilters;

const initialTagState = {
    tagNameEnt: {},
    annotations: [],
    filteredPageEntities: {},
    filteredComments: {},
    formFilterState: {},
    filters: []
};
function tagsReducer(state = initialTagState, action) {
    switch (action.type) {
        case LOAD_ANNOTATION_SET: {
            return {
                ...state,
                ...initialTagState
            };
        }
        case LOAD_ANNOTATION_SET_SUCCESS: {
            const annotations = action.payload.body.annotations;
            const tagNameEnt = StoreUtils.genTagNameEntities(annotations);
            return {
                ...state,
                tagNameEnt,
                annotations
            };
        }
        case SAVE_ANNOTATION_SUCCESS: {
            const payload = action.payload;
            const anno = [...state.annotations].filter(a => a.id !== payload.id) || [];
            const annotations = [...anno, payload];
            const tagNameEnt = StoreUtils.genTagNameEntities(annotations);
            return {
                ...state,
                annotations,
                tagNameEnt
            };
        }
        case DELETE_ANNOTATION_SUCCESS: {
            const id = action.payload;
            const annotations = [...state.annotations].filter(a => a.id !== id);
            const tagNameEnt = StoreUtils.genTagNameEntities(annotations);
            const filteredPageEntities = StoreUtils.groupByKeyEntities(annotations, 'page');
            const filteredComments = {
                ...state.filteredComments
            };
            delete filteredComments[id];
            return {
                ...state,
                annotations,
                tagNameEnt,
                filteredComments,
                filteredPageEntities,
                filters: []
            };
        }
        case ADD_FILTER_TAGS: {
            const formFilterState = action.payload;
            const filters = Object.keys(formFilterState).reduce((arr, key) => {
                return formFilterState[key] ? [...arr, key] : arr;
            }, []);
            const filteredComments = filters.reduce((obj, f) => {
                return {
                    ...obj,
                    ...state.tagNameEnt[f]
                };
            }, {});
            const annotations = Object.keys(filteredComments).map(key => state.annotations.filter(a => a.id === key)[0]);
            const filteredPageEntities = StoreUtils.groupByKeyEntities(annotations, 'page');
            return {
                ...state,
                filters,
                filteredComments,
                filteredPageEntities,
            };
        }
        case CLEAR_FILTER_TAGS: {
            return {
                ...state,
                filters: [],
                filteredComments: {},
                filteredPageEntities: {},
            };
        }
    }
    return state;
}
const getTagNameEnt = (state) => state.tagNameEnt;
const getFilters = (state) => state.filters;
const getFilteredComments = (state) => state.filteredComments;
const getFilteredPageEnt = (state) => state.filteredPageEntities;

const LOAD_BOOKMARKS = '[Bookmarks] Load Bookmarks';
const LOAD_BOOKMARKS_SUCCESS = '[Bookmarks] Load Bookmarks Success';
const LOAD_BOOKMARKS_FAIL = '[Bookmarks] Load Bookmarks Failure';
const CREATE_BOOKMARK = '[Bookmarks] Create Bookmark';
const CREATE_BOOKMARK_SUCCESS = '[Bookmarks] Create Bookmark Success';
const CREATE_BOOKMARK_FAIL = '[Bookmarks] Create Bookmark Failure';
const DELETE_BOOKMARK = '[Bookmarks] Delete Bookmark';
const DELETE_BOOKMARK_SUCCESS = '[Bookmarks] Delete Bookmark Success';
const DELETE_BOOKMARK_FAIL = '[Bookmarks] Delete Bookmark Failure';
const MOVE_BOOKMARK = '[Bookmarks] Move Bookmark';
const MOVE_BOOKMARK_SUCCESS = '[Bookmarks] Move Bookmark Success';
const MOVE_BOOKMARK_FAIL = '[Bookmarks] Move Bookmark Failure';
const UPDATE_BOOKMARK = '[Bookmarks] Update Bookmark';
const UPDATE_BOOKMARK_SUCCESS = '[Bookmarks] Update Bookmark Success';
const UPDATE_BOOKMARK_FAIL = '[Bookmarks] Update Bookmark Failure';
const UPDATE_BOOKMARK_SCROLL_TOP = '[Bookmarks] Update Bookmark Scroll Top';
class LoadBookmarks {
    constructor() {
        this.type = LOAD_BOOKMARKS;
    }
}
class LoadBookmarksSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_BOOKMARKS_SUCCESS;
    }
}
class LoadBookmarksFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_BOOKMARKS_FAIL;
    }
}
class CreateBookmark {
    constructor(payload) {
        this.payload = payload;
        this.type = CREATE_BOOKMARK;
    }
}
class CreateBookmarkSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = CREATE_BOOKMARK_SUCCESS;
    }
}
class CreateBookmarkFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = CREATE_BOOKMARK_FAIL;
    }
}
class DeleteBookmark {
    constructor(payload) {
        this.payload = payload;
        this.type = DELETE_BOOKMARK;
    }
}
class DeleteBookmarkSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = DELETE_BOOKMARK_SUCCESS;
    }
}
class DeleteBookmarkFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = DELETE_BOOKMARK_FAIL;
    }
}
class MoveBookmark {
    constructor(payload) {
        this.payload = payload;
        this.type = MOVE_BOOKMARK;
    }
}
class MoveBookmarkSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = MOVE_BOOKMARK_SUCCESS;
    }
}
class MoveBookmarkFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = MOVE_BOOKMARK_FAIL;
    }
}
class UpdateBookmark {
    constructor(payload) {
        this.payload = payload;
        this.type = UPDATE_BOOKMARK;
    }
}
class UpdateBookmarkSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = UPDATE_BOOKMARK_SUCCESS;
    }
}
class UpdateBookmarkFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = UPDATE_BOOKMARK_FAIL;
    }
}
class UpdateBookmarkScrollTop {
    constructor(payload) {
        this.payload = payload;
        this.type = UPDATE_BOOKMARK_SCROLL_TOP;
    }
}

const getBookmarkChildren = (bookmarks) => {
    if (bookmarks) {
        return bookmarks.reduce((childIds, bookmark) => {
            if (bookmark.children && bookmark.children.length > 0) {
                return [...childIds, bookmark.id, ...getBookmarkChildren(bookmark.children)];
            }
            return [...childIds, bookmark.id];
        }, []);
    }
    else {
        return [];
    }
};
const generateBookmarkEntities = (bookmarks) => {
    return bookmarks.reduce((bookmarkEntities, bookmark) => Object.assign(bookmarkEntities, { [bookmark.id]: bookmark }), {});
};
const indexEntities = (entities) => {
    const entityIds = Object.keys(entities);
    for (let index = 0; entityIds.length > 0; index++) {
        let keysToRemove = [];
        entityIds.forEach(key => {
            if (!entities[key].previous || !entityIds.includes(entities[key].previous.toString())) {
                entities[key].index = index;
                keysToRemove.push(key);
            }
        });
        keysToRemove.forEach(key => entityIds.splice(entityIds.indexOf(key), 1));
        keysToRemove = [];
    }
};
const generateBookmarkNodes = (entities) => {
    const bookmarkEntities = JSON.parse(JSON.stringify(entities));
    indexEntities(bookmarkEntities);
    return Object.keys(bookmarkEntities).reduce((nodes, bookmarkId) => {
        const bookmarkEntity = bookmarkEntities[bookmarkId];
        if (bookmarkEntity.parent) {
            const parentEntity = bookmarkEntities[bookmarkEntity.parent];
            if (!parentEntity.children) {
                parentEntity.children = [];
            }
            parentEntity.children[bookmarkEntity.index] = bookmarkEntity;
        }
        else {
            nodes[bookmarkEntity.index] = bookmarkEntity;
        }
        return nodes;
    }, []);
};

const initialBookmarksState = {
    bookmarks: [],
    bookmarkEntities: {},
    bookmarkPageEntities: {},
    editableBookmark: undefined,
    loaded: false,
    loading: false,
    scrollTop: null,
};
function bookmarksReducer(state = initialBookmarksState, action) {
    switch (action.type) {
        case LOAD_BOOKMARKS: {
            return {
                ...state,
                loading: true
            };
        }
        case LOAD_BOOKMARKS_SUCCESS:
        case LOAD_BOOKMARKS_FAIL: {
            const bookmarks = action.payload.status === 200 ? action.payload.body : [];
            const bookmarkEntities = generateBookmarkEntities(bookmarks);
            const bookmarkPageEntities = StoreUtils.groupByKeyEntities(bookmarks, 'pageNumber');
            return {
                ...state,
                bookmarks,
                bookmarkEntities,
                bookmarkPageEntities,
                loaded: true
            };
        }
        case CREATE_BOOKMARK_SUCCESS: {
            const bookmark = action.payload;
            const bookmarkEntities = {
                ...state.bookmarkEntities,
                [bookmark.id]: bookmark,
            };
            const bookmarkArray = Object.keys(bookmarkEntities).map(key => bookmarkEntities[key]);
            const bookmarkPageEntities = StoreUtils.groupByKeyEntities(bookmarkArray, 'pageNumber');
            const editableBookmark = bookmark.id;
            return {
                ...state,
                bookmarkEntities,
                editableBookmark,
                bookmarkPageEntities,
                loading: false,
                loaded: true
            };
        }
        case MOVE_BOOKMARK_SUCCESS: {
            const movedBookmarks = generateBookmarkEntities(action.payload);
            const bookmarkEntities = {
                ...state.bookmarkEntities,
                ...movedBookmarks
            };
            return {
                ...state,
                bookmarkEntities,
                loading: false,
                loaded: true
            };
        }
        case DELETE_BOOKMARK_SUCCESS: {
            const bookmarkIds = action.payload;
            const bookmarkEntities = { ...state.bookmarkEntities };
            const bookmarkPageEntities = { ...state.bookmarkPageEntities };
            const removeBookmarksByPage = {};
            bookmarkIds.forEach(bookmarkId => {
                if (removeBookmarksByPage[bookmarkEntities[bookmarkId].pageNumber] !== undefined &&
                    removeBookmarksByPage[bookmarkEntities[bookmarkId].pageNumber].length > 0) {
                    removeBookmarksByPage[bookmarkEntities[bookmarkId].pageNumber].push(bookmarkId);
                }
                else {
                    removeBookmarksByPage[bookmarkEntities[bookmarkId].pageNumber] = [bookmarkId];
                }
                delete bookmarkEntities[bookmarkId];
            });
            Object.entries(removeBookmarksByPage).forEach(([pageNumber, bmrkIds]) => {
                bookmarkPageEntities[pageNumber]
                    = bookmarkPageEntities[pageNumber].filter(bookmark => !bmrkIds.includes(bookmark.id));
            });
            return {
                ...state,
                bookmarkEntities,
                bookmarkPageEntities,
                loading: false,
                loaded: true
            };
        }
        case UPDATE_BOOKMARK_SUCCESS: {
            const bookmark = action.payload;
            const bookmarkEntities = {
                ...state.bookmarkEntities,
                [bookmark.id]: { ...bookmark }
            };
            const bookmarkArray = Object.keys(bookmarkEntities).map(key => bookmarkEntities[key]);
            const bookmarkPageEntities = StoreUtils.groupByKeyEntities(bookmarkArray, 'pageNumber');
            const editableBookmark = undefined;
            return {
                ...state,
                bookmarkEntities,
                editableBookmark,
                bookmarkPageEntities,
                loading: false,
                loaded: true
            };
        }
        case UPDATE_BOOKMARK_SCROLL_TOP: {
            const scrollTop = action.payload;
            return {
                ...state,
                scrollTop: scrollTop
            };
        }
    }
    return state;
}
const getBookmarks = (state) => state.bookmarks;
const getBookmarkEnts = (state) => state.bookmarkEntities;
const getBookmarkPageEnt = (state) => state.bookmarkPageEntities;
const getEditBookmark = (state) => state.editableBookmark;
const getScrollTop$1 = (state) => state.scrollTop;

const LOAD_REDACTIONS = '[Redaction] Load Redaction';
const LOAD_REDACTION_SUCCESS = '[Redaction] Load Redaction Success';
const LOAD_REDACTION_FAIL = '[Redaction] Load Redaction Fail';
const SAVE_REDACTION = '[Redaction] Save Redaction';
const SAVE_REDACTION_SUCCESS = '[Redaction] Save Redaction Success';
const SAVE_REDACTION_FAIL = '[Redaction] Save Redaction Fail';
const SAVE_BULK_REDACTION = '[Redaction] Save bulk Redaction';
const SAVE_BULK_REDACTION_SUCCESS = '[Redaction] Save bulk Redaction Success';
const SAVE_BULK_REDACTION_FAIL = '[Redaction] Save bulk Redaction Fail';
const DELETE_REDACTION = '[Redaction] Delete Redaction';
const DELETE_REDACTION_SUCCESS = '[Redaction] Delete Redaction Success';
const DELETE_REDACTION_FAIL = '[Redaction] Delete Redaction Fail';
const SELECT_REDACTION = '[Redaction] Select Redaction';
const REDACT = '[Redaction] Redact';
const REDACT_SUCCESS = '[Redaction] Redact Success';
const REDACT_FAIL = '[Redaction] Redact Fail';
const RESET_REDACTED_DOCUMENT = '[Redaction] Reset Redacted Document';
const UNMARK_ALL = '[Redaction] Unmark All';
const UNMARK_ALL_SUCCESS = '[Redaction] Unmark All Success';
class LoadRedactions {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_REDACTIONS;
    }
}
class LoadRedactionSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_REDACTION_SUCCESS;
    }
}
class LoadRedactionFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = LOAD_REDACTION_FAIL;
    }
}
class SaveRedaction {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_REDACTION;
    }
}
class SaveRedactionSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_REDACTION_SUCCESS;
    }
}
class SaveRedactionFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_REDACTION_FAIL;
    }
}
class SaveBulkRedactionFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_BULK_REDACTION_FAIL;
    }
}
class SaveBulkRedaction {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_BULK_REDACTION;
    }
}
class SaveBulkRedactionSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = SAVE_BULK_REDACTION_SUCCESS;
    }
}
class DeleteRedaction {
    constructor(payload) {
        this.payload = payload;
        this.type = DELETE_REDACTION;
    }
}
class DeleteRedactionSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = DELETE_REDACTION_SUCCESS;
    }
}
class DeleteRedactionFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = DELETE_REDACTION_FAIL;
    }
}
class SelectRedaction {
    constructor(payload) {
        this.payload = payload;
        this.type = SELECT_REDACTION;
    }
}
class Redact {
    constructor(payload) {
        this.payload = payload;
        this.type = REDACT;
    }
}
class RedactSuccess {
    constructor(payload) {
        this.payload = payload;
        this.type = REDACT_SUCCESS;
    }
}
class RedactFailure {
    constructor(payload) {
        this.payload = payload;
        this.type = REDACT_FAIL;
    }
}
class ResetRedactedDocument {
    constructor() {
        this.type = RESET_REDACTED_DOCUMENT;
    }
}
class UnmarkAll {
    constructor(payload) {
        this.payload = payload;
        this.type = UNMARK_ALL;
    }
}
class UnmarkAllSuccess {
    constructor() {
        this.type = UNMARK_ALL_SUCCESS;
    }
}

const initialRedactionState = {
    redactionEntities: {},
    redactionPageEntities: {},
    selectedRedaction: {},
    redactedDocumentInfo: undefined,
    documentId: undefined
};
function redactionReducer(state = initialRedactionState, action) {
    switch (action.type) {
        case LOAD_REDACTIONS: {
            return {
                ...state,
                ...initialRedactionState
            };
        }
        case LOAD_REDACTION_SUCCESS: {
            const payload = action.payload;
            if (payload) {
                const redactionEntities = StoreUtils.generateRedactionEntities(payload);
                const redactionPageEntities = StoreUtils.groupByKeyEntities(payload, 'page');
                return {
                    ...state,
                    redactionEntities,
                    redactionPageEntities
                };
            }
            return {
                ...state
            };
        }
        case SAVE_REDACTION_SUCCESS: {
            const { payload } = action;
            const redactionEntities = {
                ...state.redactionEntities,
                [payload.redactionId]: payload
            };
            const redactionArray = Object.keys(redactionEntities).map(key => redactionEntities[key]);
            const redactionPageEntities = StoreUtils.groupByKeyEntities(redactionArray, 'page');
            return {
                ...state,
                redactionEntities,
                redactionPageEntities
            };
        }
        case SAVE_BULK_REDACTION_SUCCESS: {
            const payloadResult = Object.assign({}, ...action.payload.searchRedactions.map((x) => ({ [x.redactionId]: x })));
            const redactionEntities = {
                ...state.redactionEntities,
                ...payloadResult
            };
            const redactionArray = Object.keys(redactionEntities).map(key => redactionEntities[key]);
            const redactionPageEntities = StoreUtils.groupByKeyEntities(redactionArray, 'page');
            return {
                ...state,
                redactionEntities,
                redactionPageEntities
            };
        }
        case SELECT_REDACTION:
        case SELECT_ANNOTATION: {
            return {
                ...state,
                selectedRedaction: action.payload
            };
        }
        case DELETE_REDACTION_SUCCESS: {
            const page = action.payload.page;
            const id = action.payload.redactionId;
            const redactionEntities = {
                ...state.redactionEntities
            };
            delete redactionEntities[id];
            const pageRedactionRemoved = [
                ...state.redactionPageEntities[page].filter(redaction => redaction.redactionId !== id)
            ];
            const redactionPageEntities = {
                ...state.redactionPageEntities,
                [page]: pageRedactionRemoved
            };
            return {
                ...state,
                redactionPageEntities,
                redactionEntities,
            };
        }
        case REDACT_SUCCESS: {
            const redactedDocumentInfo = action.payload;
            return {
                ...state,
                ...initialRedactionState,
                redactedDocumentInfo
            };
        }
        case RESET_REDACTED_DOCUMENT: {
            return {
                ...state,
                redactedDocumentInfo: undefined
            };
        }
        case UNMARK_ALL_SUCCESS: {
            return {
                ...state,
                ...initialRedactionState
            };
        }
    }
    return state;
}
const getRedactionEnt$1 = (state) => state.redactionEntities;
const getPageEnt = (state) => state.redactionPageEntities;
const getSelectedRedaction = (state) => state.selectedRedaction;
const getRedactedDocInfo = (state) => state.redactedDocumentInfo;

const initialIcpSessionState = {
    session: null,
    presenter: null,
    client: null,
    participants: []
};
function icpReducer(state = initialIcpSessionState, action) {
    switch (action.type) {
        case SET_CASE_ID: {
            const caseId = action.payload;
            const session = { ...state.session, caseId };
            return {
                ...state,
                session
            };
        }
        case ICP_SOCKET_SESSION_JOINED: {
            const session = action.payload.session;
            const participantInfo = action.payload.participantInfo;
            return {
                ...state,
                session,
                client: participantInfo.client,
                presenter: participantInfo.presenter,
            };
        }
        case ICP_PARTICIPANT_LIST_UPDATED: {
            const updatedParticipants = action.payload;
            const participants = Object.keys(updatedParticipants)
                .map(id => ({ id: id, username: updatedParticipants[id] }));
            return {
                ...state,
                participants
            };
        }
        case ICP_PRESENTER_UPDATED: {
            const presenter = action.payload;
            return {
                ...state, presenter
            };
        }
        case LEAVE_ICP_SOCKET_SESSION: {
            return {
                ...state,
                ...initialIcpSessionState
            };
        }
    }
    return state;
}
const getIcpSession$1 = (state) => state.session;
const getPresenter$1 = (state) => state.presenter;
const getClient$1 = (state) => state.client;
const getParticipants$1 = (state) => state.participants;

const reducers = {
    document: docReducer,
    annotations: reducer,
    tags: tagsReducer,
    bookmarks: bookmarksReducer,
    redactions: redactionReducer,
    icp: icpReducer,
};
const getMVState = createFeatureSelector('media-viewer');

const getDocumentState = createSelector(getMVState, (state) => state.document);
const getPages = createSelector(getDocumentState, getDocPages);
const getPageList = createSelector(getPages, (pages) => Object.values(pages));
const getDocumentId = createSelector(getDocumentState, getDocId);
const getPdfPosition = createSelector(getDocumentState, getPdfPos);
const getPageDifference = createSelector(getDocumentState, getHasDifferentPageSizes);
const getConvertedDocument = createSelector(getDocumentState, getConvertedDocument$1);
const getRotation = createSelector(getDocumentState, getRotation$1);
const rotationLoaded = createSelector(getDocumentState, rotationLoaded$1);

pdfjs.GlobalWorkerOptions.workerSrc = '/assets/build/pdf.worker.min.js';
/**
 * Values of the state field returned by the find events
 */
var FindState;
(function (FindState) {
    FindState[FindState["FOUND"] = 0] = "FOUND";
    FindState[FindState["NOT_FOUND"] = 1] = "NOT_FOUND";
    FindState[FindState["WRAPPED"] = 2] = "WRAPPED";
    FindState[FindState["PENDING"] = 3] = "PENDING";
})(FindState || (FindState = {}));
class PdfJsWrapper {
    constructor(pdfViewer, downloadManager, toolbarEvents, documentLoadInit, documentLoadProgress, documentLoaded, outlineLoaded, documentLoadFailed, pageRendered, positionUpdated) {
        this.pdfViewer = pdfViewer;
        this.downloadManager = downloadManager;
        this.toolbarEvents = toolbarEvents;
        this.documentLoadInit = documentLoadInit;
        this.documentLoadProgress = documentLoadProgress;
        this.documentLoaded = documentLoaded;
        this.outlineLoaded = outlineLoaded;
        this.documentLoadFailed = documentLoadFailed;
        this.pageRendered = pageRendered;
        this.positionUpdated = positionUpdated;
        this.pdfViewer.eventBus.on('updateviewarea', e => positionUpdated.next(e));
        this.pdfViewer.eventBus.on('pagechanging', e => this.toolbarEvents.setCurrentPageInputValueSubject.next(e.pageNumber));
        this.pdfViewer.eventBus.on('pagesinit', () => this.pdfViewer.currentScaleValue = '1');
        this.pdfViewer.eventBus.on('pagerendered', e => { }); // not used left for future convenience
        this.pdfViewer.eventBus.on('pagesloaded', (e) => this.emitDocumentInfo(e));
        this.pdfViewer.eventBus.on('scalechanging', (e) => this.emitDocumentInfo(e));
        this.pdfViewer.eventBus.on('rotationchanging', (e) => this.emitDocumentInfo(e));
        this.pdfViewer.eventBus.on('updatefindcontrolstate', event => {
            this.sendSearchDetails(event);
        });
        this.pdfViewer.eventBus.on('updatefindmatchescount', event => {
            const result = { ...event.matchesCount, isPrevious: event?.source?.state?.findPrevious };
            this.toolbarEvents.searchResultsCountSubject.next(result);
        });
        this.zoomValue = 1;
    }
    sendSearchDetails(event) {
        if (event.state !== FindState.PENDING) {
            const result = { ...event.matchesCount, isPrevious: event?.source?.state?.findPrevious };
            this.toolbarEvents.searchResultsCountSubject.next(result);
            if (event?.source?.selected?.pageIdx !== -1 && event.matchesCount.total > 0) {
                this.toolbarEvents.redactionSerachSubject.next({
                    page: event?.source?.selected?.pageIdx,
                    matchedIndex: event?.source?.selected?.matchIdx,
                    matchesCount: event.matchesCount.total
                });
            }
        }
    }
    emitDocumentInfo(e) {
        const allPages = [...this.pdfViewer._pages].map(page => {
            return {
                div: page.div,
                scale: page.scale,
                rotation: page.rotation,
                id: page.id,
                viewportScale: page.viewport.scale
            };
        });
        this.pageRendered.next(allPages);
    }
    async loadDocument(documentUrl) {
        const loadingTask = this.createLoadingTask(documentUrl);
        loadingTask.onProgress = ({ loaded, total }) => {
            this.documentLoadProgress.next({ loaded, total });
        };
        this.documentLoadInit.next(documentUrl);
        try {
            const pdfDocument = await loadingTask.promise;
            this.documentLoaded.next(pdfDocument);
            this.toolbarEvents.pageCountSubject.next(pdfDocument.numPages);
            this.pdfViewer.setDocument(pdfDocument);
            if (this.pdfViewer.linkService instanceof PDFLinkService) {
                const linkservice = this.pdfViewer.linkService;
                linkservice.setDocument(pdfDocument, null);
            }
            const outlineNode = await pdfDocument.getOutline();
            const outline = outlineNode ? outlineNode.map(x => {
                return {
                    bold: x.bold,
                    color: x.color,
                    count: x.count,
                    dest: x.dest,
                    italic: x.italic,
                    items: x.items,
                    newWindow: x.newWindow,
                    title: x.title,
                    unsafeUrl: x.unsafeUrl,
                    url: x.url
                };
            }) : null;
            if (outline) {
                await this.setOutlinePageNumbers(pdfDocument, outline);
            }
            this.documentOutline = outline;
            this.outlineLoaded.next(this.documentOutline);
            const pdfMetaData = await pdfDocument.getMetadata();
            this.setCurrentPDFTitle(pdfMetaData.info?.Title);
        }
        catch (e) {
            this.documentLoadFailed.next(e);
        }
    }
    createLoadingTask(documentUrl) {
        return pdfjs.getDocument({
            url: documentUrl,
            cMapUrl: 'assets/minified/cmaps',
            cMapPacked: true,
            withCredentials: true,
            isEvalSupported: false
        });
    }
    async setOutlinePageNumbers(pdfDocument, outlineArray) {
        outlineArray.forEach(async (outline) => {
            await this.setNestedOutlinePageNumbers(pdfDocument, outline);
        });
    }
    async setNestedOutlinePageNumbers(pdfDocument, outline) {
        outline.pageNumber = await this.getOutlinePageNumber(pdfDocument, outline);
        outline.items.forEach(async (outlineItem) => {
            outlineItem.pageNumber = await this.getOutlinePageNumber(pdfDocument, outlineItem);
            this.setNestedOutlinePageNumbers(pdfDocument, outlineItem);
        });
    }
    async getOutlinePageNumber(pdfDocument, outline) {
        const dest = outline.dest;
        const pageIndex = await pdfDocument.getPageIndex(dest[0]);
        return Number(pageIndex) + 1;
    }
    downloadFile(url, filename) {
        this.downloadManager.download(null, url, filename);
    }
    setPageNumber(pageNumber) {
        this.pdfViewer.currentPageNumber = pageNumber;
    }
    getPageNumber() {
        return this.pdfViewer.currentPageNumber;
    }
    changePageNumber(numPages) {
        this.pdfViewer.currentPageNumber += numPages;
    }
    search(operation) {
        const command = operation.reset ? '' : 'again';
        const data = {
            source: this.pdfViewer,
            type: command,
            query: operation.searchTerm,
            phraseSearch: true,
            caseSensitive: operation.matchCase,
            entireWord: operation.wholeWord,
            highlightAll: operation.highlightAll,
            findPrevious: operation.previous,
        };
        this.pdfViewer.eventBus.dispatch('find', data);
    }
    clearSearch() {
        this.pdfViewer.eventBus.dispatch('findbarclose', {});
    }
    navigateTo(destination) {
        if (destination instanceof Object) {
            if (!destination[1].name.includes('XYZ')) {
                destination[1] = { name: 'XYZ' };
                destination[2] = destination[2] || null;
                destination[3] = destination[3] || null;
            }
            destination[4] = this.zoomValue;
        }
        this.nativeNavigate(destination);
    }
    nativeNavigate(destination) {
        this.pdfViewer.linkService.goToDestination(destination);
    }
    setZoom(zoomValue) {
        this.pdfViewer.currentScaleValue = this.getZoomValue(zoomValue).toString();
        this.zoomValue = +this.pdfViewer.currentScaleValue;
        this.toolbarEvents.zoomValueSubject.next(this.zoomValue);
    }
    stepZoom(zoomValue) {
        this.pdfViewer.currentScaleValue = this.getZoomValue((+this.pdfViewer.currentScaleValue) + zoomValue).toString();
        this.zoomValue = +this.pdfViewer.currentScaleValue;
        this.toolbarEvents.zoomValueSubject.next(this.zoomValue);
    }
    getZoomValue(zoomValue) {
        if (isNaN(zoomValue)) {
            return this.zoomValue;
        }
        if (zoomValue > 5) {
            return 5;
        }
        if (zoomValue < 0.1) {
            return 0.1;
        }
        return +zoomValue.toFixed(2);
    }
    rotate(rotation) {
        return this.pdfViewer.pagesRotation = (this.pdfViewer.pagesRotation + rotation) % 360;
    }
    resetRotation(rotation) {
        return this.pdfViewer.pagesRotation = rotation;
    }
    getNormalisedPagesRotation() {
        return this.pdfViewer.pagesRotation;
    }
    getCurrentPDFZoomValue() {
        return +this.pdfViewer.currentScaleValue;
    }
    setCurrentPDFTitle(title) {
        this.documentTitle = title;
    }
    getCurrentPDFTitle() {
        return this.documentTitle;
    }
}

class IcpEventService {
    constructor() {
        this.enabled = new BehaviorSubject(false);
        this.sessionLaunch = new Subject();
        this.becomingPresenter = new Subject();
        this.stoppingPresenting = new Subject();
        this.leavingSession = new BehaviorSubject(false);
        this.sessionExitConfirmed = new Subject();
        this.participantsListVisible = new BehaviorSubject(false);
        this.launchSession = () => {
            this.sessionLaunch.next();
        };
        this.enable = () => {
            this.enabled.next(true);
            this.launchSession();
        };
        this.becomePresenter = () => {
            this.becomingPresenter.next();
        };
        this.stopPresenting = () => {
            this.stoppingPresenting.next();
        };
        this.leaveSession = () => {
            this.leavingSession.next(true);
        };
        this.confirmExit = () => {
            this.sessionExitConfirmed.next();
            this.participantsListVisible.next(false);
            this.enabled.next(false);
        };
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpEventService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpEventService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [] });

var SearchType;
(function (SearchType) {
    SearchType["Redact"] = "Redact";
    SearchType["Highlight"] = "Highlight";
})(SearchType || (SearchType = {}));
class ToolbarEventService {
    constructor(icpEventService) {
        this.icpEventService = icpEventService;
        this.highlightModeSubject = new BehaviorSubject(false);
        this.highlightToolbarSubject = new BehaviorSubject(false);
        this.drawModeSubject = new BehaviorSubject(false);
        this.rotateSubject = new Subject();
        this.searchSubject = new Subject();
        this.searchResultsCountSubject = new Subject();
        this.zoomSubject = new Subject();
        this.stepZoomSubject = new Subject();
        this.zoomValueSubject = new BehaviorSubject(1);
        this.pageCountSubject = new Subject();
        this.printSubject = new Subject();
        this.downloadSubject = new Subject();
        this.setCurrentPageSubject = new Subject();
        this.setCurrentPageInputValueSubject = new Subject();
        this.changePageByDeltaSubject = new Subject();
        this.showCommentSummary = new BehaviorSubject(false);
        this.grabNDrag = new BehaviorSubject(false);
        this.saveRotationSubject = new Subject();
        this.redactionMode = new BehaviorSubject(false);
        this.redactionPreview = new Subject();
        this.applyRedactToDocument = new Subject();
        this.clearAllRedactMarkers = new Subject();
        this.redactWholePage = new Subject();
        this.redactionSerachSubject = new Subject();
        this.redactAllInProgressSubject = new BehaviorSubject(false);
        this.openRedactionSearch = new BehaviorSubject(null);
        this.sidebarOpen = new BehaviorSubject(false);
        this.sidebarOutlineView = new BehaviorSubject(true);
        this.searchBarHidden = new BehaviorSubject(true);
        this.commentsPanelVisible = new BehaviorSubject(false);
    }
    /**
     * Reset the stateful behaviour subjects
     */
    reset() {
        this.setCurrentPageSubject.next(1);
        this.zoomValueSubject.next(1);
        this.highlightModeSubject.next(false);
        this.highlightToolbarSubject.next(false);
        this.drawModeSubject.next(false);
        this.showCommentSummary.next(false);
        this.grabNDrag.next(false);
    }
    // Function to inform Observers that highlightMode has been enabled
    toggleHighlightMode() {
        // Highlight and Draw states are mutually exclusive
        if (this.highlightModeSubject.getValue() === false) {
            this.drawModeSubject.next(false);
            this.grabNDrag.next(false);
            this.highlightModeSubject.next(true);
        }
        else {
            this.highlightModeSubject.next(false);
        }
    }
    // Function to inform Observers that ToggleMode has been enabled
    toggleDrawMode() {
        if (this.drawModeSubject.getValue() === false) {
            this.highlightModeSubject.next(false);
            this.grabNDrag.next(false);
            this.drawModeSubject.next(true);
        }
        else {
            this.drawModeSubject.next(false);
        }
    }
    toggleHighlightToolbar() {
        this.highlightToolbarSubject.next(!this.highlightToolbarSubject.getValue());
    }
    rotate(angle) {
        this.rotateSubject.next(angle);
    }
    search(phrase) {
        this.searchSubject.next(phrase);
    }
    getSearchResultsCount() {
        return this.searchResultsCountSubject.asObservable();
    }
    zoom(value) {
        this.zoomSubject.next(value);
    }
    stepZoom(value) {
        this.stepZoomSubject.next(value);
    }
    getZoomValue() {
        return this.zoomValueSubject.asObservable();
    }
    getPageCount() {
        return this.pageCountSubject.asObservable();
    }
    print() {
        this.printSubject.next();
    }
    download() {
        this.downloadSubject.next();
    }
    setPage(value) {
        this.setCurrentPageSubject.next(value);
    }
    incrementPage(value) {
        this.changePageByDeltaSubject.next(value);
    }
    getCurrentPageNumber() {
        return this.setCurrentPageInputValueSubject.asObservable();
    }
    getShowCommentSummary() {
        return this.showCommentSummary.asObservable();
    }
    toggleCommentsSummary(value) {
        this.showCommentSummary.next(value);
    }
    saveRotation() {
        this.saveRotationSubject.next();
    }
    toggleGrabNDrag() {
        this.grabNDrag.next(!this.grabNDrag.getValue());
    }
    toggleSideBar(toggle) {
        this.sidebarOpen.next(toggle);
    }
    toggleSideBarView(toggle) {
        this.sidebarOutlineView.next(toggle);
    }
    toggleRedactionMode() {
        if (this.redactionMode.getValue() === false) {
            this.drawModeSubject.next(false);
            this.grabNDrag.next(false);
            this.redactionMode.next(true);
        }
        else {
            this.redactionMode.next(false);
        }
        this.openRedactionSearch.next({ modeType: SearchType.Redact, isOpen: false });
    }
    toggleRedactionPreview(viewMode) {
        this.redactionPreview.next(viewMode);
    }
    unmarkAll() {
        this.clearAllRedactMarkers.next();
    }
    applyRedactionToDocument() {
        this.applyRedactToDocument.next();
    }
    redactPage() {
        this.redactWholePage.next();
    }
    toggleCommentsPanel(isVisible) {
        if (isVisible) {
            this.toggleParticipantsList(!isVisible);
        }
        this.commentsPanelVisible.next(isVisible);
    }
    toggleParticipantsList(isVisible) {
        if (isVisible) {
            this.toggleCommentsPanel(!isVisible);
        }
        this.icpEventService.participantsListVisible.next(isVisible);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ToolbarEventService, deps: [{ token: IcpEventService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ToolbarEventService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ToolbarEventService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: IcpEventService }] });

class PdfJsWrapperFactory {
    constructor(toolbarEvents) {
        this.toolbarEvents = toolbarEvents;
        this.linkService = new pdfjsViewer.PDFLinkService();
        this.eventBus = new pdfjsViewer.EventBus();
    }
    create(container) {
        const pdfFindController = new pdfjsViewer.PDFFindController({
            linkService: this.linkService,
            eventBus: this.eventBus
        });
        const pdfViewer = new pdfjsViewer.PDFViewer({
            container: container.nativeElement,
            linkService: this.linkService,
            findController: pdfFindController,
            eventBus: this.eventBus,
            imageResourcesPath: '/assets/images/',
        });
        this.linkService.setViewer(pdfViewer);
        this.pdfJsWrapper = new PdfJsWrapper(pdfViewer, new pdfjsViewer.DownloadManager(), this.toolbarEvents, new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject());
        return this.pdfJsWrapper;
    }
    pdfWrapper() {
        return this.pdfJsWrapper;
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PdfJsWrapperFactory, deps: [{ token: ToolbarEventService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PdfJsWrapperFactory, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PdfJsWrapperFactory, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: ToolbarEventService }] });

class PrintService {
    printDocumentNatively(url) {
        const printWindow = window.open(url);
        printWindow.focus();
        setTimeout((printer) => {
            printer.print();
        }, 3000, printWindow);
    }
    printElementNatively(element, width, height) {
        const printWindow = window.open('', '', `left=0,top=0,width=${width},height=${height},toolbar=0,scrollbars=0,status=0`);
        const documentHead = document.head;
        printWindow.document.body.appendChild(documentHead.cloneNode(true));
        printWindow.document.body.appendChild(element.cloneNode(true));
        printWindow.document.close();
        printWindow.focus();
        printWindow.print();
        setTimeout((printer) => {
            printer.close();
        }, 1000, printWindow);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PrintService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PrintService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PrintService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }] });

class ViewerEventService {
    constructor() {
        this.textHighlight = new Subject();
        this.boxHighlight = new Subject();
        this.ctxToolbarCleared = new Subject();
        this.navigationEvent = new Subject();
        this.navigationEventICP = new Subject();
    }
    textSelected(selectionData) {
        this.textHighlight.next(selectionData);
    }
    boxSelected(selectionData) {
        this.boxHighlight.next(selectionData);
    }
    clearCtxToolbar() {
        this.ctxToolbarCleared.next();
    }
    goToDestination(destination) {
        this.navigationEvent.next(destination);
    }
    goToDestinationICP(destination) {
        this.navigationEventICP.next(destination);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ViewerEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ViewerEventService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ViewerEventService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [] });

const getIcpState = createSelector(getMVState, (state) => state.icp);
const getIcpSession = createSelector(getIcpState, getIcpSession$1);
const getCaseId = createSelector(getIcpSession, session => session === null ? null : session.caseId);
const getPresenter = createSelector(getIcpState, getPresenter$1);
const getPresenterName = createSelector(getPresenter, presenter => presenter === null ? null : presenter.username);
const getClient = createSelector(getIcpState, getClient$1);
const isPresenter = createSelector(getPresenter, getClient, (presenter, client) => presenter === null ? undefined : presenter.id === client.id // isPresenter is called when = false.
);
const getParticipants = createSelector(getIcpState, getParticipants$1);

var IcpEvents;
(function (IcpEvents) {
    IcpEvents["SESSION_JOINED"] = "IcpClientJoinedSession";
    IcpEvents["CLIENT_DISCONNECTED"] = "IcpClientDisconnectedFromSession";
    IcpEvents["NEW_PARTICIPANT_JOINED"] = "IcpNewParticipantJoinedSession";
    IcpEvents["REMOVE_PARTICIPANT"] = "IcpRemoveParticipantFromList";
    IcpEvents["PARTICIPANTS_UPDATED"] = "IcpParticipantsListUpdated";
    IcpEvents["UPDATE_PRESENTER"] = "IcpNewPresenterStartsPresenting";
    IcpEvents["PRESENTER_UPDATED"] = "IcpPresenterUpdated";
    IcpEvents["UPDATE_SCREEN"] = "IcpUpdateScreen";
    IcpEvents["SCREEN_UPDATED"] = "IcpScreenUpdated";
    IcpEvents["SESSION_JOIN"] = "IcpClientJoinSession";
    IcpEvents["SESSION_LEAVE"] = "IcpClientLeaveSession";
})(IcpEvents || (IcpEvents = {}));

class SocketService {
    constructor() {
        this.connected$ = new BehaviorSubject(false);
        this.sessionJoined$ = new Subject();
        this.presenterUpdated$ = new Subject();
        this.clientDisconnected$ = new Subject();
        this.participantUpdated$ = new Subject();
        this.newParticipantJoined$ = new Subject();
        this.screenUpdated$ = new Subject();
    }
    ngOnDestroy() {
        this.subscription.unsubscribe();
    }
    connect(url, session) {
        const socketUrl = new URL(url);
        socketUrl.searchParams.append('sessionId', `${session.sessionId}`);
        socketUrl.searchParams.append('caseId', `${session.caseId}`);
        socketUrl.searchParams.append('documentId', `${session.documentId}`);
        return this.getSocketClient(socketUrl.toString()).subscribe((socket) => {
            socket.onopen = (event) => {
                this.connected$.next(true);
            };
            socket.onmessage = (event) => {
                console.log('onmessage');
                const eventData = JSON.parse(event.data);
                if (eventData.data && eventData.data.eventName) {
                    this.messageEventHandller(eventData.data.eventName, eventData.data.data);
                }
            };
            socket.onerror = (event) => {
                console.log('onerror');
            };
            socket.onclose = (event) => {
                console.log('onclose');
            };
        });
    }
    connected() {
        return this.connected$.asObservable();
    }
    join(session) {
        this.emit(IcpEvents.SESSION_JOIN, session);
    }
    leave(session) {
        this.emit(IcpEvents.SESSION_LEAVE, session);
        this.subscription.unsubscribe();
    }
    emit(event, data) {
        this.socket.send(JSON.stringify({
            type: 'event',
            event,
            data
        }));
    }
    listen(event) {
        switch (event) {
            case IcpEvents.SESSION_JOINED: {
                return this.sessionJoined$.asObservable();
            }
            case IcpEvents.PRESENTER_UPDATED: {
                return this.presenterUpdated$.asObservable();
            }
            case IcpEvents.CLIENT_DISCONNECTED: {
                return this.clientDisconnected$.asObservable();
            }
            case IcpEvents.PARTICIPANTS_UPDATED: {
                return this.participantUpdated$.asObservable();
            }
            case IcpEvents.NEW_PARTICIPANT_JOINED: {
                return this.newParticipantJoined$.asObservable();
            }
            case IcpEvents.SCREEN_UPDATED: {
                return this.screenUpdated$.asObservable();
            }
            default: {
                break;
            }
        }
    }
    messageEventHandller(eventName, data) {
        switch (eventName) {
            case IcpEvents.SESSION_JOINED: {
                this.sessionJoined$.next(data);
                break;
            }
            case IcpEvents.PRESENTER_UPDATED: {
                this.presenterUpdated$.next(data);
                break;
            }
            case IcpEvents.CLIENT_DISCONNECTED: {
                this.clientDisconnected$.next();
                break;
            }
            case IcpEvents.PARTICIPANTS_UPDATED: {
                this.participantUpdated$.next(data);
                break;
            }
            case IcpEvents.NEW_PARTICIPANT_JOINED: {
                this.newParticipantJoined$.next();
                break;
            }
            case IcpEvents.SCREEN_UPDATED: {
                this.screenUpdated$.next(data);
                break;
            }
        }
    }
    getSocketClient(url) {
        this.socket = new WebSocket(url, 'json.webpubsub.azure.v1');
        return of(this.socket);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SocketService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SocketService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SocketService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [] });

class IcpUpdateService {
    constructor(socket) {
        this.socket = socket;
    }
    joinSession(username, session, token) {
        this.session = session;
        console.log('Joining Session');
        console.log(this.session);
        console.log('Joining session');
        this.socket.connect(`${session.connectionUrl}?access_token=${token}`, session);
        this.socket.connected().subscribe(isConnected => {
            if (isConnected) {
                this.socket.join({ ...this.session, username });
            }
        });
        return this.socket.listen(IcpEvents.SESSION_JOINED);
    }
    leaveSession() {
        this.socket.leave(this.session);
    }
    newParticipantJoined() {
        return this.socket.listen(IcpEvents.NEW_PARTICIPANT_JOINED);
    }
    clientDisconnected() {
        return this.socket.listen(IcpEvents.CLIENT_DISCONNECTED);
    }
    removeParticipant(participantId) {
        this.socket.emit(IcpEvents.REMOVE_PARTICIPANT, {
            participantId: participantId,
            caseId: this.session.caseId,
            documentId: this.session.documentId
        });
    }
    participantListUpdated() {
        return this.socket.listen(IcpEvents.PARTICIPANTS_UPDATED);
    }
    updatePresenter(presenter) {
        this.socket.emit(IcpEvents.UPDATE_PRESENTER, {
            ...this.session,
            presenterId: presenter.id,
            presenterName: presenter.username
        });
    }
    presenterUpdated() {
        return this.socket.listen(IcpEvents.PRESENTER_UPDATED);
    }
    updateScreen(screen) {
        const update = {
            body: screen,
            caseId: this.session.caseId,
            documentId: this.session.documentId
        };
        this.socket.emit(IcpEvents.UPDATE_SCREEN, update);
    }
    screenUpdated() {
        return this.socket.listen(IcpEvents.SCREEN_UPDATED);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpUpdateService, deps: [{ token: SocketService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpUpdateService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpUpdateService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: SocketService }] });

class IcpPresenterService {
    constructor(toolbarEvents, socketService, store) {
        this.toolbarEvents = toolbarEvents;
        this.socketService = socketService;
        this.store = store;
    }
    update(isPresenter) {
        if (isPresenter) {
            this.subscribe();
        }
        else {
            this.unsubscribe();
        }
    }
    subscribe() {
        if (!this.$subscription) {
            this.$subscription = this.store.pipe(select(getPdfPosition)).subscribe(pdfPosition => {
                this.pdfPosition = pdfPosition;
                this.onPositionUpdate(pdfPosition);
            });
            this.$subscription.add(this.store.pipe(select(getPresenter)).subscribe(presenter => {
                this.presenter = presenter;
            }));
            this.$subscription.add(this.socketService.newParticipantJoined().subscribe(() => this.onNewParticipantJoined()));
        }
    }
    unsubscribe() {
        if (this.$subscription) {
            this.$subscription.unsubscribe();
            this.$subscription = undefined;
        }
    }
    onPositionUpdate(pdfPosition) {
        const screen = { pdfPosition, document: undefined };
        this.socketService.updateScreen(screen);
    }
    onNewParticipantJoined() {
        this.onPositionUpdate(this.pdfPosition);
        this.socketService.updatePresenter(this.presenter);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpPresenterService, deps: [{ token: ToolbarEventService }, { token: IcpUpdateService }, { token: i1.Store }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpPresenterService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpPresenterService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: IcpUpdateService }, { type: i1.Store }] });

class IcpFollowerService {
    constructor(toolbarEvents, viewerEvents, socketService, store) {
        this.toolbarEvents = toolbarEvents;
        this.viewerEvents = viewerEvents;
        this.socketService = socketService;
        this.store = store;
        this.previousRotation = null;
    }
    update(isFollower) {
        if (isFollower) {
            this.subscribe();
        }
        else {
            this.unsubscribe();
        }
    }
    subscribe() {
        if (!this.$subscription) {
            this.$subscription = this.socketService.screenUpdated()
                .subscribe(screen => this.followScreenUpdate(screen));
        }
    }
    unsubscribe() {
        if (this.$subscription) {
            this.$subscription.unsubscribe();
            this.$subscription = undefined;
        }
    }
    followScreenUpdate({ pdfPosition }) {
        if (pdfPosition) {
            this.viewerEvents.goToDestinationICP([
                pdfPosition.pageNumber - 1,
                { 'name': 'XYZ' },
                pdfPosition.left,
                pdfPosition.top
            ]);
        }
        this.store.pipe(select(getPdfPosition), take(1), distinctUntilChanged(undefined, a => a.rotation))
            .subscribe(position => {
            if (this.previousRotation === pdfPosition.rotation) {
                return;
            }
            const rotationDelta = (pdfPosition.rotation - position.rotation) % 360;
            if (rotationDelta && rotationDelta !== 0) {
                this.toolbarEvents.rotate(rotationDelta);
            }
        });
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpFollowerService, deps: [{ token: ToolbarEventService }, { token: ViewerEventService }, { token: IcpUpdateService }, { token: i1.Store }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpFollowerService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpFollowerService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: ViewerEventService }, { type: IcpUpdateService }, { type: i1.Store }] });

class IcpService {
    constructor(toolbarEvents, viewerEvents, socketService, presenterSubscriptions, followerSubscriptions, store, icpEventService) {
        this.toolbarEvents = toolbarEvents;
        this.viewerEvents = viewerEvents;
        this.socketService = socketService;
        this.presenterSubscriptions = presenterSubscriptions;
        this.followerSubscriptions = followerSubscriptions;
        this.store = store;
        this.icpEventService = icpEventService;
        this.subscription = this.store.pipe(select(getCaseId), filter(value => !!value)).subscribe(caseId => {
            this.caseId = caseId;
        });
        this.subscription.add(this.store.pipe(select(getDocumentId)).subscribe(docId => this.documentId = docId));
        this.subscription.add(this.icpEventService.sessionLaunch.subscribe(() => {
            if (this.caseId && this.documentId) {
                this.launchSession();
            }
        }));
    }
    ngOnDestroy() {
        this.unsubscribeSession();
        this.subscription.unsubscribe();
    }
    launchSession() {
        this.store.dispatch(new LoadIcpSession({ caseId: this.caseId, documentId: this.documentId }));
        this.subscription.add(this.store.pipe(select(getIcpSession), filter(value => !!value && Object.keys(value).length > 1), take(1)).subscribe(() => { this.setUpSessionSubscriptions(); }));
    }
    setUpSessionSubscriptions() {
        this.sessionSubscription = this.icpEventService.becomingPresenter.subscribe(() => this.becomePresenter());
        this.sessionSubscription.add(this.icpEventService.stoppingPresenting.subscribe(() => this.stopPresenting()));
        this.sessionSubscription.add(this.icpEventService.sessionExitConfirmed.subscribe(() => this.leavePresentation()));
        this.sessionSubscription.add(this.store.pipe(select(getPresenter)).subscribe(presenter => this.presenter = presenter));
        this.sessionSubscription.add(this.store.pipe(select(getClient)).subscribe(client => this.client = client));
        this.sessionSubscription.add(this.store.pipe(select(isPresenter)).subscribe(isPresenter => {
            this.isPresenter = isPresenter;
            this.presenterSubscriptions.update(isPresenter);
            this.followerSubscriptions.update(!isPresenter);
        }));
        this.sessionSubscription.add(this.socketService.clientDisconnected().subscribe(cli => this.clientDisconnected(cli)));
        this.sessionSubscription.add(this.socketService.presenterUpdated().subscribe(pres => {
            this.store.dispatch(new IcpPresenterUpdated(pres));
        }));
        this.sessionSubscription.add(this.socketService.participantListUpdated().subscribe(participants => {
            this.store.dispatch(new IcpParticipantListUpdated(participants));
        }));
    }
    unsubscribeSession() {
        this.presenterSubscriptions.update(false);
        this.followerSubscriptions.update(false);
        this.sessionSubscription.unsubscribe();
    }
    leavePresentation() {
        if (this.isPresenter) {
            this.stopPresenting();
        }
        this.removeParticipant(this.client.id);
        this.socketService.leaveSession();
        this.store.dispatch(new LeaveIcpSocketSession());
        this.unsubscribeSession();
    }
    stopPresenting() {
        const presenter = { username: '', id: '' };
        this.socketService.updatePresenter(presenter);
    }
    becomePresenter() {
        this.socketService.updatePresenter(this.client);
    }
    clientDisconnected(client) {
        if (client === this.presenter.id) {
            this.stopPresenting();
        }
        this.removeParticipant(client);
    }
    removeParticipant(participantId) {
        this.socketService.removeParticipant(participantId);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpService, deps: [{ token: ToolbarEventService }, { token: ViewerEventService }, { token: IcpUpdateService }, { token: IcpPresenterService }, { token: IcpFollowerService }, { token: i1.Store }, { token: IcpEventService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: ViewerEventService }, { type: IcpUpdateService }, { type: IcpPresenterService }, { type: IcpFollowerService }, { type: i1.Store }, { type: IcpEventService }] });

class ToolbarButtonVisibilityService {
    constructor() {
        this.showPrint = false;
        this.showDownload = false;
        this.showNavigation = false;
        this.showZoom = false;
        this.showRotate = false;
        this.showPresentationMode = false;
        this.showRedact = false;
        this.showOpenFile = false;
        this.showBookmark = false;
        this.showHighlightButton = false;
        this.showDrawButton = false;
        this.showSearchBar = false;
        this.showSidebar = false;
        this.showCommentSummary = false;
        this.showGrabNDragButton = false;
        this.showSaveRotationButton = false;
    }
    /**
     * Reset the visibility of all buttons to false then set the value from the options
     */
    setup(options) {
        this.showPrint = false;
        this.showDownload = false;
        this.showNavigation = false;
        this.showZoom = false;
        this.showRotate = false;
        this.showPresentationMode = false;
        this.showRedact = false;
        this.showOpenFile = false;
        this.showBookmark = false;
        this.showHighlightButton = false;
        this.showDrawButton = false;
        this.showSearchBar = false;
        this.showSidebar = false;
        this.showCommentSummary = false;
        this.showGrabNDragButton = false;
        this.showSaveRotationButton = false;
        for (const key in options) {
            this[key] = options[key];
        }
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ToolbarButtonVisibilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ToolbarButtonVisibilityService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ToolbarButtonVisibilityService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });
/**
 * Default toolbar state for the PDF viewer
 */
const defaultPdfOptions = {
    showPrint: true,
    showDownload: true,
    showNavigation: true,
    showZoom: true,
    showRotate: true,
    showSearchBar: true,
    showSidebar: true,
    showGrabNDragButton: true,
    showCommentSummary: true,
    showPresentationMode: true,
    showRedact: true
};
/**
 * Default toolbar state for the image viewer
 */
const defaultImageOptions = {
    showPrint: true,
    showDownload: true,
    showZoom: true,
    showRotate: true,
    showGrabNDragButton: true,
    showCommentSummary: true,
    showRedact: true
};
/**
 * Default toolbar state for multimedia
 */
const defaultMultimediaOptions = {
    showDownload: true
};
/**
 * Default toolbar state for unsupported media
 */
const defaultUnsupportedOptions = {
    showDownload: true,
    showPrint: true
};

/**
 * Helper Class
 * Used for dynamic templates manipulation
 * */
class HtmlTemplatesHelper {
    static setDescribedBy(errorMessage, config) {
        if (!errorMessage) {
            return config.hint ? `${config.id}-hint` : null;
        }
        else if (errorMessage && errorMessage.isInvalid) {
            return config.hint ? `${config.id}-hint ${config.id}-error` : `${config.id}-error`;
        }
        else {
            return config.hint ? `${config.id}-hint` : null;
        }
    }
    static getAdjustedBoundingRect(element, log = true) {
        const viewportX = window.visualViewport.offsetLeft;
        const viewportY = window.visualViewport.offsetTop;
        const viewportScale = window.visualViewport.scale;
        const viewportPageX = window.visualViewport.pageLeft;
        const viewportPageY = window.visualViewport.pageTop;
        if (log && viewportX || viewportY || (viewportScale != 1) || viewportPageX || viewportPageY) {
            console.log(`Element: ${element.id} Viewport X: ${viewportX}, Y: ${viewportY}, Scale: ${viewportScale}, PageX: ${viewportPageX}, PageY: ${viewportPageY}`);
        }
        return element.getBoundingClientRect();
    }
}

const getTagsRootState = createSelector(getMVState, (state) => state.tags);
const getTagEntities = createSelector(getTagsRootState, getTagNameEnt);
const getTagFilters = createSelector(getTagsRootState, getFilters);
const getTagFiltered = createSelector(getTagsRootState, getFilteredComments);
const getFilteredPageEntities = createSelector(getTagsRootState, getFilteredPageEnt);
const getAllTagsArr = createSelector(getTagEntities, (tagEnt) => Object.keys(tagEnt).map(key => {
    return {
        key,
        length: Object.keys(tagEnt[key]).length
    };
}));

const getAnnotationsSetState = createSelector(getMVState, (state) => state.annotations);
const getAnnotationEntities = createSelector(getAnnotationsSetState, getAnnoEnt);
const getSet = createSelector(getAnnotationsSetState, getAnnoSet);
const getDocumentIdSetId = createSelector(getSet, (annoSet) => {
    return {
        documentId: annoSet.documentId,
        annotationSetId: annoSet.id
    };
});
const getAnnotationSet = createSelector(getAnnotationEntities, getSet, (entities, set) => {
    return {
        ...set,
        annotations: Object.keys(entities).map(key => entities[key])
    };
});
const getSelectedAnnotation = createSelector(getAnnotationsSetState, getSelectedAnno);
const getCommentEntities = createSelector(getAnnotationsSetState, getCommentEnts);
const getPageEntities = createSelector(getAnnotationsSetState, getAnnoPageEnt);
const getComponentSearchQueries = createSelector(getAnnotationsSetState, commentSearchQ);
const getComponentSearchText = createSelector(getComponentSearchQueries, (queries) => queries.commentSearch);
const getCommentSummaryFilters = createSelector(getAnnotationsSetState, getSummaryFilters);
const getAnnoPerPage = createSelector(getPages, getPageEntities, getFilteredPageEntities, (pages, pageEnt, filteredPageEnt) => {
    const isFiltered = !!Object.keys(filteredPageEnt).length;
    const entities = isFiltered ? filteredPageEnt : pageEnt;
    if (pages) {
        const arr = [];
        Object.keys(pages).forEach(key => {
            arr.push({
                anno: entities[key] ? entities[key] : [],
                styles: pages[key].styles
            });
        });
        return arr;
    }
});
const getCommentsArray = createSelector(getCommentEntities, getPages, getAnnotationEntities, getTagFiltered, (commentEnts, pages, annoEnts, filtered) => {
    if (commentEnts && annoEnts && pages[1]) {
        const isFiltered = !!Object.keys(filtered).length;
        const com = isFiltered ? filtered : commentEnts;
        return Object.keys(com).map(key => {
            const page = annoEnts[key].page;
            return {
                ...commentEnts[key],
                page,
                pages
            };
        });
    }
});
const getCommentSummary = createSelector(getCommentsArray, getCommentSummaryFilters, (commentSummary = [], filters) => {
    const comments = StoreUtils.filterCommentsSummary(commentSummary, filters.filters);
    if (comments.length) {
        const savedComments = comments.filter((comment) => {
            return comment.createdByDetails !== undefined;
        });
        return savedComments.map((comment) => {
            return {
                page: comment.page,
                user: comment.createdByDetails.forename.concat(' ').concat(comment.createdByDetails.surname),
                date: moment(comment.lastModifiedDate).format('D MMMM YYYY'),
                tags: comment.tags,
                comment: comment.content
            };
        });
    }
    return [''];
});
const getFilteredAnnotations = createSelector(getAnnotationEntities, getTagFiltered, (annoEnt, filters) => {
    const isFiltered = !!Object.keys(filters).length;
    const anno = isFiltered ? filters : annoEnt;
    return Object.keys(anno).map(key => annoEnt[key])
        .filter(annotation => annotation.comments && annotation.comments.length > 0);
});

class HighlightCreateService {
    constructor(toolBarEvents, store) {
        this.toolBarEvents = toolBarEvents;
        this.store = store;
    }
    saveAnnotation(rectangles, page) {
        this.store.pipe(select(getDocumentIdSetId), take(1)).subscribe(anoSetDocId => {
            const anno = {
                id: v4(),
                color: 'FFFF00',
                comments: [],
                page: page,
                rectangles: rectangles,
                type: 'highlight',
                ...anoSetDocId,
                createdBy: '',
                createdByDetails: undefined,
                createdDate: moment.utc().tz('Europe/London').toISOString(),
                lastModifiedBy: '',
                lastModifiedByDetails: undefined,
                lastModifiedDate: '',
                tags: [],
            };
            this.store.dispatch(new SaveAnnotation(anno));
        });
    }
    saveAnnotationSet(searchRectangles) {
        this.store.pipe(select(getDocumentIdSetId), take(1)).subscribe(anoSetDocId => {
            const annoSet = searchRectangles.map(x => {
                return {
                    id: v4(),
                    color: 'FFFF00',
                    comments: [],
                    page: x.page,
                    rectangles: x.rectangles,
                    type: 'highlight',
                    ...anoSetDocId,
                    createdBy: '',
                    createdByDetails: undefined,
                    createdDate: moment.utc().tz('Europe/London').toISOString(),
                    lastModifiedBy: '',
                    lastModifiedByDetails: undefined,
                    lastModifiedDate: '',
                    tags: [],
                };
            });
            this.store.dispatch(new SaveAnnotationSet({
                id: anoSetDocId.annotationSetId, annotations: annoSet, documentId: anoSetDocId.documentId
            }));
        });
    }
    applyRotation(pageHeight, pageWidth, offsetHeight, offsetWidth, offsetTop, offsetLeft, rotate, zoom) {
        const { x, y, width, height } = {
            x: +(offsetLeft / zoom).toFixed(2),
            y: +(offsetTop / zoom).toFixed(2),
            width: +(offsetWidth / zoom).toFixed(2),
            height: +(offsetHeight / zoom).toFixed(2)
        };
        const rectangle = { x, y, width, height };
        switch (rotate) {
            case 90:
                rectangle.width = height;
                rectangle.height = width;
                rectangle.x = y;
                rectangle.y = +(pageWidth / zoom - x - width).toFixed(2);
                break;
            case 180:
                rectangle.x = +(pageWidth / zoom - x - width).toFixed(2);
                rectangle.y = +(pageHeight / zoom - y - height).toFixed(2);
                break;
            case 270:
                rectangle.width = height;
                rectangle.height = width;
                rectangle.x = +(pageHeight / zoom - y - height).toFixed(2);
                rectangle.y = x;
                break;
        }
        return rectangle;
    }
    resetHighlight() {
        window.getSelection().removeAllRanges();
        this.toolBarEvents.highlightModeSubject.next(false);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HighlightCreateService, deps: [{ token: ToolbarEventService }, { token: i1.Store }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HighlightCreateService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HighlightCreateService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: i1.Store }] });

class RedactionSearchBarComponent {
    constructor(store, toolbarButtons, toolbarEvents, highlightService) {
        this.store = store;
        this.toolbarButtons = toolbarButtons;
        this.toolbarEvents = toolbarEvents;
        this.highlightService = highlightService;
        this.highlightAll = true;
        this.matchCase = false;
        this.wholeWord = false;
        this.resultsText = '';
        this.searchText = '';
        this.resultCount = 0;
        this.redactElements = [];
        this.advancedSearchVisible = false;
    }
    ngOnInit() {
        this.subscription = this.toolbarEvents.redactionSerachSubject.subscribe((results) => this.redactAllSearched(results));
        this.subscription.add(this.store.pipe(select(getDocumentId)).subscribe(docId => this.documentId = docId));
        this.subscription.add(this.store.pipe(select(getPages)).subscribe((pages) => {
            if (pages[1]) {
                this.allPages = pages;
            }
        }));
        this.subscription.add(this.toolbarEvents.searchResultsCountSubject.subscribe(results => this.setSearchResultsCount(results)));
        this.subscription.add(this.toolbarEvents.openRedactionSearch.subscribe((searchMode) => {
            if (searchMode) {
                this.openSearchModal = searchMode.isOpen;
                this.searchType = searchMode.modeType;
                this.modeText();
            }
        }));
        this.subscription.add(this.toolbarEvents.redactAllInProgressSubject
            .subscribe(inProgress => this.redactAllInProgress = inProgress));
    }
    ngOnDestroy() {
        this.subscription.unsubscribe();
    }
    onWindowKeyDown(e) {
        if (e.code === 'F3' || (e.ctrlKey && e.code === 'KeyF')) {
            e.preventDefault();
            this.toolbarEvents.searchBarHidden.next(false);
            setTimeout(() => this.findInput.nativeElement.focus(), 200);
        }
    }
    search(reset = true) {
        this.redactAll = !reset;
        if (this.redactAll) {
            this.toolbarEvents.redactAllInProgressSubject.next(true);
        }
        if (reset) {
            this.redactElements = [];
        }
        this.toolbarEvents.search({
            searchTerm: this.searchText,
            highlightAll: this.highlightAll,
            matchCase: this.matchCase,
            wholeWord: this.wholeWord,
            previous: false,
            reset
        });
    }
    modeText() {
        if (this.searchType === SearchType.Highlight) {
            this.inProgressText = 'Highlighting';
            this.titleText = 'Highlight';
        }
        else if (this.searchType === SearchType.Redact) {
            this.inProgressText = 'Redacting';
            this.titleText = 'Redact';
        }
    }
    saveRedaction(redactRectangle) {
        const redaction = redactRectangle.map(ele => {
            return { page: ele.page, rectangles: ele.rectangles, redactionId: v4(), documentId: this.documentId };
        });
        this.store.dispatch(new SaveBulkRedaction({ searchRedactions: redaction }));
    }
    existInRedactElements(pageNumber, matechedIndex, rectangles) {
        if (this.redactElements && this.redactElements.length > 0) {
            const pagesFound = this.redactElements.find(re => re.page === pageNumber && re.matchedIndex === matechedIndex);
            const pageRectangles = pagesFound?.rectangles;
            if (!pageRectangles || pageRectangles.length <= 0) {
                return false;
            }
            let matchesRectangles = 0;
            for (let rectIndx = 0; rectIndx < pageRectangles.length; rectIndx++) {
                const rectangle = pageRectangles[rectIndx];
                const foundRectangle = rectangles.find(re => re.width === rectangle.width &&
                    re.height === rectangle.height && re.x === rectangle.x && re.y === rectangle.y);
                if (foundRectangle) {
                    matchesRectangles++;
                }
            }
            return pageRectangles.length === matchesRectangles;
        }
        return false;
    }
    onCloseSearchModal() {
        this.toolbarEvents.openRedactionSearch.next({ isOpen: false, modeType: this.searchType });
    }
    setSearchResultsCount(results) {
        this.resultCount = results.total;
        this.resultsText = this.resultCount > 0
            ? `${results.total} results founds`
            : 'No results found';
    }
    redactAllSearched(results) {
        const $this = this;
        const intervalId = setInterval(() => {
            const highlightElement = document.getElementsByClassName('highlight selected');
            if (highlightElement && highlightElement.length > 0) {
                clearInterval(intervalId);
                $this.redactAllSearchedTick(results);
            }
        }, 100);
    }
    redactAllSearchedTick(results) {
        const highlightElement = document.getElementsByClassName('highlight selected');
        if (highlightElement && highlightElement.length > 0) {
            this.resultCount = results.matchesCount;
            const pageNumber = results.page + 1;
            const rectangles = this.getRectangles(pageNumber);
            if (rectangles && this.redactElements.length <= this.resultCount
                && !this.existInRedactElements(pageNumber, results.matchedIndex, rectangles)) {
                this.redactElements.push({ page: pageNumber, matchedIndex: results?.matchedIndex, rectangles });
                this.CreateRedactAllText();
            }
            if (this.redactAll && this.resultCount && this.resultCount > 0
                && rectangles && this.redactElements.length < this.resultCount) {
                this.search(false);
            }
            if (this.redactAll && this.resultCount && this.redactElements.length === this.resultCount) {
                this.redactAll = false;
                this.redactAllText = null;
                if (this.searchType === SearchType.Redact) {
                    this.saveRedaction(this.redactElements);
                }
                else if (this.searchType === SearchType.Highlight) {
                    this.highlightService.saveAnnotationSet(this.redactElements);
                    this.cleanUpPostSave();
                }
            }
        }
    }
    cleanUpPostSave() {
        this.toolbarEvents.redactAllInProgressSubject.next(false);
        this.searchText = '';
        this.search();
    }
    CreateRedactAllText() {
        this.redactAllText = `${this.redactElements.length} of ${this.resultCount}`;
    }
    onEscapeKeyPress(e) {
        this.toolbarEvents.searchBarHidden.next(true);
    }
    onEnterKeyPress(e) {
        this.search();
    }
    toggleSearchBar() {
        this.toolbarEvents.searchBarHidden.next(!this.toolbarEvents.searchBarHidden.getValue());
    }
    getRectangles(page) {
        this.pageHeight = this.allPages[page].styles.height;
        this.pageWidth = this.allPages[page].styles.width;
        this.zoom = parseFloat(this.allPages[page].scaleRotation.scale);
        this.rotate = parseInt(this.allPages[page].scaleRotation.rotation, 10);
        const selectedHighLightedElements = document.getElementsByClassName('highlight selected');
        if (selectedHighLightedElements && selectedHighLightedElements.length > 0) {
            const docRange = document.createRange();
            if (some(selectedHighLightedElements, element => element.className === 'highlight begin selected' || element.className === 'highlight end selected')) {
                docRange.setStart(selectedHighLightedElements[0], 0);
                const endNode = selectedHighLightedElements[selectedHighLightedElements.length - 1];
                docRange.setEnd(endNode, endNode.childNodes.length);
            }
            else {
                docRange.selectNodeContents(selectedHighLightedElements[0]);
            }
            const selection = window.getSelection();
            selection?.removeAllRanges();
            selection?.addRange(docRange);
            if (selection.rangeCount && !selection.isCollapsed) {
                const range = selection.getRangeAt(0).cloneRange();
                const clientRects = range.getClientRects();
                if (clientRects) {
                    const parentRect = HtmlTemplatesHelper.getAdjustedBoundingRect(selectedHighLightedElements[0]?.parentElement?.parentElement);
                    const selectionRectangles = [];
                    for (let i = 0; i < clientRects.length; i++) {
                        const selectionRectangle = this.createTextRectangle(clientRects[i], parentRect);
                        const findSelecttionRectangle = selectionRectangles.find((rect) => rect.width === selectionRectangle.width && rect.x === selectionRectangle.x);
                        if (!findSelecttionRectangle) {
                            selectionRectangles.push(selectionRectangle);
                        }
                    }
                    return selectionRectangles;
                }
            }
        }
    }
    createTextRectangle(rect, parentRect) {
        const height = rect.bottom - rect.top;
        const width = rect.right - rect.left;
        const top = rect.top - parentRect.top;
        const left = rect.left - parentRect.left;
        let rectangle = this.highlightService.applyRotation(this.pageHeight, this.pageWidth, height, width, top, left, this.rotate, this.zoom);
        rectangle = { id: v4(), ...rectangle };
        return rectangle;
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedactionSearchBarComponent, deps: [{ token: i1.Store }, { token: ToolbarButtonVisibilityService }, { token: ToolbarEventService }, { token: HighlightCreateService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: RedactionSearchBarComponent, selector: "mv-redaction-search-bar", host: { listeners: { "window:keydown": "onWindowKeyDown($event)" } }, viewQueries: [{ propertyName: "findInput", first: true, predicate: ["findInput"], descendants: true, static: true }], ngImport: i0, template: "<div\n  *ngIf=\"openSearchModal\"\n  class=\"searchbar redaction-search-bar govuk-!-padding-3\"\n>\n  <div class=\"govuk-grid-row\">\n    <div class=\"govuk-grid-column-full govuk-!-padding-right-0\">\n      <div class=\"redaction-search-buttons-area\">\n        <button\n          id=\"mvCloseBtn\"\n          #mvCloseBtn\n          class=\"mv-button searchbar-button--close\"\n          title=\"Close Search\"\n          data-l10n-id=\"mvRedactBtn\"\n          (click)=\"onCloseSearchModal()\"\n        ></button>\n      </div>\n      <input\n        id=\"search_input\"\n        class=\"govuk-input govuk-!-width-three-quarters govuk-!-display-inline-block govuk-!-margin-top-5\"\n        type=\"text\"\n        aria-label=\"Redact from search\"\n        #findInput\n        title=\"Redact from search\"\n        placeholder=\"{{ titleText + ' from search...' | rpxTranslate }}\"\n        data-l10n-id=\"search_input\"\n        [ngModel]=\"searchText\"\n        (ngModelChange)=\"searchText = $event\"\n        (keydown.escape)=\"onEscapeKeyPress($event)\"\n        (keydown.enter)=\"onEnterKeyPress($event)\"\n      />\n      <div class=\"redaction-search-buttons-area\">\n        <button\n          id=\"mvSearchAllBtn\"\n          class=\"govuk-button govuk-!-margin-bottom-0\"\n          data-module=\"govuk-button\"\n          (click)=\"search()\"\n          [disabled]=\"redactAllInProgress\"\n        >\n          {{ \"Search\" | rpxTranslate }}\n        </button>\n        <button\n          id=\"mvRedactAllBtn\"\n          class=\"govuk-button govuk-!-margin-left-2 govuk-!-margin-bottom-0\"\n          data-module=\"govuk-button\"\n          (click)=\"search(false)\"\n          [disabled]=\"redactAllInProgress || resultCount <= 0\"\n        >\n          {{ titleText + \" all\" | rpxTranslate }}\n        </button>\n      </div>\n      <div\n        class=\"govuk-grid-column-three-quarters govuk-!-padding-left-0 govuk-!-padding-top-2 redaction-status-text\"\n      >\n        <span\n          id=\"findRedactResultsCount\"\n          class=\"govuk-grid-column-full govuk-!-margin-right-4 govuk-!-margin-left-0 govuk-!-padding-left-0\"\n          ><h4\n            class=\"govuk-!-display-inline-block govuk-!-margin-top-0 govuk-!-margin-bottom-1\"\n            *ngIf=\"redactAllInProgress\"\n          >\n            {{ inProgressText + \" in progress\" | rpxTranslate }}\n          </h4>\n          {{ redactAllInProgress ? \"\" : resultsText }}</span\n        >\n        <span>\n          <h5\n            id=\"redactAllInProgressCount\"\n            class=\"govuk-!-display-inline-block govuk-!-margin-top-0 govuk-!-margin-bottom-1\"\n          >\n            {{ redactAllInProgress ? redactAllText : \"\" }}\n          </h5>\n        </span>\n      </div>\n    </div>\n  </div>\n</div>\n", styles: [".redaction-search-buttons-area{display:flex;flex-direction:row;padding-top:.5rem}.redaction-search-bar{width:20rem;left:73%;top:2%}.redaction-status-text{height:2.6rem}\n"], dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: i5$1.RpxTranslatePipe, name: "rpxTranslate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedactionSearchBarComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-redaction-search-bar', template: "<div\n  *ngIf=\"openSearchModal\"\n  class=\"searchbar redaction-search-bar govuk-!-padding-3\"\n>\n  <div class=\"govuk-grid-row\">\n    <div class=\"govuk-grid-column-full govuk-!-padding-right-0\">\n      <div class=\"redaction-search-buttons-area\">\n        <button\n          id=\"mvCloseBtn\"\n          #mvCloseBtn\n          class=\"mv-button searchbar-button--close\"\n          title=\"Close Search\"\n          data-l10n-id=\"mvRedactBtn\"\n          (click)=\"onCloseSearchModal()\"\n        ></button>\n      </div>\n      <input\n        id=\"search_input\"\n        class=\"govuk-input govuk-!-width-three-quarters govuk-!-display-inline-block govuk-!-margin-top-5\"\n        type=\"text\"\n        aria-label=\"Redact from search\"\n        #findInput\n        title=\"Redact from search\"\n        placeholder=\"{{ titleText + ' from search...' | rpxTranslate }}\"\n        data-l10n-id=\"search_input\"\n        [ngModel]=\"searchText\"\n        (ngModelChange)=\"searchText = $event\"\n        (keydown.escape)=\"onEscapeKeyPress($event)\"\n        (keydown.enter)=\"onEnterKeyPress($event)\"\n      />\n      <div class=\"redaction-search-buttons-area\">\n        <button\n          id=\"mvSearchAllBtn\"\n          class=\"govuk-button govuk-!-margin-bottom-0\"\n          data-module=\"govuk-button\"\n          (click)=\"search()\"\n          [disabled]=\"redactAllInProgress\"\n        >\n          {{ \"Search\" | rpxTranslate }}\n        </button>\n        <button\n          id=\"mvRedactAllBtn\"\n          class=\"govuk-button govuk-!-margin-left-2 govuk-!-margin-bottom-0\"\n          data-module=\"govuk-button\"\n          (click)=\"search(false)\"\n          [disabled]=\"redactAllInProgress || resultCount <= 0\"\n        >\n          {{ titleText + \" all\" | rpxTranslate }}\n        </button>\n      </div>\n      <div\n        class=\"govuk-grid-column-three-quarters govuk-!-padding-left-0 govuk-!-padding-top-2 redaction-status-text\"\n      >\n        <span\n          id=\"findRedactResultsCount\"\n          class=\"govuk-grid-column-full govuk-!-margin-right-4 govuk-!-margin-left-0 govuk-!-padding-left-0\"\n          ><h4\n            class=\"govuk-!-display-inline-block govuk-!-margin-top-0 govuk-!-margin-bottom-1\"\n            *ngIf=\"redactAllInProgress\"\n          >\n            {{ inProgressText + \" in progress\" | rpxTranslate }}\n          </h4>\n          {{ redactAllInProgress ? \"\" : resultsText }}</span\n        >\n        <span>\n          <h5\n            id=\"redactAllInProgressCount\"\n            class=\"govuk-!-display-inline-block govuk-!-margin-top-0 govuk-!-margin-bottom-1\"\n          >\n            {{ redactAllInProgress ? redactAllText : \"\" }}\n          </h5>\n        </span>\n      </div>\n    </div>\n  </div>\n</div>\n", styles: [".redaction-search-buttons-area{display:flex;flex-direction:row;padding-top:.5rem}.redaction-search-bar{width:20rem;left:73%;top:2%}.redaction-status-text{height:2.6rem}\n"] }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: ToolbarButtonVisibilityService }, { type: ToolbarEventService }, { type: HighlightCreateService }], propDecorators: { findInput: [{
                type: ViewChild,
                args: ['findInput', { static: true }]
            }], onWindowKeyDown: [{
                type: HostListener,
                args: ['window:keydown', ['$event']]
            }] } });

// TODO: replace by NgRx
class CommentService {
    constructor() {
        this.unsavedChanges = new Subject();
        this.marginToCommentEmitter = new BehaviorSubject(false);
    }
    setCommentSet(commentSetComponent) {
        this.commentSetComponent = commentSetComponent;
    }
    onCommentChange(changes) {
        this.unsavedChanges.next(changes);
    }
    getUnsavedChanges() {
        return this.unsavedChanges.asObservable();
    }
    hasUnsavedComments(annotation) {
        if (annotation.comments.length > 0) {
            const comment = this.getComment(annotation);
            return comment.hasUnsavedChanges;
        }
        return false;
    }
    updateUnsavedCommentsStatus(annotation, hasUnsavedChanges) {
        const comment = this.getComment(annotation);
        comment.hasUnsavedChanges = hasUnsavedChanges;
        this.allCommentsSaved();
    }
    getComment(annotation) {
        return this.commentSetComponent.commentComponents
            .find(c => c.comment.annotationId === annotation.comments[0].annotationId);
    }
    resetCommentSet() {
        this.commentSetComponent = null;
    }
    allCommentsSaved() {
        this.onCommentChange(this.commentSetComponent.commentComponents.some(comment => comment.hasUnsavedChanges === true));
    }
    createMarginToCommentEvent(margin) {
        this.marginToCommentEmitter.next(margin);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentService, decorators: [{
            type: Injectable
        }] });

class CommentSetRenderService {
    redrawComponents(commentComponents, pageHeights, rotate, zoom) {
        let prevComment;
        this.sortComponents(commentComponents, pageHeights, rotate, zoom).forEach((comment) => {
            this.adjustIfOverlapping(comment, prevComment, zoom);
            prevComment = comment;
        });
    }
    sortComponents(commentComponents, pageHeights, rotate, zoom) {
        return commentComponents.sort((a, b) => {
            a.rectTop = this.top(a._rectangle, pageHeights[a.page - 1], rotate, zoom);
            b.rectTop = this.top(b._rectangle, pageHeights[b.page - 1], rotate, zoom);
            return this.processSort(a, b);
        });
    }
    adjustIfOverlapping(comment, prevComment, zoom) {
        if (prevComment) {
            const endOfPrevComment = prevComment.commentTop + this.height(prevComment);
            if (comment.commentTop <= endOfPrevComment) {
                comment.rectTop = (endOfPrevComment - comment.totalPrevPagesHeight) / zoom;
            }
        }
    }
    processSort(a, b) {
        if (this.onSameLine(a, b)) {
            return a.rectLeft >= b.rectLeft ? 1 : -1;
        }
        return a.commentTop >= b.commentTop ? 1 : -1;
    }
    onSameLine(a, b) {
        return this.difference(a.commentTop, b.commentTop) === 0;
    }
    top(rectangle, height, rotate, zoom) {
        const actualHeight = height / zoom;
        switch (rotate) {
            case 90: return rectangle.x;
            case 180: return actualHeight - (rectangle.y + rectangle.height);
            case 270: return actualHeight - (rectangle.x + rectangle.width);
            default: return rectangle.y;
        }
    }
    height(element) {
        return HtmlTemplatesHelper.getAdjustedBoundingRect(element.form.nativeElement)?.height | 0;
    }
    difference(a, b) { return Math.abs(a - b); }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentSetRenderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentSetRenderService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentSetRenderService, decorators: [{
            type: Injectable
        }] });

class TagsServices {
    constructor(http) {
        this.http = http;
        this.snakeCase = string => {
            // transform string_to_snake_case
            return string.replace(/ +/g, ' ') // find space
                .split(/ |\B(?=[A-Z])/) // split it into array
                .map(word => word.toLowerCase()) // transform to lover case
                .join('_'); // trun array into sting using _
        };
    }
    getAllTags(createdBy) {
        const url = `/em-anno/tags/${createdBy}`;
        return this.http.get(url);
    }
    // @TODO: Move everything below this to NgRx store
    getNewTags(annoid) {
        return this.tagItems ? this.tagItems[annoid] : [];
    }
    updateTagItems(items, annoId) {
        const snakeCased = items.map(item => {
            return {
                ...item,
                name: this.snakeCase(item.name)
            };
        });
        this.tagItems = {
            ...this.tagItems,
            [annoId]: snakeCased
        };
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TagsServices, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TagsServices }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TagsServices, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$1.HttpClient }] });

class TextHighlightDirective {
    constructor(element) {
        this.element = element;
    }
    ngAfterViewChecked() {
        if (this.textToHighlight) {
            this.highlightInputText(this.textToHighlight);
        }
    }
    highlightInputText(textToHighlight) {
        this.resetHighlight();
        this.textToHighlight = textToHighlight;
        const searchPattern = new RegExp(textToHighlight, 'gi');
        const hostElement = this.element.nativeElement;
        if (hostElement.innerHTML.match(searchPattern)) {
            hostElement.innerHTML = hostElement.innerHTML
                .replace(searchPattern, this.highlightPattern('$&'));
        }
        this.textToHighlight = undefined;
    }
    resetHighlight() {
        const hostElement = this.element.nativeElement;
        const searchPattern = new RegExp(this.highlightPattern('(.*?)'), 'gi');
        while (hostElement.innerHTML.match(searchPattern)) {
            const matchGroups = searchPattern.exec(hostElement.innerHTML);
            if (matchGroups) {
                hostElement.innerHTML = hostElement.innerHTML.replace(matchGroups[0], matchGroups[1]);
            }
        }
    }
    highlightPattern(dynamicText) {
        return '<span class="mvTextHighlight">' + dynamicText + '</span>';
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TextHighlightDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
    /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: TextHighlightDirective, selector: "[mvTextHighlight]", inputs: { textToHighlight: "textToHighlight" }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TextHighlightDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[mvTextHighlight]'
                }]
        }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { textToHighlight: [{
                type: Input
            }] } });

class TextareaAutoExpandDirective {
    constructor(el) {
        this.el = el;
    }
    ngAfterContentChecked() {
        this.adjustHeight();
    }
    onMouseDown() {
        this.adjustHeight();
    }
    adjustHeight() {
        const nativeElement = this.el.nativeElement;
        nativeElement.style.overflow = 'hidden';
        nativeElement.style.height = 'auto';
        nativeElement.style.height = nativeElement.scrollHeight - 5 + 'px';
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TextareaAutoExpandDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
    /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: TextareaAutoExpandDirective, selector: "[mvTextAreaAutoExpand]", host: { listeners: { "input": "onMouseDown()" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TextareaAutoExpandDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[mvTextAreaAutoExpand]'
                }]
        }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { onMouseDown: [{
                type: HostListener,
                args: ['input']
            }] } });

class TagsComponent {
    constructor(tagsServices) {
        this.tagsServices = tagsServices;
        this.validators = [this.minLength, this.maxLength20];
        this.errorMessages = {
            'minLength': 'Minimum of 2 characters',
            'maxLength20': 'Maximum of 20 characters'
        };
        this.requestAutocompleteItems = (text) => {
            return this.tagsServices.getAllTags(this.userId);
        };
    }
    onUpdateTags(value) {
        this.tagsServices.updateTagItems(value, this.annoId);
    }
    minLength(control) {
        if (control.value.length < 2) {
            return {
                'minLength': true
            };
        }
        return null;
    }
    maxLength20(control) {
        if (control.value.length >= 20) {
            return {
                'maxLength20': true
            };
        }
        return null;
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TagsComponent, deps: [{ token: TagsServices }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: TagsComponent, selector: "mv-tags", inputs: { tagItems: "tagItems", userId: "userId", editable: "editable", annoId: "annoId" }, ngImport: i0, template: "<div class=\"tags\">\n  <tag-input\n    *ngIf=\"editable\" class=\"tags__edit\"\n    [maxItems]=\"10\"\n    [ngModel]=\"tagItems\"\n    (ngModelChange)=\"tagItems = $event; onUpdateTags($event)\"\n    [ngModelOptions]=\"{standalone:true}\"\n    [placeholder]=\"'Add tag'\"\n    [displayBy]=\"'label'\"\n    [identifyBy]=\"'name'\"\n    [onTextChangeDebounce]=\"250\"\n    [secondaryPlaceholder]=\"'Search or add tags'\"\n    [validators]=\"validators\"\n    [errorMessages]=\"errorMessages\"\n    [onlyFromAutocomplete]=\"false\">\n    <tag-input-dropdown\n      [autocompleteObservable]=\"requestAutocompleteItems\"\n      [displayBy]=\"'label'\"\n      [identifyBy]=\"'name'\"\n      [zIndex]=\"10000\"\n      [minimumTextLength]=\"2\">\n      <ng-template let-item=\"item\" let-index=\"index\">\n        {{ item.label }}\n      </ng-template>\n    </tag-input-dropdown>\n  </tag-input>\n\n  <div class=\"tags__renderer\" *ngIf=\"!editable && (tagItems && tagItems.length)\">\n    <span *ngFor=\"let tag of tagItems\" class=\"tags__item hmcts-badge\">\n      {{tag.label}}\n    </span>\n  </div>\n</div>\n\n", dependencies: [{ kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.TagInputComponent, selector: "tag-input", inputs: ["separatorKeys", "separatorKeyCodes", "placeholder", "secondaryPlaceholder", "maxItems", "validators", "asyncValidators", "onlyFromAutocomplete", "errorMessages", "theme", "onTextChangeDebounce", "inputId", "inputClass", "clearOnBlur", "hideForm", "addOnBlur", "addOnPaste", "pasteSplitPattern", "blinkIfDupe", "removable", "editable", "allowDupes", "modelAsStrings", "trimTags", "inputText", "ripple", "tabindex", "disable", "dragZone", "onRemoving", "onAdding", "animationDuration"], outputs: ["onAdd", "onRemove", "onSelect", "onFocus", "onBlur", "onTextChange", "onPaste", "onValidationError", "onTagEdited", "inputTextChange"] }, { kind: "component", type: i4.TagInputDropdown, selector: "tag-input-dropdown", inputs: ["offset", "focusFirstElement", "showDropdownIfEmpty", "autocompleteObservable", "minimumTextLength", "limitItemsTo", "displayBy", "identifyBy", "matchingFn", "appendToBody", "keepOpen", "dynamicUpdate", "zIndex", "autocompleteItems"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TagsComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-tags', encapsulation: ViewEncapsulation.None, template: "<div class=\"tags\">\n  <tag-input\n    *ngIf=\"editable\" class=\"tags__edit\"\n    [maxItems]=\"10\"\n    [ngModel]=\"tagItems\"\n    (ngModelChange)=\"tagItems = $event; onUpdateTags($event)\"\n    [ngModelOptions]=\"{standalone:true}\"\n    [placeholder]=\"'Add tag'\"\n    [displayBy]=\"'label'\"\n    [identifyBy]=\"'name'\"\n    [onTextChangeDebounce]=\"250\"\n    [secondaryPlaceholder]=\"'Search or add tags'\"\n    [validators]=\"validators\"\n    [errorMessages]=\"errorMessages\"\n    [onlyFromAutocomplete]=\"false\">\n    <tag-input-dropdown\n      [autocompleteObservable]=\"requestAutocompleteItems\"\n      [displayBy]=\"'label'\"\n      [identifyBy]=\"'name'\"\n      [zIndex]=\"10000\"\n      [minimumTextLength]=\"2\">\n      <ng-template let-item=\"item\" let-index=\"index\">\n        {{ item.label }}\n      </ng-template>\n    </tag-input-dropdown>\n  </tag-input>\n\n  <div class=\"tags__renderer\" *ngIf=\"!editable && (tagItems && tagItems.length)\">\n    <span *ngFor=\"let tag of tagItems\" class=\"tags__item hmcts-badge\">\n      {{tag.label}}\n    </span>\n  </div>\n</div>\n\n" }]
        }], ctorParameters: () => [{ type: TagsServices }], propDecorators: { tagItems: [{
                type: Input
            }], userId: [{
                type: Input
            }], editable: [{
                type: Input
            }], annoId: [{
                type: Input
            }] } });

/**
 * A moment timezone pipe to support parsing based on time zone abbreviations
 * covers all cases of offset variation due to daylight saving.
 *
 * Same API as DatePipe with additional timezone abbreviation support
 * Official date pipe dropped support for abbreviations names from Angular V5
 */
class MomentDatePipe extends DatePipe {
    transform(value, format = 'mediumDate', timezone = 'Europe/London') {
        const timezoneOffset = moment(value).tz(timezone).format('Z');
        return super.transform(value, format, timezoneOffset);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MomentDatePipe, deps: null, target: i0.ɵɵFactoryTarget.Pipe }); }
    /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: MomentDatePipe, name: "momentDate" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MomentDatePipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'momentDate'
                }]
        }] });

class CommentComponent {
    constructor(store, commentService, tagsServices) {
        this.store = store;
        this.commentService = commentService;
        this.tagsServices = tagsServices;
        this.CHAR_LIMIT = 5000;
        this.totalPrevPagesHeight = 0;
        this.hasUnsavedChanges = false;
        this.commentClick = new EventEmitter();
        this.renderComments = new EventEmitter();
        this.delete = new EventEmitter();
        this.updated = new EventEmitter();
        this.changes = new EventEmitter();
        this.rotate = 0;
        this.zoom = 1;
    }
    ngOnInit() {
        this.subscriptions = this.store.select(getComponentSearchText)
            .pipe(distinctUntilChanged()).subscribe(searchString => this.searchString = searchString);
        this.reRenderComments();
        this.marginToComment$ = this.commentService.marginToCommentEmitter.asObservable();
    }
    ngAfterContentInit() {
        if (this.tagItems && this.tagItems.length) {
            this.tagsServices.updateTagItems(this.tagItems, this._comment.annotationId);
        }
    }
    ngOnDestroy() {
        this.subscriptions.unsubscribe();
    }
    set comment(comment) {
        this._comment = { ...comment };
        this.page = this._comment.page;
        this.lastUpdate = comment.lastModifiedDate ? comment.lastModifiedDate : comment.createdDate;
        this.author = comment.createdByDetails;
        this.createdBy = comment.createdBy;
        this.editor = comment.lastModifiedByDetails;
        this.originalComment = comment.content;
        this.fullComment = this.originalComment;
        this.selected = this._comment.selected;
        this._editable = this._comment.editable;
        this.tagItems = this._comment.tags;
        const pageMarginBottom = 10;
        this.totalPrevPagesHeight = 0;
        for (let i = 0; i < this.page - 1; i++) {
            const height = this._comment.pages[i + 1] ? this._comment.pages[i + 1].styles.height : undefined;
            if (height) {
                this.totalPrevPagesHeight += height + pageMarginBottom;
            }
        }
    }
    get comment() {
        return this._comment;
    }
    set annotation(annotation) {
        this._rectangle = annotation.rectangles
            .reduce((prev, current) => prev.y < current.y ? prev : current);
        const actualHeight = this._comment.pages[this.page].styles.height / this.zoom;
        switch (this.rotate) {
            case 90:
                this.rectTop = this._rectangle.x;
                break;
            case 180:
                this.rectTop = actualHeight - (this._rectangle.y + this._rectangle.height);
                break;
            case 270:
                this.rectTop = actualHeight - (this._rectangle.x + this._rectangle.width);
                break;
            default: this.rectTop = this._rectangle.y;
        }
        this.rectLeft = this._rectangle.x;
    }
    get editable() {
        return this._editable;
    }
    onCommentChange(updatedComment) {
        this.hasUnsavedChanges =
            this.originalComment.substring(0, this.CHAR_LIMIT) !== updatedComment.substring(0, this.CHAR_LIMIT);
        this.commentService.onCommentChange(this.hasUnsavedChanges);
    }
    deleteOrCancel() {
        if (!this.editable) {
            this.delete.emit(this._comment);
        }
        else {
            this.hasUnsavedChanges = false;
            this._editable = false;
            this.fullComment = this.originalComment;
            this.changes.emit(false);
            if (!this.author && !this.fullComment) {
                this.delete.emit(this._comment);
            }
        }
    }
    editOrSave() {
        if (!this.editable) {
            this._editable = true;
        }
        else {
            this._comment.content = this.fullComment.substring(0, this.CHAR_LIMIT);
            const tags = this.tagsServices.getNewTags(this._comment.annotationId);
            const payload = {
                comment: this._comment,
                tags
            };
            this.updated.emit(payload);
            this.hasUnsavedChanges = false;
            this._editable = false;
            this.changes.emit(false);
        }
    }
    onCommentClick() {
        if (!this.selected) {
            this.selected = true;
            this._editable = false;
            this.commentClick.emit({ annotationId: this._comment.annotationId, editable: this._editable, selected: true });
        }
    }
    reRenderComments() {
        this.renderComments.emit(this._comment);
    }
    get commentTop() {
        return this.totalPrevPagesHeight + (this.rectTop * this.zoom);
    }
    get height() {
        return HtmlTemplatesHelper.getAdjustedBoundingRect(this.form.nativeElement).height / this.zoom;
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentComponent, deps: [{ token: i1.Store }, { token: CommentService }, { token: TagsServices }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CommentComponent, selector: "mv-anno-comment", inputs: { rotate: "rotate", zoom: "zoom", index: "index", page: "page", comment: "comment", annotation: "annotation" }, outputs: { commentClick: "commentClick", renderComments: "renderComments", delete: "delete", updated: "updated", changes: "changes" }, viewQueries: [{ propertyName: "form", first: true, predicate: ["form"], descendants: true }, { propertyName: "editableComment", first: true, predicate: ["editableComment"], descendants: true }], ngImport: i0, template: "<div\n  #form\n  (click)=\"onCommentClick()\"\n  class=\"aui-comment\"\n  [ngClass]=\"{ stylestoggle: (marginToComment$ | async) }\"\n  [style.top.px]=\"commentTop\"\n  [style.zIndex]=\"selected ? 100 : 0\"\n>\n  <div id=\"detailsWrapper {{ index }}\" class=\"aui-comment__header\">\n    <span *ngIf=\"author && !editor\" class=\"aui-comment__author\">\n      {{ author.forename }} {{ author.surname }}\n    </span>\n    <span *ngIf=\"editor\" class=\"aui-comment__author\">\n      {{ editor.forename }} {{ editor.surname }}\n    </span>\n    <time [hidden]=\"!selected && !this.editable\" class=\"aui-comment__meta\">\n      {{ lastUpdate | momentDate : \"d MMMM y h:mm a\" }}\n    </time>\n  </div>\n  <mv-tags\n    [tagItems]=\"tagItems\"\n    [userId]=\"createdBy\"\n    [editable]=\"editable\"\n    [annoId]=\"_comment.annotationId\"\n  >\n  </mv-tags>\n  <textarea\n    *ngIf=\"selected && editable\"\n    #editableComment\n    mvTextAreaAutoExpand\n    type=\"text\"\n    required\n    name=\"content\"\n    [maxlength]=\"CHAR_LIMIT\"\n    class=\"aui-comment__content form-control mimic-focus edit-mode expanded\"\n    [ngModel]=\"fullComment\"\n    (ngModelChange)=\"fullComment = $event; reRenderComments(); onCommentChange($event)\"\n    aria-label=\"comment\"\n  >\n  </textarea>\n  <p\n    *ngIf=\"!editable\"\n    mvTextHighlight\n    class=\"commentText\"\n    [textToHighlight]=\"searchString\"\n  >\n    {{ fullComment }}\n  </p>\n  <div\n    *ngIf=\"\n      selected ||\n      this.editable ||\n      (!fullComment.length && tagItems && !tagItems.length)\n    \"\n    class=\"aui-comment__footer commentBtns\"\n  >\n    <button\n      class=\"govuk-button\"\n      type=\"button\"\n      role=\"button\"\n      (click)=\"editOrSave()\"\n    >\n      {{ !editable ? (\"Edit\" | rpxTranslate) : (\"Save\" | rpxTranslate) }}\n    </button>\n    <button\n      type=\"button\"\n      role=\"button\"\n      class=\"govuk-button govuk-button--secondary\"\n      (click)=\"deleteOrCancel()\"\n    >\n      {{ !editable ? (\"Delete\" | rpxTranslate) : (\"Cancel\" | rpxTranslate) }}\n    </button>\n  </div>\n  <span class=\"aui-comment__private\">{{ \"private\" | rpxTranslate }}</span>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: TextHighlightDirective, selector: "[mvTextHighlight]", inputs: ["textToHighlight"] }, { kind: "directive", type: TextareaAutoExpandDirective, selector: "[mvTextAreaAutoExpand]" }, { kind: "component", type: TagsComponent, selector: "mv-tags", inputs: ["tagItems", "userId", "editable", "annoId"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5$1.RpxTranslatePipe, name: "rpxTranslate" }, { kind: "pipe", type: MomentDatePipe, name: "momentDate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-anno-comment', template: "<div\n  #form\n  (click)=\"onCommentClick()\"\n  class=\"aui-comment\"\n  [ngClass]=\"{ stylestoggle: (marginToComment$ | async) }\"\n  [style.top.px]=\"commentTop\"\n  [style.zIndex]=\"selected ? 100 : 0\"\n>\n  <div id=\"detailsWrapper {{ index }}\" class=\"aui-comment__header\">\n    <span *ngIf=\"author && !editor\" class=\"aui-comment__author\">\n      {{ author.forename }} {{ author.surname }}\n    </span>\n    <span *ngIf=\"editor\" class=\"aui-comment__author\">\n      {{ editor.forename }} {{ editor.surname }}\n    </span>\n    <time [hidden]=\"!selected && !this.editable\" class=\"aui-comment__meta\">\n      {{ lastUpdate | momentDate : \"d MMMM y h:mm a\" }}\n    </time>\n  </div>\n  <mv-tags\n    [tagItems]=\"tagItems\"\n    [userId]=\"createdBy\"\n    [editable]=\"editable\"\n    [annoId]=\"_comment.annotationId\"\n  >\n  </mv-tags>\n  <textarea\n    *ngIf=\"selected && editable\"\n    #editableComment\n    mvTextAreaAutoExpand\n    type=\"text\"\n    required\n    name=\"content\"\n    [maxlength]=\"CHAR_LIMIT\"\n    class=\"aui-comment__content form-control mimic-focus edit-mode expanded\"\n    [ngModel]=\"fullComment\"\n    (ngModelChange)=\"fullComment = $event; reRenderComments(); onCommentChange($event)\"\n    aria-label=\"comment\"\n  >\n  </textarea>\n  <p\n    *ngIf=\"!editable\"\n    mvTextHighlight\n    class=\"commentText\"\n    [textToHighlight]=\"searchString\"\n  >\n    {{ fullComment }}\n  </p>\n  <div\n    *ngIf=\"\n      selected ||\n      this.editable ||\n      (!fullComment.length && tagItems && !tagItems.length)\n    \"\n    class=\"aui-comment__footer commentBtns\"\n  >\n    <button\n      class=\"govuk-button\"\n      type=\"button\"\n      role=\"button\"\n      (click)=\"editOrSave()\"\n    >\n      {{ !editable ? (\"Edit\" | rpxTranslate) : (\"Save\" | rpxTranslate) }}\n    </button>\n    <button\n      type=\"button\"\n      role=\"button\"\n      class=\"govuk-button govuk-button--secondary\"\n      (click)=\"deleteOrCancel()\"\n    >\n      {{ !editable ? (\"Delete\" | rpxTranslate) : (\"Cancel\" | rpxTranslate) }}\n    </button>\n  </div>\n  <span class=\"aui-comment__private\">{{ \"private\" | rpxTranslate }}</span>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: CommentService }, { type: TagsServices }], propDecorators: { commentClick: [{
                type: Output
            }], renderComments: [{
                type: Output
            }], delete: [{
                type: Output
            }], updated: [{
                type: Output
            }], changes: [{
                type: Output
            }], rotate: [{
                type: Input
            }], zoom: [{
                type: Input
            }], index: [{
                type: Input
            }], page: [{
                type: Input
            }], form: [{
                type: ViewChild,
                args: ['form', { static: false }]
            }], editableComment: [{
                type: ViewChild,
                args: ['editableComment', { static: false }]
            }], comment: [{
                type: Input
            }], annotation: [{
                type: Input
            }] } });

class CommentSetComponent {
    constructor(store, commentService, renderService, toolbarEvents) {
        this.store = store;
        this.commentService = commentService;
        this.renderService = renderService;
        this.toolbarEvents = toolbarEvents;
        this.pageHeights = [];
        this.subscriptions = [];
        this.clearSelection();
    }
    ngOnInit() {
        this.comments$ = this.store.pipe(select(getCommentsArray));
        this.annoEntities$ = this.store.pipe(select(getAnnotationEntities));
        this.subscriptions.push(this.toolbarEvents.commentsPanelVisible.subscribe(toggle => {
            this.redrawComments();
            this.showCommentsPanel = toggle;
        }));
        this.subscriptions.push(this.toolbarEvents.rotateSubject.subscribe(rotate => this.rotateDocument()));
    }
    ngOnChanges(changes) {
        if (changes.annotationSet) {
            this.commentService.setCommentSet(this);
        }
        if (changes.contentScrollTop) {
            if (this.container) {
                this.container.nativeElement.scrollTo(0, this.contentScrollTop);
            }
        }
    }
    ngOnDestroy() {
        if (this.subscriptions.length > 0) {
            this.subscriptions.forEach(subscription => subscription.unsubscribe());
        }
    }
    onSelect(annotationId) {
        this.store.dispatch(new SelectedAnnotation(annotationId));
    }
    onCommentDelete(comment) {
        const annotation = this.annotationSet.annotations.find(anno => anno.id === comment.annotationId);
        const comments = [];
        const annot = {
            ...annotation,
            comments
        };
        this.onAnnotationUpdate(annot);
        this.redrawComments();
    }
    redrawComments() {
        setTimeout(() => {
            const componentList = this.commentComponents.map(comment => comment);
            this.renderService.redrawComponents(componentList, this.pageHeights, this.rotate, this.zoom);
        }, 0);
    }
    rotateDocument() {
        if (this.panel) {
            this.panel.nativeElement.style.height = '0';
        }
    }
    onCommentUpdate(payload) {
        const annotation = this.annotationSet.annotations.find(anno => anno.id === payload.comment.annotationId);
        const comments = [payload.comment];
        const tags = payload.tags;
        const annot = {
            ...annotation,
            comments,
            tags
        };
        this.onAnnotationUpdate(annot);
    }
    onAnnotationUpdate(annotation) {
        this.store.dispatch(new SaveAnnotation(annotation));
    }
    onContainerClick(e) {
        if (e.path && e.path[0] === this.panel.nativeElement) {
            this.clearSelection();
        }
    }
    clearSelection() {
        this.store.dispatch(new SelectedAnnotation({ annotationId: '', editable: false, selected: false }));
    }
    allCommentsSaved() {
        this.commentService.allCommentsSaved();
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentSetComponent, deps: [{ token: i1.Store }, { token: CommentService }, { token: CommentSetRenderService }, { token: ToolbarEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CommentSetComponent, selector: "mv-comment-set", inputs: { annotationSet: "annotationSet", zoom: "zoom", rotate: "rotate", height: "height", pageHeights: "pageHeights", contentScrollTop: "contentScrollTop" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }, { propertyName: "panel", first: true, predicate: ["panel"], descendants: true }, { propertyName: "commentComponents", predicate: ["commentComponent"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div #container [ngClass]=\"{'comments': showCommentsPanel}\">\n  <div #panel [ngClass]=\"{ 'comments-panel comment-container': true, 'expanded': showCommentsPanel }\"\n     [style.height.px]=\"height\"\n     (click)=\"onContainerClick($event)\">\n    <ng-container *ngFor=\"let comment of (comments$ | async); let i = index;\">\n      <mv-anno-comment\n        [ngStyle]=\"showCommentsPanel ? {} : {'display':'none'}\"\n        #commentComponent\n        (commentClick)=\"onSelect($event)\"\n        (delete)=\"onCommentDelete($event)\"\n        (updated)=\"onCommentUpdate($event)\"\n        (changes)=\"allCommentsSaved()\"\n        [zoom]=\"zoom\"\n        [rotate]=\"rotate\"\n        [index]=\"i\"\n        [page]=\"comment.page\"\n        [comment]=\"comment\"\n        [annotation]=\"(annoEntities$ | async)[comment.annotationId]\"\n        (renderComments)=\"redrawComments()\">\n      </mv-anno-comment>\n    </ng-container>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: CommentComponent, selector: "mv-anno-comment", inputs: ["rotate", "zoom", "index", "page", "comment", "annotation"], outputs: ["commentClick", "renderComments", "delete", "updated", "changes"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentSetComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-comment-set', template: "<div #container [ngClass]=\"{'comments': showCommentsPanel}\">\n  <div #panel [ngClass]=\"{ 'comments-panel comment-container': true, 'expanded': showCommentsPanel }\"\n     [style.height.px]=\"height\"\n     (click)=\"onContainerClick($event)\">\n    <ng-container *ngFor=\"let comment of (comments$ | async); let i = index;\">\n      <mv-anno-comment\n        [ngStyle]=\"showCommentsPanel ? {} : {'display':'none'}\"\n        #commentComponent\n        (commentClick)=\"onSelect($event)\"\n        (delete)=\"onCommentDelete($event)\"\n        (updated)=\"onCommentUpdate($event)\"\n        (changes)=\"allCommentsSaved()\"\n        [zoom]=\"zoom\"\n        [rotate]=\"rotate\"\n        [index]=\"i\"\n        [page]=\"comment.page\"\n        [comment]=\"comment\"\n        [annotation]=\"(annoEntities$ | async)[comment.annotationId]\"\n        (renderComments)=\"redrawComments()\">\n      </mv-anno-comment>\n    </ng-container>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: CommentService }, { type: CommentSetRenderService }, { type: ToolbarEventService }], propDecorators: { annotationSet: [{
                type: Input
            }], zoom: [{
                type: Input
            }], rotate: [{
                type: Input
            }], height: [{
                type: Input
            }], pageHeights: [{
                type: Input
            }], contentScrollTop: [{
                type: Input
            }], container: [{
                type: ViewChild,
                args: ['container', { static: false }]
            }], panel: [{
                type: ViewChild,
                args: ['panel', { static: false }]
            }], commentComponents: [{
                type: ViewChildren,
                args: ['commentComponent']
            }] } });

class CommentsNavigateComponent {
    constructor(store, toolbarEvents) {
        this.store = store;
        this.toolbarEvents = toolbarEvents;
        this.autoSelect = false;
        this.navigationList = [];
        this.index = 0;
    }
    ngOnChanges(changes) {
        if (changes.annotationList) {
            this.initNavigationList();
        }
    }
    initNavigationList() {
        this.index = 0;
        this.navigationList = [...this.annotationList || []]
            .map(annotation => ({
            content: annotation.comments[0].content,
            annotationId: annotation.id,
            page: annotation.page,
            rectangle: this.upperRectangle(annotation.rectangles),
        }))
            .sort(this.sortComments);
        if (this.autoSelect) {
            this.toolbarEvents.setPage(Number.parseInt(this.navigationList[0].page, 0));
            this.store.dispatch(new SelectedAnnotation({
                annotationId: this.navigationList[0].annotationId,
                editable: false,
                selected: true
            }));
        }
    }
    sortComments(mappedCommentA, mappedCommentB) {
        if (mappedCommentA.page !== mappedCommentB.page) {
            return mappedCommentA.page - mappedCommentB.page;
        }
        else {
            const rectA = mappedCommentA.rectangle;
            const rectB = mappedCommentB.rectangle;
            if (rectA.y !== rectB.y) {
                return rectA.y - rectB.y;
            }
            else {
                return rectA.x - rectB.x;
            }
        }
    }
    nextItem() {
        this.index += 1;
        if (this.index === this.annotationList.length) {
            this.index = 0;
        }
        this.toolbarEvents.setPage(Number.parseInt(this.navigationList[this.index].page, 0));
        this.store.dispatch(new SelectedAnnotation({
            annotationId: this.navigationList[this.index].annotationId, editable: false, selected: true
        }));
    }
    prevItem() {
        this.index -= 1;
        if (this.index < 0) {
            this.index = this.navigationList.length - 1;
        }
        this.toolbarEvents.setPage(Number.parseInt(this.navigationList[this.index].page, 0));
        this.store.dispatch(new SelectedAnnotation({
            annotationId: this.navigationList[this.index].annotationId,
            editable: false,
            selected: true
        }));
    }
    upperRectangle(rectangles) {
        [...rectangles].sort((rect1, rect2) => rect1.y - rect2.y);
        return { x: rectangles[0].x, y: rectangles[0].y };
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentsNavigateComponent, deps: [{ token: i1.Store }, { token: ToolbarEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CommentsNavigateComponent, selector: "mv-comments-navigate", inputs: { annotationList: "annotationList", autoSelect: "autoSelect" }, usesOnChanges: true, ngImport: i0, template: "<p class=\"comment-search\">\n  <span class=\"comment-search__item\">\n    Showing {{ index + 1 }} of {{ navigationList.length }}\n  </span>\n  <a [routerLink]=\"[]\"\n     class=\"comment-search__item\"\n     title=\"Previous comment\"\n     (click)=\"prevItem()\">Prev</a>\n  <a [routerLink]=\"[]\"\n     class=\"comment-search__item\"\n     title=\"Next comment'\"\n     (click)=\"nextItem()\">Next</a>\n</p>\n", dependencies: [{ kind: "directive", type: i3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentsNavigateComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-comments-navigate', encapsulation: ViewEncapsulation.None, template: "<p class=\"comment-search\">\n  <span class=\"comment-search__item\">\n    Showing {{ index + 1 }} of {{ navigationList.length }}\n  </span>\n  <a [routerLink]=\"[]\"\n     class=\"comment-search__item\"\n     title=\"Previous comment\"\n     (click)=\"prevItem()\">Prev</a>\n  <a [routerLink]=\"[]\"\n     class=\"comment-search__item\"\n     title=\"Next comment'\"\n     (click)=\"nextItem()\">Next</a>\n</p>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: ToolbarEventService }], propDecorators: { annotationList: [{
                type: Input
            }], autoSelect: [{
                type: Input
            }] } });

class CommentSearchComponent {
    constructor(store) {
        this.store = store;
        this.searchResults = [];
        this.searchIndex = 0;
    }
    ngAfterViewInit() {
        if (this.searchInput) {
            this.searchInput.nativeElement.focus();
        }
    }
    ngOnDestroy() {
        // TODO workaround for tab error
        setTimeout(() => { this.store.dispatch(new SearchComment('')); }, 250);
    }
    searchComments(searchText) {
        this.clearSearch();
        if (searchText.length > 2) {
            this.searchString = searchText;
            this.searchResults = this.annotations
                .filter(annotation => annotation.comments.length > 0)
                .filter(annotation => annotation.comments[0].content.toLowerCase().includes(this.searchString.toLowerCase()));
            if (this.searchResults.length > 0) {
                this.store.dispatch(new SearchComment(searchText));
            }
        }
    }
    clearSearch() {
        this.searchString = undefined;
        this.searchResults = [];
        this.searchIndex = 0;
        this.store.dispatch(new SearchComment(''));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentSearchComponent, deps: [{ token: i1.Store }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CommentSearchComponent, selector: "mv-comment-search", inputs: { annotations: "annotations" }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }], ngImport: i0, template: "<input\n  #searchInput\n  type=\"text\"\n  class=\"govuk-input comment-search__item\"\n  id=\"search-comments-input\"\n  name=\"searchString\"\n  aria-label=\"search comments input\"\n  [ngModel]=\"searchString\"\n  (ngModelChange)=\"searchString = $event\"\n/>\n<button\n  type=\"button\"\n  [class.govuk-button--disabled]=\"searchInput?.value.length <= 2\"\n  class=\"govuk-button comment-search__item\"\n  (click)=\"searchComments(searchInput.value.trim())\"\n>\n  {{ \"Search\" | rpxTranslate }}\n</button>\n<ng-container *ngIf=\"searchResults.length > 0\">\n  <mv-comments-navigate [annotationList]=\"searchResults\"></mv-comments-navigate>\n</ng-container>\n<ng-container *ngIf=\"searchString && searchResults?.length === 0\">\n  <p class=\"comment-search__item\">\n    {{ \"No matches have been found\" | rpxTranslate }}\n  </p>\n</ng-container>\n", dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: CommentsNavigateComponent, selector: "mv-comments-navigate", inputs: ["annotationList", "autoSelect"] }, { kind: "pipe", type: i5$1.RpxTranslatePipe, name: "rpxTranslate" }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentSearchComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-comment-search', encapsulation: ViewEncapsulation.None, template: "<input\n  #searchInput\n  type=\"text\"\n  class=\"govuk-input comment-search__item\"\n  id=\"search-comments-input\"\n  name=\"searchString\"\n  aria-label=\"search comments input\"\n  [ngModel]=\"searchString\"\n  (ngModelChange)=\"searchString = $event\"\n/>\n<button\n  type=\"button\"\n  [class.govuk-button--disabled]=\"searchInput?.value.length <= 2\"\n  class=\"govuk-button comment-search__item\"\n  (click)=\"searchComments(searchInput.value.trim())\"\n>\n  {{ \"Search\" | rpxTranslate }}\n</button>\n<ng-container *ngIf=\"searchResults.length > 0\">\n  <mv-comments-navigate [annotationList]=\"searchResults\"></mv-comments-navigate>\n</ng-container>\n<ng-container *ngIf=\"searchString && searchResults?.length === 0\">\n  <p class=\"comment-search__item\">\n    {{ \"No matches have been found\" | rpxTranslate }}\n  </p>\n</ng-container>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }], propDecorators: { annotations: [{
                type: Input
            }], searchInput: [{
                type: ViewChild,
                args: ['searchInput', { static: false }]
            }] } });

class FilterPipe {
    transform(items, searchText, fieldName) {
        if (!items) {
            return [];
        }
        if (!searchText) {
            return items;
        }
        return items.filter(item => {
            if (item) {
                if (item[fieldName]) {
                    return item[fieldName].toLowerCase().includes(searchText.toLowerCase());
                }
                else {
                    return item.toLowerCase().includes(searchText.toLowerCase());
                }
            }
            return false;
        });
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FilterPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
    /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: FilterPipe, name: "filter" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FilterPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'filter'
                }]
        }] });

class UnsnakePipe {
    transform(items) {
        return items.split('_').join(' ');
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UnsnakePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
    /** @nocollapse */ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: UnsnakePipe, name: "unsnake" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UnsnakePipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'unsnake'
                }]
        }] });

class CommentFilterComponent {
    constructor(store, fb) {
        this.store = store;
        this.fb = fb;
        this.isPreview = false;
    }
    ngOnInit() {
        this.tagGroup = this.fb.group({
            'tagFilters': this.fb.group({}),
        });
        this.filter$ = this.store.pipe(select(getTagFilters));
        this.$subscriptions = this.tagGroup.valueChanges.pipe(auditTime(5)).subscribe(value => {
            const tagFilters = value['tagFilters'];
            this.store.dispatch(new AddFilterTags(tagFilters));
        });
        this.buildFrom();
    }
    buildFrom() {
        const checkboxes = this.tagGroup.get('tagFilters');
        this.allTags$ = this.store.pipe(select(getAllTagsArr)).pipe(tap(tags => {
            this.tagGroup.reset();
            tags.forEach((value) => {
                checkboxes.addControl(value.key, new UntypedFormControl(false));
            });
        }));
    }
    onClearFilters() {
        this.tagGroup.reset();
        this.store.dispatch(new ClearFilterTags());
    }
    ngOnDestroy() {
        this.$subscriptions.unsubscribe();
    }
    onRemoveFilter(tagName) {
        const checkboxes = this.tagGroup.get('tagFilters');
        checkboxes.controls[tagName].setValue(false);
    }
    onToggleFilterView() {
        this.isPreview = !this.isPreview;
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentFilterComponent, deps: [{ token: i1.Store }, { token: i2.UntypedFormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CommentFilterComponent, selector: "mv-comment-filter", ngImport: i0, template: "<div class=\"comment-filter\">\n  <div class=\"hmcts-filter__content\">\n    <div class=\"hmcts-filter__toggle-filters\">\n      <p\n        class=\"hmcts-filter__toggle-filters-link\"\n        [ngClass]=\"{ 'govuk-accordion__section--expanded': isPreview }\"\n        (click)=\"onToggleFilterView()\"\n      >\n        <strong>{{ \"Filter options\" | rpxTranslate }}</strong\n        ><span class=\"govuk-accordion__icon\"></span>\n      </p>\n    </div>\n\n    <ng-container *ngIf=\"filter$ | async as filters\">\n      <div class=\"hmcts-filter__selected-heading\" *ngIf=\"filters.length\">\n        <div class=\"hmcts-filter__heading-action\">\n          <p>\n            <a\n              (click)=\"onClearFilters()\"\n              class=\"govuk-link govuk-link--no-visited-state\"\n              [routerLink]=\"[]\"\n              >{{ \"Clear filters\" | rpxTranslate }}</a\n            >\n          </p>\n        </div>\n      </div>\n\n      <h4\n        class=\"govuk-heading-s govuk-!-margin-bottom-0\"\n        *ngIf=\"filters.length\"\n      >\n        {{ \"Tag filters\" | rpxTranslate }}\n      </h4>\n\n      <ul class=\"hmcts-filter-tags\" *ngIf=\"filters.length\">\n        <li *ngFor=\"let tagName of filters\">\n          <a\n            class=\"hmcts-filter__tag\"\n            [routerLink]=\"[]\"\n            (click)=\"onRemoveFilter(tagName)\"\n          >\n            <span class=\"govuk-visually-hidden\">{{\n              \"Remove this filter\" | rpxTranslate\n            }}</span\n            >{{ tagName | unsnake }}</a\n          >\n        </li>\n      </ul>\n    </ng-container>\n\n    <div class=\"hmcts-filter__options\" [ngClass]=\"{ isVisible: isPreview }\">\n      <div class=\"govuk-form-group\">\n        <label class=\"govuk-label govuk-label--s\" for=\"keywords\">\n          {{ \"Search Tags\" | rpxTranslate }}\n        </label>\n        <input\n          class=\"govuk-input\"\n          id=\"keywords\"\n          name=\"keywords\"\n          type=\"text\"\n          [ngModel]=\"searchValue\"\n          (ngModelChange)=\"searchValue = $event\"\n        />\n      </div>\n\n      <div class=\"govuk-form-group\">\n        <div [formGroup]=\"tagGroup\">\n          <fieldset class=\"govuk-fieldset\" formGroupName=\"tagFilters\">\n            <legend class=\"govuk-fieldset__legend govuk-fieldset__legend--s\">\n              Tags\n            </legend>\n            <div class=\"govuk-checkboxes--scroll\">\n              <div class=\"govuk-checkboxes govuk-checkboxes--small\">\n                <div\n                  class=\"govuk-checkboxes__item\"\n                  *ngFor=\"\n                    let item of allTags$ | async | filter : searchValue : 'key'\n                  \"\n                >\n                  <input\n                    [formControlName]=\"item.key\"\n                    [id]=\"item.key\"\n                    class=\"govuk-checkboxes__input\"\n                    [value]=\"false\"\n                    [attr.aria-describedby]=\"item.key\"\n                    type=\"checkbox\"\n                  />\n                  <label\n                    class=\"govuk-label govuk-checkboxes__label\"\n                    [for]=\"item.key\"\n                  >\n                    {{ item.key | unsnake }} ({{ item.length }})\n                  </label>\n                </div>\n              </div>\n            </div>\n          </fieldset>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5$1.RpxTranslatePipe, name: "rpxTranslate" }, { kind: "pipe", type: FilterPipe, name: "filter" }, { kind: "pipe", type: UnsnakePipe, name: "unsnake" }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentFilterComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-comment-filter', encapsulation: ViewEncapsulation.None, template: "<div class=\"comment-filter\">\n  <div class=\"hmcts-filter__content\">\n    <div class=\"hmcts-filter__toggle-filters\">\n      <p\n        class=\"hmcts-filter__toggle-filters-link\"\n        [ngClass]=\"{ 'govuk-accordion__section--expanded': isPreview }\"\n        (click)=\"onToggleFilterView()\"\n      >\n        <strong>{{ \"Filter options\" | rpxTranslate }}</strong\n        ><span class=\"govuk-accordion__icon\"></span>\n      </p>\n    </div>\n\n    <ng-container *ngIf=\"filter$ | async as filters\">\n      <div class=\"hmcts-filter__selected-heading\" *ngIf=\"filters.length\">\n        <div class=\"hmcts-filter__heading-action\">\n          <p>\n            <a\n              (click)=\"onClearFilters()\"\n              class=\"govuk-link govuk-link--no-visited-state\"\n              [routerLink]=\"[]\"\n              >{{ \"Clear filters\" | rpxTranslate }}</a\n            >\n          </p>\n        </div>\n      </div>\n\n      <h4\n        class=\"govuk-heading-s govuk-!-margin-bottom-0\"\n        *ngIf=\"filters.length\"\n      >\n        {{ \"Tag filters\" | rpxTranslate }}\n      </h4>\n\n      <ul class=\"hmcts-filter-tags\" *ngIf=\"filters.length\">\n        <li *ngFor=\"let tagName of filters\">\n          <a\n            class=\"hmcts-filter__tag\"\n            [routerLink]=\"[]\"\n            (click)=\"onRemoveFilter(tagName)\"\n          >\n            <span class=\"govuk-visually-hidden\">{{\n              \"Remove this filter\" | rpxTranslate\n            }}</span\n            >{{ tagName | unsnake }}</a\n          >\n        </li>\n      </ul>\n    </ng-container>\n\n    <div class=\"hmcts-filter__options\" [ngClass]=\"{ isVisible: isPreview }\">\n      <div class=\"govuk-form-group\">\n        <label class=\"govuk-label govuk-label--s\" for=\"keywords\">\n          {{ \"Search Tags\" | rpxTranslate }}\n        </label>\n        <input\n          class=\"govuk-input\"\n          id=\"keywords\"\n          name=\"keywords\"\n          type=\"text\"\n          [ngModel]=\"searchValue\"\n          (ngModelChange)=\"searchValue = $event\"\n        />\n      </div>\n\n      <div class=\"govuk-form-group\">\n        <div [formGroup]=\"tagGroup\">\n          <fieldset class=\"govuk-fieldset\" formGroupName=\"tagFilters\">\n            <legend class=\"govuk-fieldset__legend govuk-fieldset__legend--s\">\n              Tags\n            </legend>\n            <div class=\"govuk-checkboxes--scroll\">\n              <div class=\"govuk-checkboxes govuk-checkboxes--small\">\n                <div\n                  class=\"govuk-checkboxes__item\"\n                  *ngFor=\"\n                    let item of allTags$ | async | filter : searchValue : 'key'\n                  \"\n                >\n                  <input\n                    [formControlName]=\"item.key\"\n                    [id]=\"item.key\"\n                    class=\"govuk-checkboxes__input\"\n                    [value]=\"false\"\n                    [attr.aria-describedby]=\"item.key\"\n                    type=\"checkbox\"\n                  />\n                  <label\n                    class=\"govuk-label govuk-checkboxes__label\"\n                    [for]=\"item.key\"\n                  >\n                    {{ item.key | unsnake }} ({{ item.length }})\n                  </label>\n                </div>\n              </div>\n            </div>\n          </fieldset>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: i2.UntypedFormBuilder }] });

class CommentSetHeaderComponent {
    constructor(store, commentService, toolbarEvents, icpEventService) {
        this.store = store;
        this.commentService = commentService;
        this.toolbarEvents = toolbarEvents;
        this.icpEventService = icpEventService;
        this.showCommentSummaryDialog = new EventEmitter();
        this.tabs = [];
        this.tabSelected = '';
    }
    ngOnInit() {
        const tagFilter$ = this.store.pipe(select(getTagFilters));
        const filteredAnnotation$ = this.store.pipe(select(getFilteredAnnotations));
        this.$subscriptions = combineLatest([tagFilter$, filteredAnnotation$]).subscribe(([formData, filteredAnno]) => {
            this.navigationList = filteredAnno;
            this.tabs = this.navigationList.length > 0 ?
                [{ label: 'comments' }, { label: 'filter' }, { label: 'search' }] : [{ label: 'comments' }];
            this.isFiltered = !formData.length;
            this.tabs = [...this.tabs].map((tab) => {
                return !this.isFiltered && tab.label === 'filter' ? { ...tab, isFiltered: true } : { ...tab, isFiltered: false };
            });
        });
    }
    toggleCommentsSummary() {
        this.showCommentSummaryDialog.emit();
    }
    selectTab(tab) {
        this.tabSelected = tab !== this.tabSelected ? tab : undefined;
        if (this.tabSelected) {
            this.marginToComment = true;
            this.commentService.createMarginToCommentEvent(this.marginToComment);
        }
        else {
            this.marginToComment = false;
            this.commentService.createMarginToCommentEvent(this.marginToComment);
        }
    }
    toggleCommentsPanel() {
        this.toolbarEvents.toggleCommentsPanel(!this.toolbarEvents.commentsPanelVisible.getValue());
    }
    ngOnDestroy() {
        this.$subscriptions.unsubscribe();
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentSetHeaderComponent, deps: [{ token: i1.Store }, { token: CommentService }, { token: ToolbarEventService }, { token: IcpEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CommentSetHeaderComponent, selector: "mv-comment-set-header", inputs: { showCommentSummary: "showCommentSummary", isHidden: "isHidden" }, outputs: { showCommentSummaryDialog: "showCommentSummaryDialog" }, ngImport: i0, template: "<div class=\"govuk-tabs commentSummaryHeader\" [ngClass]=\"{'icp-mode': icpEventService.enabled | async}\" data-module=\"govuk-tabs\">\n  <ul class=\"govuk-tabs__list\">\n    <li *ngFor=\"let tab of tabs; let i = index\" class=\"govuk-tabs__list-item govuk-tabs__list-item\"\n        [ngClass]=\"{'govuk-tabs__list-item--selected': tabSelected === tab.label}\">\n      <a id=\"commentSubPane{{ i }}\" (click)=\"selectTab(tab.label)\" [routerLink]=\"[]\" [ngClass]=\"{'govuk-tabs__list-item--filtered': tab.isFiltered}\"\n         class=\"govuk-tabs__tab\" [hidden]=\"isHidden\">\n        {{ tab.label | titlecase }}\n      </a>\n    </li>\n    <li>\n      <button id=\"mvCloseBtn\" #mvCloseBtn class=\"mv-button commentSummaryHeader-button--close\"\n        title=\"Close Comments\" (click)=\"toggleCommentsPanel()\" [hidden]=\"isHidden\">\n      </button>\n    </li>\n  </ul>\n  <div class=\"govuk-tabs__panel\" [hidden]=\"!tabSelected\">\n    <ng-container *ngIf=\"tabSelected === 'comments'\">\n      <div style=\"width: 100%\">\n        <div class=\"hmcts-banner\" *ngIf=\"navigationList?.length === 0\">\n          <svg alt=\"\" class=\"hmcts-banner__icon\" fill=\"currentColor\" focusable=\"false\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 25 25\" height=\"25\" width=\"25\">\n            <path d=\"M13.7,18.5h-2.4v-2.4h2.4V18.5z M12.5,13.7c-0.7,0-1.2-0.5-1.2-1.2V7.7c0-0.7,0.5-1.2,1.2-1.2s1.2,0.5,1.2,1.2v4.8\nC13.7,13.2,13.2,13.7,12.5,13.7z M12.5,0.5c-6.6,0-12,5.4-12,12s5.4,12,12,12s12-5.4,12-12S19.1,0.5,12.5,0.5z\" /></svg>\n          <div class=\"hmcts-banner__message\">\n            <span class=\"hmcts-banner__assistive\">information</span>\n            Select text to add a comment or highlight.\n          </div>\n        </div>\n        <button type=\"button\" class=\"govuk-button\"\n                id=\"commentSummary\" tabindex=\"0\"\n                data-l10n-id=\"commentSummary\"\n                title=\"Open collate summary\"\n                (click)=\"toggleCommentsSummary()\">Collate comments</button>\n      </div>\n      <ng-container *ngIf=\"navigationList?.length > 0\">\n        <mv-comments-navigate\n          [annotationList]=\"navigationList\">\n        </mv-comments-navigate>\n      </ng-container>\n      <p class=\"aui-comment__private-text\">\n        <span class=\"aui-comment__private\">private</span>\n        All comments can only be seen by you\n      </p>\n    </ng-container>\n    <div [hidden]=\"tabSelected !== 'filter'\">\n      <div class=\"govuk-tabs__panel--container\">\n        <mv-comment-filter></mv-comment-filter>\n        <mv-comments-navigate\n          *ngIf=\"navigationList?.length > 0\"\n          [annotationList]=\"navigationList\">\n        </mv-comments-navigate>\n      </div>\n    </div>\n\n    <div [hidden]=\"tabSelected !== 'search'\">\n      <mv-comment-search [annotations]=\"navigationList\"></mv-comment-search>\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: CommentSearchComponent, selector: "mv-comment-search", inputs: ["annotations"] }, { kind: "component", type: CommentsNavigateComponent, selector: "mv-comments-navigate", inputs: ["annotationList", "autoSelect"] }, { kind: "component", type: CommentFilterComponent, selector: "mv-comment-filter" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.TitleCasePipe, name: "titlecase" }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentSetHeaderComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-comment-set-header', encapsulation: ViewEncapsulation.None, template: "<div class=\"govuk-tabs commentSummaryHeader\" [ngClass]=\"{'icp-mode': icpEventService.enabled | async}\" data-module=\"govuk-tabs\">\n  <ul class=\"govuk-tabs__list\">\n    <li *ngFor=\"let tab of tabs; let i = index\" class=\"govuk-tabs__list-item govuk-tabs__list-item\"\n        [ngClass]=\"{'govuk-tabs__list-item--selected': tabSelected === tab.label}\">\n      <a id=\"commentSubPane{{ i }}\" (click)=\"selectTab(tab.label)\" [routerLink]=\"[]\" [ngClass]=\"{'govuk-tabs__list-item--filtered': tab.isFiltered}\"\n         class=\"govuk-tabs__tab\" [hidden]=\"isHidden\">\n        {{ tab.label | titlecase }}\n      </a>\n    </li>\n    <li>\n      <button id=\"mvCloseBtn\" #mvCloseBtn class=\"mv-button commentSummaryHeader-button--close\"\n        title=\"Close Comments\" (click)=\"toggleCommentsPanel()\" [hidden]=\"isHidden\">\n      </button>\n    </li>\n  </ul>\n  <div class=\"govuk-tabs__panel\" [hidden]=\"!tabSelected\">\n    <ng-container *ngIf=\"tabSelected === 'comments'\">\n      <div style=\"width: 100%\">\n        <div class=\"hmcts-banner\" *ngIf=\"navigationList?.length === 0\">\n          <svg alt=\"\" class=\"hmcts-banner__icon\" fill=\"currentColor\" focusable=\"false\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 25 25\" height=\"25\" width=\"25\">\n            <path d=\"M13.7,18.5h-2.4v-2.4h2.4V18.5z M12.5,13.7c-0.7,0-1.2-0.5-1.2-1.2V7.7c0-0.7,0.5-1.2,1.2-1.2s1.2,0.5,1.2,1.2v4.8\nC13.7,13.2,13.2,13.7,12.5,13.7z M12.5,0.5c-6.6,0-12,5.4-12,12s5.4,12,12,12s12-5.4,12-12S19.1,0.5,12.5,0.5z\" /></svg>\n          <div class=\"hmcts-banner__message\">\n            <span class=\"hmcts-banner__assistive\">information</span>\n            Select text to add a comment or highlight.\n          </div>\n        </div>\n        <button type=\"button\" class=\"govuk-button\"\n                id=\"commentSummary\" tabindex=\"0\"\n                data-l10n-id=\"commentSummary\"\n                title=\"Open collate summary\"\n                (click)=\"toggleCommentsSummary()\">Collate comments</button>\n      </div>\n      <ng-container *ngIf=\"navigationList?.length > 0\">\n        <mv-comments-navigate\n          [annotationList]=\"navigationList\">\n        </mv-comments-navigate>\n      </ng-container>\n      <p class=\"aui-comment__private-text\">\n        <span class=\"aui-comment__private\">private</span>\n        All comments can only be seen by you\n      </p>\n    </ng-container>\n    <div [hidden]=\"tabSelected !== 'filter'\">\n      <div class=\"govuk-tabs__panel--container\">\n        <mv-comment-filter></mv-comment-filter>\n        <mv-comments-navigate\n          *ngIf=\"navigationList?.length > 0\"\n          [annotationList]=\"navigationList\">\n        </mv-comments-navigate>\n      </div>\n    </div>\n\n    <div [hidden]=\"tabSelected !== 'search'\">\n      <mv-comment-search [annotations]=\"navigationList\"></mv-comment-search>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: CommentService }, { type: ToolbarEventService }, { type: IcpEventService }], propDecorators: { showCommentSummary: [{
                type: Input
            }], isHidden: [{
                type: Input
            }], showCommentSummaryDialog: [{
                type: Output
            }] } });

const getBookmarkState = createSelector(getMVState, (state) => state.bookmarks);
const getBookmarkPages = createSelector(getBookmarkState, getBookmarkPageEnt);
const getBookmarkEntities = createSelector(getBookmarkState, getBookmarkEnts);
const getBookmarkNodes = createSelector(getBookmarkEntities, (entities) => generateBookmarkNodes(entities));
const getEditableBookmark = createSelector(getBookmarkState, getEditBookmark);
const getScrollTop = createSelector(getBookmarkState, getScrollTop$1);
const getBookmarkInfo = createSelector(getBookmarkNodes, getDocumentId, getPdfPosition, getPages, (bookmarkNodes, docId, pdfPosition, pages) => {
    return {
        pageNumber: pdfPosition.pageNumber - 1,
        xCoordinate: pdfPosition.left,
        yCoordinate: ((pages[pdfPosition.pageNumber].styles.height)
            - (pdfPosition.top * (pages[pdfPosition.pageNumber].viewportScale)))
            / parseFloat(pages[pdfPosition.pageNumber].scaleRotation.scale),
        previous: bookmarkNodes.length > 0 ? bookmarkNodes.sort((a, b) => a.index - b.index)[bookmarkNodes.length - 1].id : undefined,
        documentId: docId
    };
});
const getBookmarksPerPage = createSelector(getPages, getBookmarkPages, (pages, pageEnt) => {
    if (pages && pageEnt) {
        const arr = [];
        Object.keys(pages).forEach(key => {
            const pageIdx = Number(key) - 1; // -1 as the thisPages array is 0 indexed
            const thisPage = pageEnt[pageIdx];
            arr.push({
                bookmark: thisPage ? thisPage : [],
                styles: pages[key].styles
            });
        });
        return arr;
    }
});

class BoxHighlightCreateComponent {
    constructor(toolbarEvents, highlightService) {
        this.toolbarEvents = toolbarEvents;
        this.highlightService = highlightService;
        this.saveSelection = new EventEmitter();
        this.drawStartX = -1;
        this.drawStartY = -1;
        this.backgroundColor = 'none';
        this.subscriptions = [];
    }
    ngOnInit() {
        this.subscriptions = [
            this.toolbarEvents.drawModeSubject.subscribe(drawMode => {
                this.defaultHeight = drawMode ? '100%' : '0px';
                this.defaultWidth = drawMode ? '100%' : '0px';
            }),
            this.toolbarEvents.redactWholePage.subscribe(() => {
                this.wholePage = true;
            })
        ];
    }
    ngOnDestroy() {
        this.subscriptions.forEach(subscription => {
            subscription.unsubscribe();
        });
    }
    initHighlight(event) {
        if (this.wholePage) {
            this.highlightPage();
            return;
        }
        const rect = HtmlTemplatesHelper.getAdjustedBoundingRect(event.target), offsetX = event.clientX - rect.left, offsetY = event.clientY - rect.top;
        console.log(`initHighlight: rect=${JSON.stringify(rect)}, clientX=${event.clientX}, clientY=${event.clientY}, offsetX=${offsetX}, offsetY=${offsetY}`);
        this.position = 'absolute';
        this.backgroundColor = 'yellow';
        this.drawStartX = offsetX;
        this.drawStartY = offsetY;
        this.display = 'block';
        this.height = 50;
        this.width = 50;
        this.top = this.drawStartY;
        this.left = this.drawStartX;
        switch (this.rotate) {
            case 90:
                this.top = this.drawStartY - this.height;
                break;
            case 180:
                this.top = this.drawStartY - this.height;
                this.left = this.drawStartX - this.width;
                break;
            case 270:
                this.left = this.drawStartX - this.width;
                break;
        }
    }
    updateHighlight(event) {
        const rect = HtmlTemplatesHelper.getAdjustedBoundingRect(event.target, false), offsetX = event.clientX - rect.left, offsetY = event.clientY - rect.top;
        if (this.drawStartX > 0 && this.drawStartY > 0) {
            this.height = Math.abs(offsetY - this.drawStartY);
            this.width = Math.abs(offsetX - this.drawStartX);
            this.top = Math.min(offsetY, this.drawStartY);
            this.left = Math.min(offsetX, this.drawStartX);
        }
    }
    createHighlight() {
        if (this.height / this.zoom > 5 || this.width / this.zoom > 5) {
            let rectangle = this.highlightService
                .applyRotation(this.pageHeight, this.pageWidth, this.height, this.width, this.top, this.left, this.rotate, this.zoom);
            rectangle = { id: v4(), ...rectangle };
            console.log(`createHighlight: rectangle=${JSON.stringify(rectangle)}`);
            this.saveSelection.emit({ rectangles: [rectangle], page: this.page });
            this.resetHighlight();
        }
    }
    resetHighlight() {
        this.drawStartX = -1;
        this.drawStartY = -1;
        this.display = 'none';
        this.width = 0;
        this.height = 0;
        this.backgroundColor = 'none';
        this.position = 'initial';
        this.wholePage = false;
    }
    highlightPage() {
        this.height = this.pageHeight;
        this.width = this.pageWidth;
        this.top = 0;
        this.left = 0;
        this.createHighlight();
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BoxHighlightCreateComponent, deps: [{ token: ToolbarEventService }, { token: HighlightCreateService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: BoxHighlightCreateComponent, selector: "mv-box-highlight-create", inputs: { page: "page", pageHeight: "pageHeight", pageWidth: "pageWidth", rotate: "rotate", zoom: "zoom", container: "container" }, outputs: { saveSelection: "saveSelection" }, viewQueries: [{ propertyName: "highlight", first: true, predicate: ["boxHighlight"], descendants: true }], ngImport: i0, template: "<div [style.height]=\"defaultHeight\"\n     [style.width]=\"defaultWidth\"\n     (mousedown)=\"initHighlight($event)\"\n     (mousemove)=\"updateHighlight($event)\"\n     (mouseup)=\"createHighlight()\">\n  <div #boxHighlight\n     class=\"box-highlight\"\n     [style.display]=\"display\"\n     [style.position]=\"position\"\n     [style.background-color]=\"backgroundColor\"\n     [style.height]=\"height ? height + 'px' : '100%'\"\n     [style.width]=\"width ? width + 'px' : '100%'\"\n     [style.top]=\"top + 'px'\"\n     [style.left]=\"left + 'px'\">\n  </div>\n</div>\n" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BoxHighlightCreateComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-box-highlight-create', template: "<div [style.height]=\"defaultHeight\"\n     [style.width]=\"defaultWidth\"\n     (mousedown)=\"initHighlight($event)\"\n     (mousemove)=\"updateHighlight($event)\"\n     (mouseup)=\"createHighlight()\">\n  <div #boxHighlight\n     class=\"box-highlight\"\n     [style.display]=\"display\"\n     [style.position]=\"position\"\n     [style.background-color]=\"backgroundColor\"\n     [style.height]=\"height ? height + 'px' : '100%'\"\n     [style.width]=\"width ? width + 'px' : '100%'\"\n     [style.top]=\"top + 'px'\"\n     [style.left]=\"left + 'px'\">\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: HighlightCreateService }], propDecorators: { page: [{
                type: Input
            }], pageHeight: [{
                type: Input
            }], pageWidth: [{
                type: Input
            }], rotate: [{
                type: Input
            }], zoom: [{
                type: Input
            }], container: [{
                type: Input
            }], saveSelection: [{
                type: Output
            }], highlight: [{
                type: ViewChild,
                args: ['boxHighlight', { static: false }]
            }] } });

class RectangleComponent {
    set annoRect(annoRect) {
        this._annoRect = { ...annoRect };
        this.height = +(annoRect.height * this.zoom).toFixed(2);
        this.width = +(annoRect.width * this.zoom).toFixed(2);
        this.left = +(annoRect.x * this.zoom).toFixed(2);
        this.top = +(annoRect.y * this.zoom).toFixed(2);
    }
    get annoRect() {
        return this._annoRect;
    }
    constructor(toolbarEvents, highlightService) {
        this.toolbarEvents = toolbarEvents;
        this.highlightService = highlightService;
        this.selectEvent = new EventEmitter();
        this.updateEvent = new EventEmitter();
        this.subscriptions = [];
        this.enableGrabNDrag = false;
    }
    ngOnChanges(changes) {
        if (changes.rotate) {
            this.adjustForRotation(this.rotate);
        }
    }
    ngAfterViewInit() {
        this.subscriptions.push(this.toolbarEvents.grabNDrag.subscribe(grabNDrag => this.enableGrabNDrag = grabNDrag));
    }
    ngOnDestroy() {
        this.subscriptions.filter(subscription => !subscription.closed)
            .forEach(subscription => subscription.unsubscribe());
    }
    set selected(selected) {
        this._selected = selected;
        if (this._selected && this.viewRect) {
            this.viewRect.nativeElement.focus();
        }
    }
    get selected() {
        return this._selected;
    }
    onClick() {
        this.selectEvent.emit(this.annoRect);
    }
    onUpdate(viewRect) {
        const { offsetHeight, offsetWidth, offsetTop, offsetLeft } = viewRect;
        if (this.hasRectangleChanged(viewRect)) {
            let rectangle = this.highlightService
                .applyRotation(this.pageHeight, this.pageWidth, offsetHeight, offsetWidth, offsetTop, offsetLeft, this.rotate, this.zoom);
            rectangle = { ...this.annoRect, ...rectangle };
            this.updateEvent.emit({ ...rectangle });
        }
    }
    adjustForRotation(rotation) {
        const { top, left, height, width } = this;
        switch (rotation) {
            case 90:
                this.width = height;
                this.height = width;
                this.left = this.pageWidth - top - height;
                this.top = left;
                break;
            case 180:
                this.left = this.pageWidth - left - width;
                this.top = this.pageHeight - top - height;
                break;
            case 270:
                this.width = height;
                this.height = width;
                this.left = top;
                this.top = this.pageHeight - left - width;
                break;
        }
    }
    hasRectangleChanged(viewRect) {
        return Math.round(this.left) !== viewRect.offsetLeft ||
            Math.round(this.top) !== viewRect.offsetTop ||
            Math.round(this.width) !== viewRect.offsetWidth ||
            Math.round(this.height) !== viewRect.offsetHeight;
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RectangleComponent, deps: [{ token: ToolbarEventService }, { token: HighlightCreateService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: RectangleComponent, selector: "mv-anno-rectangle", inputs: { color: "color", zoom: "zoom", rotate: "rotate", editable: "editable", pageHeight: "pageHeight", pageWidth: "pageWidth", annoRect: "annoRect", selected: "selected" }, outputs: { selectEvent: "selectEvent", updateEvent: "updateEvent" }, viewQueries: [{ propertyName: "viewRect", first: true, predicate: ["rectElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"editable; else nonEditable\">\n  <div #rectElement\n       class=\"rectangle\"\n       draggable\n       resizable\n       [tabindex]=\"annoRect.id\"\n       [ngClass]=\"{ 'selected': selected, 'grabNDrag': enableGrabNDrag }\"\n       [style.backgroundColor]=\"'#' + color\"\n       [style.width]=\"width + 'px'\"\n       [style.height]=\"height + 'px'\"\n       [style.left]=\"left + 'px'\"\n       [style.top]=\"top + 'px'\"\n       [rotate]=\"0\"\n       [selected]=\"selected\"\n       (click)=\"onClick()\"\n       (stopped)=\"onUpdate(rectElement)\">\n  </div>\n</div>\n<ng-template #nonEditable>\n  <div #rectElement\n       class=\"rectangle\"\n       [tabindex]=\"annoRect.id\"\n       [ngClass]=\"{ 'selected': selected }\"\n       [style.backgroundColor]=\"'#' + color\"\n       [style.width]=\"width + 'px'\"\n       [style.height]=\"height+ 'px'\"\n       [style.left]=\"left + 'px'\"\n       [style.top]=\"top + 'px'\"\n       (click)=\"onClick()\">\n  </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4$1.DraggableElementDirective, selector: "[draggable]", inputs: ["rotate"], outputs: ["coordinates", "stopped"] }, { kind: "directive", type: i4$1.ResizableElementDirective, selector: "[resizable]", inputs: ["rotate", "selected"], outputs: ["stopped"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RectangleComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-anno-rectangle', template: "<div *ngIf=\"editable; else nonEditable\">\n  <div #rectElement\n       class=\"rectangle\"\n       draggable\n       resizable\n       [tabindex]=\"annoRect.id\"\n       [ngClass]=\"{ 'selected': selected, 'grabNDrag': enableGrabNDrag }\"\n       [style.backgroundColor]=\"'#' + color\"\n       [style.width]=\"width + 'px'\"\n       [style.height]=\"height + 'px'\"\n       [style.left]=\"left + 'px'\"\n       [style.top]=\"top + 'px'\"\n       [rotate]=\"0\"\n       [selected]=\"selected\"\n       (click)=\"onClick()\"\n       (stopped)=\"onUpdate(rectElement)\">\n  </div>\n</div>\n<ng-template #nonEditable>\n  <div #rectElement\n       class=\"rectangle\"\n       [tabindex]=\"annoRect.id\"\n       [ngClass]=\"{ 'selected': selected }\"\n       [style.backgroundColor]=\"'#' + color\"\n       [style.width]=\"width + 'px'\"\n       [style.height]=\"height+ 'px'\"\n       [style.left]=\"left + 'px'\"\n       [style.top]=\"top + 'px'\"\n       (click)=\"onClick()\">\n  </div>\n</ng-template>\n" }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: HighlightCreateService }], propDecorators: { color: [{
                type: Input
            }], zoom: [{
                type: Input
            }], rotate: [{
                type: Input
            }], editable: [{
                type: Input
            }], pageHeight: [{
                type: Input
            }], pageWidth: [{
                type: Input
            }], selectEvent: [{
                type: Output
            }], updateEvent: [{
                type: Output
            }], viewRect: [{
                type: ViewChild,
                args: ['rectElement', { static: false }]
            }], annoRect: [{
                type: Input
            }], selected: [{
                type: Input
            }] } });

class CtxToolbarComponent {
    constructor() {
        this.createHighlightEvent = new EventEmitter();
        this.deleteHighlightEvent = new EventEmitter();
        this.addOrEditCommentEvent = new EventEmitter();
        this.createBookmarkEvent = new EventEmitter();
        this.defaultHeight = 70;
        this.defaultWidth = 300;
    }
    ngOnChanges(changes) {
        this.setRectangle();
        this.top = this.popupTop();
        this.left = this.popupLeft();
    }
    set rectangles(rectangles) {
        if (rectangles) {
            this._rectangles = rectangles;
            this.setRectangle();
        }
    }
    get rectangles() {
        return this._rectangles;
    }
    createHighlight() {
        this.createHighlightEvent.emit();
        this.rectangle = undefined;
    }
    deleteHighlight() {
        this.deleteHighlightEvent.emit();
    }
    addOrEditComment() {
        this.addOrEditCommentEvent.emit();
        setTimeout(() => {
            // This hack to wait until the element is rendered seems to be unreliable,
            if (!location.hash) {
                document.getElementById('viewerContainer')?.scrollBy(0, 1);
            }
        }, 20);
    }
    createBookmark() {
        this.createBookmarkEvent.emit(this.rectangle);
        this.rectangle = undefined;
    }
    setRectangle() {
        const rectangle = this.rectangles
            .reduce((prev, current) => prev.y < current.y ? prev : current);
        this.rectangle = { ...rectangle };
        switch (this.rotate) {
            case 90:
                this.rectangle.width = rectangle.height;
                this.rectangle.height = rectangle.width;
                this.rectangle.x = (this.pageWidth / this.zoom) - rectangle.y - rectangle.height;
                this.rectangle.y = rectangle.x;
                break;
            case 180:
                this.rectangle.x = (this.pageWidth / this.zoom) - rectangle.x - rectangle.width;
                this.rectangle.y = (this.pageHeight / this.zoom) - rectangle.y - rectangle.height;
                break;
            case 270:
                this.rectangle.width = rectangle.height;
                this.rectangle.height = rectangle.width;
                this.rectangle.x = rectangle.y;
                this.rectangle.y = (this.pageHeight / this.zoom) - rectangle.x - rectangle.width;
                break;
        }
    }
    popupTop() {
        const popupTop = this.rectangle.y * this.zoom - this.defaultHeight;
        return popupTop <= 0 ? this.defaultHeight : popupTop;
    }
    popupLeft() {
        const popupLeft = (this.rectangle.x + (this.rectangle.width / 2)) * this.zoom - (this.defaultWidth / 2);
        if (popupLeft <= 0) {
            return 0;
        }
        else if (popupLeft >= this.pageWidth - this.defaultWidth) {
            return this.pageWidth - this.defaultWidth;
        }
        else {
            return popupLeft;
        }
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CtxToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CtxToolbarComponent, selector: "mv-ctx-toolbar", inputs: { zoom: "zoom", rotate: "rotate", pageHeight: "pageHeight", pageWidth: "pageWidth", canHighlight: "canHighlight", canBookmark: "canBookmark", canComment: "canComment", canDelete: "canDelete", rectangles: "rectangles" }, outputs: { createHighlightEvent: "createHighlightEvent", deleteHighlightEvent: "deleteHighlightEvent", addOrEditCommentEvent: "addOrEditCommentEvent", createBookmarkEvent: "createBookmarkEvent" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"toolbar\" *ngIf=\"rectangle\"\n     [style.top.px]=\"top\"\n     [style.left.px]=\"left\">\n  <button *ngIf=\"canHighlight\"\n          type=\"button\" title=\"Highlight\"\n          class=\"aui__toolbar-button aui__toolbar-button--comments contextual-btn leftButton aui__toolbar-button-highlight\"\n          (mousedown)=\"createHighlight()\">\n    <span>Highlight</span>\n  </button>\n  <button *ngIf=\"canDelete\"\n          type=\"button\" title=\"Delete\"\n          class=\"aui__toolbar-button aui__toolbar-button--comments contextual-btn leftButton\"\n          (mousedown)=\"deleteHighlight()\">\n    <span>Remove</span>\n  </button>\n  <button *ngIf=\"canComment\"\n          type=\"button\" title=\"Comment\"\n          class=\"aui__toolbar-button aui__toolbar-button--comments contextual-btn rightButton aui__toolbar-button-comment\"\n          (mousedown)=\"addOrEditComment()\">\n    <span>Comment</span></button>\n  <button *ngIf=\"canBookmark\"\n          type=\"button\" title=\"Bookmark\"\n          class=\"aui__toolbar-button aui__toolbar-button--comments contextual-btn rightButton aui__toolbar-button-bookmark\"\n          id=\"bookmarkButton\"\n          (mousedown)=\"createBookmark()\">\n    <span>Bookmark</span></button>\n  <div class=\"arrow-down\">\n    <div class=\"inner-triangle\"></div>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CtxToolbarComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-ctx-toolbar', template: "<div class=\"toolbar\" *ngIf=\"rectangle\"\n     [style.top.px]=\"top\"\n     [style.left.px]=\"left\">\n  <button *ngIf=\"canHighlight\"\n          type=\"button\" title=\"Highlight\"\n          class=\"aui__toolbar-button aui__toolbar-button--comments contextual-btn leftButton aui__toolbar-button-highlight\"\n          (mousedown)=\"createHighlight()\">\n    <span>Highlight</span>\n  </button>\n  <button *ngIf=\"canDelete\"\n          type=\"button\" title=\"Delete\"\n          class=\"aui__toolbar-button aui__toolbar-button--comments contextual-btn leftButton\"\n          (mousedown)=\"deleteHighlight()\">\n    <span>Remove</span>\n  </button>\n  <button *ngIf=\"canComment\"\n          type=\"button\" title=\"Comment\"\n          class=\"aui__toolbar-button aui__toolbar-button--comments contextual-btn rightButton aui__toolbar-button-comment\"\n          (mousedown)=\"addOrEditComment()\">\n    <span>Comment</span></button>\n  <button *ngIf=\"canBookmark\"\n          type=\"button\" title=\"Bookmark\"\n          class=\"aui__toolbar-button aui__toolbar-button--comments contextual-btn rightButton aui__toolbar-button-bookmark\"\n          id=\"bookmarkButton\"\n          (mousedown)=\"createBookmark()\">\n    <span>Bookmark</span></button>\n  <div class=\"arrow-down\">\n    <div class=\"inner-triangle\"></div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [], propDecorators: { zoom: [{
                type: Input
            }], rotate: [{
                type: Input
            }], pageHeight: [{
                type: Input
            }], pageWidth: [{
                type: Input
            }], canHighlight: [{
                type: Input
            }], canBookmark: [{
                type: Input
            }], canComment: [{
                type: Input
            }], canDelete: [{
                type: Input
            }], createHighlightEvent: [{
                type: Output
            }], deleteHighlightEvent: [{
                type: Output
            }], addOrEditCommentEvent: [{
                type: Output
            }], createBookmarkEvent: [{
                type: Output
            }], rectangles: [{
                type: Input
            }] } });

class AnnotationViewComponent {
    set annotation(value) {
        this.anno = { ...value };
    }
    set selectedAnnoId(selectedId) {
        if (selectedId) {
            const id = this.anno.id || this.anno.redactionId; // todo make it unique
            this.selected = selectedId.annotationId ? (selectedId.annotationId === id) : false;
        }
    }
    constructor(toolbarEvents, store) {
        this.toolbarEvents = toolbarEvents;
        this.store = store;
        this.update = new EventEmitter();
        this.delete = new EventEmitter();
        this.annotationClick = new EventEmitter();
    }
    onSelect() {
        const annotationId = this.anno.id || this.anno.redactionId;
        this.annotationClick.emit({ annotationId, editable: false, selected: true });
    }
    onRectangleUpdate(rectangle) {
        const annotation = { ...this.anno };
        annotation.rectangles = annotation.rectangles.filter(r => r.id !== rectangle.id);
        annotation.rectangles.push(rectangle);
        this.update.emit(annotation);
    }
    deleteHighlight() {
        this.delete.emit(this.anno);
    }
    addOrEditComment() {
        if (this.anno.comments.length === 0) {
            const comment = {
                annotationId: this.anno.id,
                content: '',
                createdBy: this.anno.createdBy,
                createdByDetails: undefined,
                createdDate: moment.utc().tz('Europe/London').toISOString(),
                id: v4(),
                lastModifiedBy: '',
                lastModifiedByDetails: undefined,
                lastModifiedDate: '',
                tags: [],
                page: null,
                pages: {},
                pageHeight: null,
                selected: false,
                editable: false
            };
            this.store.dispatch(new AddOrEditComment(comment));
        }
        this.selected = true;
        this.annotationClick.emit({ annotationId: this.anno.id, editable: true, selected: true });
        this.toolbarEvents.toggleCommentsPanel(true);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationViewComponent, deps: [{ token: ToolbarEventService }, { token: i1.Store }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: AnnotationViewComponent, selector: "mv-annotation", inputs: { annotation: "annotation", zoom: "zoom", rotate: "rotate", selectedAnnoId: "selectedAnnoId", pageHeight: "pageHeight", pageWidth: "pageWidth" }, outputs: { update: "update", delete: "delete", annotationClick: "annotationClick" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div #container [tabindex]=\"anno.id\">\n  <mv-ctx-toolbar *ngIf=\"selected\"\n                  [canDelete]=\"true\" [canComment]=\"true\"\n                  [rectangles]=\"anno.rectangles\"\n                  [zoom]=\"zoom\"\n                  [rotate]=\"rotate\"\n                  [pageHeight]=\"pageHeight\"\n                  [pageWidth]=\"pageWidth\"\n                  (deleteHighlightEvent)=\"deleteHighlight()\"\n                  (addOrEditCommentEvent)=\"addOrEditComment()\">\n  </mv-ctx-toolbar>\n  <ng-container *ngFor=\"let rectangle of anno.rectangles\">\n    <mv-anno-rectangle\n      (selectEvent)=\"onSelect()\"\n      (updateEvent)=\"onRectangleUpdate($event)\"\n      [selected]=\"selected\"\n      [zoom]=\"zoom\"\n      [rotate]=\"rotate\"\n      [pageHeight]=\"pageHeight\"\n      [pageWidth]=\"pageWidth\"\n      [editable]=\"anno.rectangles.length <= 1\"\n      [annoRect]=\"rectangle\"\n      [color]=\"anno.color\">\n    </mv-anno-rectangle>\n  </ng-container>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: RectangleComponent, selector: "mv-anno-rectangle", inputs: ["color", "zoom", "rotate", "editable", "pageHeight", "pageWidth", "annoRect", "selected"], outputs: ["selectEvent", "updateEvent"] }, { kind: "component", type: CtxToolbarComponent, selector: "mv-ctx-toolbar", inputs: ["zoom", "rotate", "pageHeight", "pageWidth", "canHighlight", "canBookmark", "canComment", "canDelete", "rectangles"], outputs: ["createHighlightEvent", "deleteHighlightEvent", "addOrEditCommentEvent", "createBookmarkEvent"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationViewComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-annotation', template: "<div #container [tabindex]=\"anno.id\">\n  <mv-ctx-toolbar *ngIf=\"selected\"\n                  [canDelete]=\"true\" [canComment]=\"true\"\n                  [rectangles]=\"anno.rectangles\"\n                  [zoom]=\"zoom\"\n                  [rotate]=\"rotate\"\n                  [pageHeight]=\"pageHeight\"\n                  [pageWidth]=\"pageWidth\"\n                  (deleteHighlightEvent)=\"deleteHighlight()\"\n                  (addOrEditCommentEvent)=\"addOrEditComment()\">\n  </mv-ctx-toolbar>\n  <ng-container *ngFor=\"let rectangle of anno.rectangles\">\n    <mv-anno-rectangle\n      (selectEvent)=\"onSelect()\"\n      (updateEvent)=\"onRectangleUpdate($event)\"\n      [selected]=\"selected\"\n      [zoom]=\"zoom\"\n      [rotate]=\"rotate\"\n      [pageHeight]=\"pageHeight\"\n      [pageWidth]=\"pageWidth\"\n      [editable]=\"anno.rectangles.length <= 1\"\n      [annoRect]=\"rectangle\"\n      [color]=\"anno.color\">\n    </mv-anno-rectangle>\n  </ng-container>\n</div>\n" }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: i1.Store }], propDecorators: { annotation: [{
                type: Input
            }], zoom: [{
                type: Input
            }], rotate: [{
                type: Input
            }], selectedAnnoId: [{
                type: Input
            }], pageHeight: [{
                type: Input
            }], pageWidth: [{
                type: Input
            }], update: [{
                type: Output
            }], delete: [{
                type: Output
            }], annotationClick: [{
                type: Output
            }], container: [{
                type: ViewChild,
                args: ['container', { static: false }]
            }] } });

class AnnotationSetComponent {
    constructor(store, commentService) {
        this.store = store;
        this.commentService = commentService;
        this.annotations = [];
    }
    ngOnInit() {
        this.selectedAnnotation$ = this.store.pipe(select(getSelectedAnnotation));
    }
    onAnnotationUpdate(annotation) {
        this.store.dispatch(new SaveAnnotation(annotation));
    }
    onAnnotationDelete(annotation) {
        if (annotation.comments.length > 0) {
            this.commentService.updateUnsavedCommentsStatus(annotation, false);
        }
        this.store.dispatch(new DeleteAnnotation(annotation.id));
    }
    selectAnnotation(selectedAnnotation) {
        this.store.dispatch(new SelectedAnnotation(selectedAnnotation));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationSetComponent, deps: [{ token: i1.Store }, { token: CommentService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: AnnotationSetComponent, selector: "mv-annotation-set", inputs: { page: "page", annotations: "annotations", zoom: "zoom", rotate: "rotate", pageHeight: "pageHeight", pageWidth: "pageWidth" }, ngImport: i0, template: "<ng-container *ngFor=\"let annotation of annotations\">\n  <mv-annotation [annotation]=\"annotation\"\n                 [zoom]=\"zoom\"\n                 [rotate]=\"rotate\"\n                 [selectedAnnoId]=\"selectedAnnotation$ | async\"\n                 [pageHeight]=\"pageHeight\"\n                 [pageWidth]=\"pageWidth\"\n                 (update)=\"onAnnotationUpdate($event)\"\n                 (delete)=\"onAnnotationDelete($event)\"\n                 (annotationClick)=\"selectAnnotation($event)\">\n  </mv-annotation>\n</ng-container>\n", dependencies: [{ kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: AnnotationViewComponent, selector: "mv-annotation", inputs: ["annotation", "zoom", "rotate", "selectedAnnoId", "pageHeight", "pageWidth"], outputs: ["update", "delete", "annotationClick"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationSetComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-annotation-set', template: "<ng-container *ngFor=\"let annotation of annotations\">\n  <mv-annotation [annotation]=\"annotation\"\n                 [zoom]=\"zoom\"\n                 [rotate]=\"rotate\"\n                 [selectedAnnoId]=\"selectedAnnotation$ | async\"\n                 [pageHeight]=\"pageHeight\"\n                 [pageWidth]=\"pageWidth\"\n                 (update)=\"onAnnotationUpdate($event)\"\n                 (delete)=\"onAnnotationDelete($event)\"\n                 (annotationClick)=\"selectAnnotation($event)\">\n  </mv-annotation>\n</ng-container>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: CommentService }], propDecorators: { page: [{
                type: Input
            }], annotations: [{
                type: Input
            }], zoom: [{
                type: Input
            }], rotate: [{
                type: Input
            }], pageHeight: [{
                type: Input
            }], pageWidth: [{
                type: Input
            }] } });

class MetadataLayerComponent {
    constructor(store, highlightService, toolbarEvents, viewerEvents) {
        this.store = store;
        this.highlightService = highlightService;
        this.toolbarEvents = toolbarEvents;
        this.viewerEvents = viewerEvents;
        this.pages = []; // todo add type
        this.drawMode = false;
    }
    ngOnInit() {
        this.$subscriptions = this.store.pipe(select(getPages))
            .subscribe(pages => this.pages = Object.values(pages));
        this.annoPages$ = this.store.pipe(select(getPageEntities));
        this.$subscriptions.add(this.toolbarEvents.drawModeSubject.subscribe(drawMode => this.drawMode = drawMode));
        this.$subscriptions.add(this.viewerEvents.textHighlight.subscribe(highlight => this.showContextToolbar(highlight)));
        this.$subscriptions.add(this.viewerEvents.ctxToolbarCleared.subscribe(() => this.clearContextToolbar()));
    }
    ngOnDestroy() {
        this.$subscriptions.unsubscribe();
    }
    showContextToolbar(highlight) {
        this.highlightPage = highlight.page;
        this.rectangles = highlight.rectangles;
        if (this.rectangles) {
            this.toolbarEvents.highlightModeSubject.next(false);
        }
    }
    clearContextToolbar() {
        this.rectangles = undefined;
    }
    createHighlight() {
        this.highlightService.saveAnnotation(this.rectangles, this.highlightPage);
        this.highlightService.resetHighlight();
        this.rectangles = undefined;
    }
    createBookmark(rectangle) {
        this.store.pipe(select(getBookmarkInfo), take(1))
            .subscribe((bookmarkInfo) => {
            const selection = window.getSelection().toString();
            this.store.dispatch(new CreateBookmark({
                ...bookmarkInfo,
                name: selection.length > 0 ? selection.substr(0, 30) : 'new bookmark',
                id: v4(),
                pageNumber: this.highlightPage - 1,
                xCoordinate: rectangle.x,
                yCoordinate: rectangle.y
            }));
            this.toolbarEvents.toggleSideBar(true);
            this.toolbarEvents.toggleSideBarView(false);
            this.highlightService.resetHighlight();
            this.rectangles = undefined;
        });
    }
    saveAnnotation({ rectangles, page }) {
        this.highlightService.saveAnnotation(rectangles, page);
        this.toolbarEvents.drawModeSubject.next(false);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MetadataLayerComponent, deps: [{ token: i1.Store }, { token: HighlightCreateService }, { token: ToolbarEventService }, { token: ViewerEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: MetadataLayerComponent, selector: "mv-metadata-layer", inputs: { zoom: "zoom", rotate: "rotate" }, ngImport: i0, template: "<div class=\"pageContainer\">\n  <div  *ngFor=\"let page of pages;  index as i\"\n       class=\"pageContainer__page\"\n       [ngStyle]=\"{\n       'width.px': page.styles.width,\n       'height.px': page.styles.height\n       }\"\n       [ngClass]=\"{ 'pageContainer__page--draw' : drawMode }\">\n    <mv-box-highlight-create\n      [page]=\"i + 1\"\n      [pageHeight]=\"page.styles.height\"\n      [pageWidth]=\"page.styles.width\"\n      [rotate]=\"rotate\"\n      [zoom]=\"zoom\"\n      (saveSelection)=\"saveAnnotation($event)\">\n    </mv-box-highlight-create>\n    <mv-ctx-toolbar *ngIf=\"rectangles && highlightPage === (i + 1)\"\n                    [rectangles]=\"rectangles\"\n                    [canBookmark]=\"true\" [canHighlight]=\"true\"\n                    [zoom]=\"zoom\"\n                    [rotate]=\"rotate\"\n                    [pageHeight]=\"page.styles.height\"\n                    [pageWidth]=\"page.styles.width\"\n                    (createBookmarkEvent)=\"createBookmark($event)\"\n                    (createHighlightEvent)=\"createHighlight()\">\n    </mv-ctx-toolbar>\n    <div class=\"pageContainer__page-item\">\n      <mv-annotation-set *ngIf=\"(annoPages$ | async) as annoPages\"\n                         [zoom]=\"zoom\"\n                         [rotate]=\"rotate\"\n                         [pageHeight]=\"page.styles.height\"\n                         [pageWidth]=\"page.styles.width\"\n                         [page]=\"i\" [annotations]=\"annoPages[i + 1]\"></mv-annotation-set>\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: BoxHighlightCreateComponent, selector: "mv-box-highlight-create", inputs: ["page", "pageHeight", "pageWidth", "rotate", "zoom", "container"], outputs: ["saveSelection"] }, { kind: "component", type: AnnotationSetComponent, selector: "mv-annotation-set", inputs: ["page", "annotations", "zoom", "rotate", "pageHeight", "pageWidth"] }, { kind: "component", type: CtxToolbarComponent, selector: "mv-ctx-toolbar", inputs: ["zoom", "rotate", "pageHeight", "pageWidth", "canHighlight", "canBookmark", "canComment", "canDelete", "rectangles"], outputs: ["createHighlightEvent", "deleteHighlightEvent", "addOrEditCommentEvent", "createBookmarkEvent"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MetadataLayerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-metadata-layer', template: "<div class=\"pageContainer\">\n  <div  *ngFor=\"let page of pages;  index as i\"\n       class=\"pageContainer__page\"\n       [ngStyle]=\"{\n       'width.px': page.styles.width,\n       'height.px': page.styles.height\n       }\"\n       [ngClass]=\"{ 'pageContainer__page--draw' : drawMode }\">\n    <mv-box-highlight-create\n      [page]=\"i + 1\"\n      [pageHeight]=\"page.styles.height\"\n      [pageWidth]=\"page.styles.width\"\n      [rotate]=\"rotate\"\n      [zoom]=\"zoom\"\n      (saveSelection)=\"saveAnnotation($event)\">\n    </mv-box-highlight-create>\n    <mv-ctx-toolbar *ngIf=\"rectangles && highlightPage === (i + 1)\"\n                    [rectangles]=\"rectangles\"\n                    [canBookmark]=\"true\" [canHighlight]=\"true\"\n                    [zoom]=\"zoom\"\n                    [rotate]=\"rotate\"\n                    [pageHeight]=\"page.styles.height\"\n                    [pageWidth]=\"page.styles.width\"\n                    (createBookmarkEvent)=\"createBookmark($event)\"\n                    (createHighlightEvent)=\"createHighlight()\">\n    </mv-ctx-toolbar>\n    <div class=\"pageContainer__page-item\">\n      <mv-annotation-set *ngIf=\"(annoPages$ | async) as annoPages\"\n                         [zoom]=\"zoom\"\n                         [rotate]=\"rotate\"\n                         [pageHeight]=\"page.styles.height\"\n                         [pageWidth]=\"page.styles.width\"\n                         [page]=\"i\" [annotations]=\"annoPages[i + 1]\"></mv-annotation-set>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: HighlightCreateService }, { type: ToolbarEventService }, { type: ViewerEventService }], propDecorators: { zoom: [{
                type: Input
            }], rotate: [{
                type: Input
            }] } });

class BookmarksComponent {
    set bookmarkNodes(value) {
        this.rebuildTreeForData(value);
        if (this._bookmarkNodes && this.sortMode !== this.customSort) {
            this.sortBookmarks();
        }
    }
    ;
    get bookmarkNodes() {
        return this._bookmarkNodes;
    }
    ;
    constructor(store) {
        this.store = store;
        this.goToDestination = new EventEmitter();
        this.treeHasChanged = new EventEmitter();
        this._bookmarkNodes = [];
        // expansion model tracks expansion state
        this.expansionModel = new SelectionModel(true);
        this.isDraggingOn = false;
        this.isUserdragging = false;
        this.expandDelay = 1000;
        this.pageLookup = {};
        this.BOOKMARK_CHAR_LIMIT = 30;
        this.dragNodeExpandOverWaitTimeMs = 300;
        this.options = {
            allowDrag: true,
            allowDrop: true
        };
        this._customSort = 'CUSTOM';
        this._positionSort = 'POSITION';
        this.hasChild = (_, node) => {
            return node.children && node.children.length > 0;
        };
    }
    ngOnInit() {
        this.sortMode = this.customSort;
        this.$subscription = this.store.pipe(select(getEditableBookmark))
            .subscribe(editableId => this.editableBookmark = editableId);
        this.$subscription.add(this.store.select(getPages)
            .subscribe(pages => {
            Object.keys(pages).map(key => {
                this.pageLookup[key] = pages[key];
            });
        }));
    }
    ngOnChanges(changes) {
        if (changes?.bookmarkNodes) {
            setTimeout(() => {
                this.store.dispatch(new UpdateBookmarkScrollTop(this.parentScrollTop));
            }, 200);
        }
    }
    ngOnDestroy() {
        this.$subscription.unsubscribe();
    }
    editBookmark(id) {
        this.editableBookmark = id;
    }
    onAddBookmarkClick() {
        this.store.pipe(select(getBookmarkInfo), take(1))
            .subscribe((bookmarkInfo) => {
            this.store.dispatch(new CreateBookmark({
                ...bookmarkInfo, name: '', id: v4()
            }));
        });
    }
    deleteBookmark2(node) {
        this.customSortBookmarks();
        let next;
        const changedData = JSON.parse(JSON.stringify(this.bookmarkNodes));
        const siblings = this.findNodeSiblings(changedData, node.id);
        if (siblings && siblings.length > node.index + 1) {
            next = siblings[node.index + 1];
            next.previous = node.previous;
        }
        const toDelete = [node.id, ...getBookmarkChildren(node.children)];
        this.store.dispatch(new DeleteBookmark({
            deleted: toDelete, updated: next
        }));
    }
    updateBookmark(bookmark, name) {
        const editedBookmark = {
            ...bookmark,
            name
        };
        if (name) {
            this.store.dispatch(new UpdateBookmark(editedBookmark));
            this.editableBookmark = undefined;
        }
    }
    goToBookmark(bookmark) {
        const thisPage = this.pageLookup[bookmark.pageNumber + 1];
        const defaultHeight = thisPage.styles.height;
        const defaultScaleY = this.scaledY(bookmark.yCoordinate, defaultHeight, thisPage);
        let top = 0, left = 0;
        switch (this.rotate) {
            case 90:
                left = -defaultScaleY;
                break;
            case 180:
                top = this.scaledY(bookmark.yCoordinate, (defaultHeight - (24 * this.zoom)), thisPage);
                break;
            case 270:
                left = defaultScaleY;
                break;
            default:
                top = defaultScaleY;
        }
        this.goToDestination.emit([
            bookmark.pageNumber,
            { 'name': 'XYZ' },
            left,
            top
        ]);
    }
    get customSort() {
        return this._customSort;
    }
    get positionSort() {
        return this._positionSort;
    }
    sort(mode) {
        this.sortMode = mode;
        this.sortBookmarks();
    }
    sortBookmarks() {
        switch (this.sortMode) {
            case this.customSort: {
                this.customSortBookmarks();
                break;
            }
            case this.positionSort: {
                this.positionSortBookmarks();
                break;
            }
            default: {
                this.customSortBookmarks();
                break;
            }
        }
    }
    positionSortBookmarks() {
        this.bookmarkNodes.sort((a, b) => a.pageNumber === b.pageNumber ? a.yCoordinate - b.yCoordinate : a.pageNumber - b.pageNumber);
        this.isDraggingOn = false;
        this.rebuildTreeForData(this.bookmarkNodes);
    }
    customSortBookmarks() {
        if (this.bookmarkNodes.length > 1) {
            this.bookmarkNodes.sort((a, b) => a.index - b.index);
        }
        this.isDraggingOn = true;
        this.rebuildTreeForData(this.bookmarkNodes);
    }
    scaledY(yCoordinate, height, page) {
        const viewportScale = page.viewportScale / this.zoom;
        return ((height / this.zoom) - yCoordinate) / viewportScale;
    }
    getNode(bookmarks, parentId) {
        if (typeof bookmarks !== 'undefined') {
            for (let i = 0; i < bookmarks.length; i++) {
                if (bookmarks[i].id === parentId) {
                    return [bookmarks[i]];
                }
                const a = this.getNode(bookmarks[i].children, parentId);
                if (a !== null) {
                    return a;
                }
            }
        }
        return null;
    }
    drop(event) {
        if (!event.isPointerOverContainer || (event.previousIndex === event.currentIndex))
            return;
        const hasMovedUpTheTree = event.previousIndex > event.currentIndex;
        const bookmarkNodesString = JSON.stringify(this._bookmarkNodes);
        const changedData = JSON.parse(bookmarkNodesString);
        const visibleNodes = this.visibleNodes(this._bookmarkNodes);
        const toNode = visibleNodes[event.currentIndex];
        const toNodeSiblings = this.findNodeSiblings(changedData, toNode.id);
        const toNodeParent = toNodeSiblings[0].parent;
        const toIndex = toNodeSiblings.findIndex(s => s.id === toNode.id);
        const fromNode = event.item.data;
        const fromNodeSiblings = this.findNodeSiblings(changedData, fromNode.id);
        const fromIndex = fromNodeSiblings.findIndex(n => n.id === fromNode.id);
        if (this.isToNodeChildOfFromNode(fromNode?.children, toNode))
            return;
        if (this.dragNodeInsertToParent) {
            const indexOfParent = toNodeSiblings.findIndex(element => element.id === toNode.id);
            const parentNode = toNodeSiblings[indexOfParent];
            const firstChild = parentNode?.children && parentNode?.children.length > 0 ? parentNode.children[0] : null;
            let movedBookmarksWithParent = [{ ...fromNode, parent: parentNode.id, previous: null }];
            if (firstChild) {
                movedBookmarksWithParent = [...movedBookmarksWithParent, { ...firstChild, previous: fromNode.id }];
            }
            let fromNodeSibling = this.getSiblingFromAllSibliings(fromNodeSiblings, fromIndex + 1);
            const nextFromindexforParent = fromIndex + 1;
            fromNodeSibling = fromNodeSibling && fromNodeSibling.id === fromNode.previous ? this.getSiblingFromAllSibliings(fromNodeSiblings, nextFromindexforParent + 1) : fromNodeSibling;
            if (fromNodeSibling && fromNodeSibling.id !== parentNode.id) {
                movedBookmarksWithParent = [...movedBookmarksWithParent, { ...fromNodeSibling, previous: fromNode.previous }];
            }
            let previousSiblingForParentIndex = toIndex - 1;
            let parentNodeSibling = this.getSiblingFromAllSibliings(toNodeSiblings, previousSiblingForParentIndex);
            if (parentNodeSibling && parentNodeSibling.id == fromNode.id) {
                previousSiblingForParentIndex = previousSiblingForParentIndex - 1;
                if (previousSiblingForParentIndex >= 0) {
                    parentNodeSibling = this.getSiblingFromAllSibliings(toNodeSiblings, previousSiblingForParentIndex);
                }
                else {
                    parentNodeSibling = null;
                }
            }
            movedBookmarksWithParent = [...movedBookmarksWithParent, { ...parentNode, previous: parentNodeSibling?.id }];
            const hasParentDups = movedBookmarksWithParent.map(x => x.id).some(function (value, index, array) {
                return array.indexOf(value) !== array.lastIndexOf(value); // comparing first and last indexes of the same value
            });
            if (hasParentDups || movedBookmarksWithParent && movedBookmarksWithParent.length <= 1)
                return;
            this.store.dispatch(new MoveBookmark(movedBookmarksWithParent));
            return;
        }
        if (!toNodeSiblings)
            return;
        const fromNodePrevious = hasMovedUpTheTree ? toNode.previous : toNode.id;
        let movedBookmarks = [{
                ...fromNode,
                previous: toNode.index > 0 ? fromNodePrevious : undefined,
                parent: toNodeParent
            }];
        let fromNodeSibling = this.getSiblingFromAllSibliings(fromNodeSiblings, fromIndex + 1);
        const nextFromindex = fromIndex + 1;
        fromNodeSibling = fromNodeSibling && fromNodeSibling.id === fromNode.previous ? this.getSiblingFromAllSibliings(fromNodeSiblings, nextFromindex + 1) : fromNodeSibling;
        if (fromNodeSibling) {
            movedBookmarks = [...movedBookmarks, { ...fromNodeSibling, previous: fromNode.previous }];
        }
        let toNodeSiblingIndex = hasMovedUpTheTree ? toIndex : toIndex + 1;
        let toNodeSibling = this.getSiblingFromAllSibliings(toNodeSiblings, toNodeSiblingIndex);
        if (toNodeSibling) {
            movedBookmarks = [...movedBookmarks, { ...toNodeSibling, previous: fromNode.id }];
        }
        const hasDups = movedBookmarks.map(x => x.id).some(function (value, index, array) {
            return array.indexOf(value) !== array.lastIndexOf(value); // comparing first and last indexes of the same value
        });
        if (hasDups || movedBookmarks && movedBookmarks.length <= 1)
            return;
        this.store.dispatch(new MoveBookmark(movedBookmarks));
    }
    getSiblingFromAllSibliings(sibling, index) {
        return sibling.length > index ? sibling[index] : undefined;
    }
    dragStart() {
        this.dragNodeInsertToParent = false;
        this.hoveredNode = null;
        this.isUserdragging = true;
    }
    dragEnd() {
        this.isUserdragging = false;
        if (this.hoverHtmlElement?.style) {
            this.hoverHtmlElement.style.borderRight = '';
        }
    }
    dragHover(event, node) {
        if (this.isUserdragging) {
            const newEvent = event;
            const percentageX = newEvent.offsetX / newEvent.target.clientWidth;
            if (percentageX > .55) {
                this.hoveredNode = node;
                if (this.hoverHtmlElement?.style) {
                    this.hoverHtmlElement.style.borderRight = '';
                }
                this.hoverHtmlElement = event.currentTarget;
                this.hoverHtmlElement.style.borderRight = '5px solid #007bff';
                this.dragNodeInsertToParent = true;
            }
            else {
                this.hoveredNode = null;
                if (this.hoverHtmlElement?.style) {
                    this.hoverHtmlElement.style.borderRight = '';
                }
                this.dragNodeInsertToParent = false;
            }
        }
    }
    dragHoverEnd(event, node) {
        if (this.isUserdragging) {
            if (!node || this.hoveredNode?.id !== node.id) {
                this.dragNodeInsertToParent = false;
                if (this.hoverHtmlElement?.style) {
                    this.hoverHtmlElement.style.borderRight = '';
                }
                this.hoveredNode = null;
            }
        }
    }
    onNodeExpand(node) {
        const isExpanded = this.treeControl.isExpanded(node);
        return isExpanded ? "toggle-children-wrapper-expanded" : "toggle-children-wrapper-collapsed";
    }
    visibleNodes(bookmarks) {
        const result = [];
        function addExpandedChildren(node, expanded) {
            result.push(node);
            if (expanded.some(bookmark => bookmark && bookmark.id === node.id) && node.children) {
                node.children.map((child) => addExpandedChildren(child, expanded));
            }
        }
        bookmarks.forEach((node) => {
            addExpandedChildren(node, this.treeControl.expansionModel.selected);
        });
        return result;
    }
    findNodeSiblings(arr, id) {
        let result, subResult;
        arr.forEach((item, i) => {
            if (item.id === id) {
                result = arr;
            }
            else if (item?.children) {
                subResult = this.findNodeSiblings(item.children, id);
                if (subResult)
                    result = subResult;
            }
        });
        return result;
    }
    rebuildTreeForData(data) {
        this._bookmarkNodes = data ?? [];
        this.datasource = new ArrayDataSource(this._bookmarkNodes);
        this.treeControl = new NestedTreeControl(node => node.children);
        this.treeControl.dataNodes = this._bookmarkNodes;
        this.expansionModel.selected.forEach((bookmark) => {
            const node = this.treeControl.dataNodes.find((n) => n.id === bookmark.id);
            this.treeControl.expand(node);
        });
        this.treeHasChanged.emit(true);
    }
    isToNodeChildOfFromNode(fromNodeChildren, toNode) {
        if (!fromNodeChildren) {
            return false;
        }
        const result = this.getNode(fromNodeChildren, toNode.id);
        return result ? true : false;
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BookmarksComponent, deps: [{ token: i1.Store }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: BookmarksComponent, selector: "mv-bookmarks", inputs: { bookmarkNodes: "bookmarkNodes", zoom: "zoom", rotate: "rotate", parentScrollTop: "parentScrollTop" }, outputs: { goToDestination: "goToDestination", treeHasChanged: "treeHasChanged" }, usesOnChanges: true, ngImport: i0, template: "<a *ngIf=\"bookmarkNodes?.length === 0\" class=\"highlightedOutlineItem\"\n  >No bookmarks created yet</a\n>\n<cdk-tree\n  cdkDropList\n  [cdkDropListDisabled]=\"!isDraggingOn\"\n  class=\"bookmarks-tree\"\n  *ngIf=\"datasource\"\n  [dataSource]=\"datasource\"\n  [treeControl]=\"treeControl\"\n  (cdkDropListDropped)=\"drop($event)\"\n>\n  <!-- This is the tree node template for leaf nodes -->\n  <cdk-nested-tree-node class=\"node-wrapper\" *cdkTreeNodeDef=\"let node\">\n    <div *ngIf=\"node.id !== editableBookmark; else inputBookmark\">\n      <div\n        class=\"node-content-wrapper nested-tree-node nest-tree-node-padding\"\n        cdkDrag\n        cdkDragBoundary=\".bookmarks-tree\"\n        [cdkDragData]=\"node\"\n        (mouseenter)=\"dragHover($event, node)\"\n        (mouseleave)=\"dragHoverEnd($event, node)\"\n        (cdkDragStarted)=\"dragStart()\"\n        (cdkDragReleased)=\"dragEnd()\"\n      >\n        <div class=\"outlineItem\">\n          <a (click)=\"goToBookmark(node)\">\n            {{ node.name }}\n          </a>\n        </div>\n        <button\n          class=\"bookmark__rename\"\n          (click)=\"editBookmark(node.id)\"\n        ></button>\n        <button\n          class=\"bookmark__delete\"\n          (click)=\"deleteBookmark2(node)\"\n        ></button>\n      </div>\n      <!-- <div class=\"node-drop-slot\"></div> -->\n    </div>\n    <ng-template #inputBookmark>\n      <input\n        #bookmarkName\n        class=\"bookmark__input\"\n        [value]=\"node.name\"\n        [maxLength]=\"BOOKMARK_CHAR_LIMIT\"\n      />\n      <button\n        class=\"bookmark__save\"\n        (click)=\"updateBookmark(node, bookmarkName.value)\"\n      ></button>\n    </ng-template>\n  </cdk-nested-tree-node>\n  <!-- This is the tree node template for expandable nodes -->\n  <cdk-nested-tree-node\n    class=\"node-wrapper\"\n    *cdkTreeNodeDef=\"let node; when: hasChild\"\n  >\n    <div *ngIf=\"node.id !== editableBookmark; else inputBookmark2\">\n      <div\n        class=\"node-content-wrapper nested-tree-node\"\n        cdkDrag\n        [cdkDragData]=\"node\"\n        (mouseenter)=\"dragHover($event, node)\"\n        (mouseleave)=\"dragHoverEnd($event, node)\"\n        (cdkDragStarted)=\"dragStart()\"\n        (cdkDragReleased)=\"dragEnd()\"\n      >\n        <div class=\"outlineItem\">\n          <span\n            cdkTreeNodeToggle\n            class=\"toggle-children-wrapper\"\n            [ngClass]=\"onNodeExpand(node)\"\n            ><span class=\"toggle-children\"></span\n          ></span>\n          <a (click)=\"goToBookmark(node)\">\n            {{ node.name }}\n          </a>\n        </div>\n        <button\n          class=\"bookmark__rename\"\n          (click)=\"editBookmark(node.id)\"\n        ></button>\n        <button\n          class=\"bookmark__delete\"\n          (click)=\"deleteBookmark2(node)\"\n        ></button>\n      </div>\n      <!-- <div class=\"node-drop-slot\"></div> -->\n    </div>\n    <ng-template #inputBookmark2>\n      <input\n        #bookmarkName\n        class=\"bookmark__input\"\n        [value]=\"node.name\"\n        [maxLength]=\"BOOKMARK_CHAR_LIMIT\"\n      />\n      <button\n        class=\"bookmark__save\"\n        (click)=\"updateBookmark(node, bookmarkName.value)\"\n      ></button>\n    </ng-template>\n    <div class=\"nested-tree-node-children\" *ngIf=\"treeControl.isExpanded(node)\">\n      <ng-container cdkTreeNodeOutlet></ng-container>\n    </div>\n  </cdk-nested-tree-node>\n</cdk-tree>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.CdkNestedTreeNode, selector: "cdk-nested-tree-node", exportAs: ["cdkNestedTreeNode"] }, { kind: "directive", type: i3$1.CdkTreeNodeDef, selector: "[cdkTreeNodeDef]", inputs: ["cdkTreeNodeDefWhen"] }, { kind: "directive", type: i3$1.CdkTreeNodeToggle, selector: "[cdkTreeNodeToggle]", inputs: ["cdkTreeNodeToggleRecursive"] }, { kind: "component", type: i3$1.CdkTree, selector: "cdk-tree", inputs: ["dataSource", "treeControl", "trackBy"], exportAs: ["cdkTree"] }, { kind: "directive", type: i3$1.CdkTreeNodeOutlet, selector: "[cdkTreeNodeOutlet]" }, { kind: "directive", type: i4$2.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i4$2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BookmarksComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-bookmarks', template: "<a *ngIf=\"bookmarkNodes?.length === 0\" class=\"highlightedOutlineItem\"\n  >No bookmarks created yet</a\n>\n<cdk-tree\n  cdkDropList\n  [cdkDropListDisabled]=\"!isDraggingOn\"\n  class=\"bookmarks-tree\"\n  *ngIf=\"datasource\"\n  [dataSource]=\"datasource\"\n  [treeControl]=\"treeControl\"\n  (cdkDropListDropped)=\"drop($event)\"\n>\n  <!-- This is the tree node template for leaf nodes -->\n  <cdk-nested-tree-node class=\"node-wrapper\" *cdkTreeNodeDef=\"let node\">\n    <div *ngIf=\"node.id !== editableBookmark; else inputBookmark\">\n      <div\n        class=\"node-content-wrapper nested-tree-node nest-tree-node-padding\"\n        cdkDrag\n        cdkDragBoundary=\".bookmarks-tree\"\n        [cdkDragData]=\"node\"\n        (mouseenter)=\"dragHover($event, node)\"\n        (mouseleave)=\"dragHoverEnd($event, node)\"\n        (cdkDragStarted)=\"dragStart()\"\n        (cdkDragReleased)=\"dragEnd()\"\n      >\n        <div class=\"outlineItem\">\n          <a (click)=\"goToBookmark(node)\">\n            {{ node.name }}\n          </a>\n        </div>\n        <button\n          class=\"bookmark__rename\"\n          (click)=\"editBookmark(node.id)\"\n        ></button>\n        <button\n          class=\"bookmark__delete\"\n          (click)=\"deleteBookmark2(node)\"\n        ></button>\n      </div>\n      <!-- <div class=\"node-drop-slot\"></div> -->\n    </div>\n    <ng-template #inputBookmark>\n      <input\n        #bookmarkName\n        class=\"bookmark__input\"\n        [value]=\"node.name\"\n        [maxLength]=\"BOOKMARK_CHAR_LIMIT\"\n      />\n      <button\n        class=\"bookmark__save\"\n        (click)=\"updateBookmark(node, bookmarkName.value)\"\n      ></button>\n    </ng-template>\n  </cdk-nested-tree-node>\n  <!-- This is the tree node template for expandable nodes -->\n  <cdk-nested-tree-node\n    class=\"node-wrapper\"\n    *cdkTreeNodeDef=\"let node; when: hasChild\"\n  >\n    <div *ngIf=\"node.id !== editableBookmark; else inputBookmark2\">\n      <div\n        class=\"node-content-wrapper nested-tree-node\"\n        cdkDrag\n        [cdkDragData]=\"node\"\n        (mouseenter)=\"dragHover($event, node)\"\n        (mouseleave)=\"dragHoverEnd($event, node)\"\n        (cdkDragStarted)=\"dragStart()\"\n        (cdkDragReleased)=\"dragEnd()\"\n      >\n        <div class=\"outlineItem\">\n          <span\n            cdkTreeNodeToggle\n            class=\"toggle-children-wrapper\"\n            [ngClass]=\"onNodeExpand(node)\"\n            ><span class=\"toggle-children\"></span\n          ></span>\n          <a (click)=\"goToBookmark(node)\">\n            {{ node.name }}\n          </a>\n        </div>\n        <button\n          class=\"bookmark__rename\"\n          (click)=\"editBookmark(node.id)\"\n        ></button>\n        <button\n          class=\"bookmark__delete\"\n          (click)=\"deleteBookmark2(node)\"\n        ></button>\n      </div>\n      <!-- <div class=\"node-drop-slot\"></div> -->\n    </div>\n    <ng-template #inputBookmark2>\n      <input\n        #bookmarkName\n        class=\"bookmark__input\"\n        [value]=\"node.name\"\n        [maxLength]=\"BOOKMARK_CHAR_LIMIT\"\n      />\n      <button\n        class=\"bookmark__save\"\n        (click)=\"updateBookmark(node, bookmarkName.value)\"\n      ></button>\n    </ng-template>\n    <div class=\"nested-tree-node-children\" *ngIf=\"treeControl.isExpanded(node)\">\n      <ng-container cdkTreeNodeOutlet></ng-container>\n    </div>\n  </cdk-nested-tree-node>\n</cdk-tree>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }], propDecorators: { bookmarkNodes: [{
                type: Input
            }], zoom: [{
                type: Input
            }], rotate: [{
                type: Input
            }], parentScrollTop: [{
                type: Input
            }], goToDestination: [{
                type: Output
            }], treeHasChanged: [{
                type: Output
            }] } });

class OutlineItemComponent {
    constructor() {
        this.navigationEvent = new EventEmitter();
    }
    ngOnInit() {
        this.showOutlineItems = true;
    }
    goToDestination(destination) {
        if (destination) {
            this.navigationEvent.emit(destination);
        }
    }
    toggleOutline() {
        this.showOutlineItems = !this.showOutlineItems;
    }
    isViewedItem(current, next) {
        if (current.pageNumber === this.currentPageNumber) {
            return true;
        }
        return next === undefined ? current.pageNumber <= this.currentPageNumber && this.endPage > this.currentPageNumber :
            current.pageNumber <= this.currentPageNumber && (next.pageNumber > this.currentPageNumber);
    }
    findEndPage(next) {
        return next === undefined ? this.endPage : next.pageNumber;
    }
    showHighlightOutlineCss() {
        return this.isCurrentSection ? 'highlightedOutlineItem' : 'outlineItem';
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OutlineItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: OutlineItemComponent, selector: "mv-outline-item", inputs: { outline: "outline", currentPageNumber: "currentPageNumber", isCurrentSection: "isCurrentSection", endPage: "endPage" }, outputs: { navigationEvent: "navigationEvent" }, ngImport: i0, template: "<div class=\"outlineItem\">\n  <div *ngIf=\"outline.items.length > 0\"\n       [ngClass]=\"{ 'outlineItemToggler': true, 'outlineItemsHidden': !showOutlineItems }\"\n       (click)=\"toggleOutline()\"\n       (keyup.enter)=\"toggleOutline()\" tabindex=\"0\"></div>\n  <a (click)=\"goToDestination(outline?.dest)\"\n     (keyup.enter)=\"goToDestination(outline?.dest)\"\n     [style.font-weight]=\"outline.bold ? 'bold' : ''\"\n     [style.font-style]=\"outline.italic ? 'italic' : ''\"\n     [ngClass]=\"showHighlightOutlineCss()\"\n     tabindex=\"0\">\n    <div style=\"text-align:left;\" [ngClass]=\"showHighlightOutlineCss()\">\n      {{ outline.title }}\n      <span style=\"float:right;\">\n        {{ outline.pageNumber }}\n      </span>\n    </div>\n  </a>\n  \n  <div *ngIf=\"outline.items.length > 0\" class=\"outlineItems\">\n    <div *ngFor=\"let outlineItem of outline.items; index as i\">\n      <mv-outline-item\n        [outline]=\"outlineItem\" \n        [currentPageNumber]= \"currentPageNumber\" \n        [isCurrentSection]= \"isViewedItem(outlineItem, outline.items[i+1])\"\n        [endPage]=\"findEndPage(outline.items[i+1])\"\n        (navigationEvent)=\"goToDestination($event)\">\n      </mv-outline-item>\n    </div>\n  </div>\n</div>\n\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: OutlineItemComponent, selector: "mv-outline-item", inputs: ["outline", "currentPageNumber", "isCurrentSection", "endPage"], outputs: ["navigationEvent"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OutlineItemComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-outline-item', template: "<div class=\"outlineItem\">\n  <div *ngIf=\"outline.items.length > 0\"\n       [ngClass]=\"{ 'outlineItemToggler': true, 'outlineItemsHidden': !showOutlineItems }\"\n       (click)=\"toggleOutline()\"\n       (keyup.enter)=\"toggleOutline()\" tabindex=\"0\"></div>\n  <a (click)=\"goToDestination(outline?.dest)\"\n     (keyup.enter)=\"goToDestination(outline?.dest)\"\n     [style.font-weight]=\"outline.bold ? 'bold' : ''\"\n     [style.font-style]=\"outline.italic ? 'italic' : ''\"\n     [ngClass]=\"showHighlightOutlineCss()\"\n     tabindex=\"0\">\n    <div style=\"text-align:left;\" [ngClass]=\"showHighlightOutlineCss()\">\n      {{ outline.title }}\n      <span style=\"float:right;\">\n        {{ outline.pageNumber }}\n      </span>\n    </div>\n  </a>\n  \n  <div *ngIf=\"outline.items.length > 0\" class=\"outlineItems\">\n    <div *ngFor=\"let outlineItem of outline.items; index as i\">\n      <mv-outline-item\n        [outline]=\"outlineItem\" \n        [currentPageNumber]= \"currentPageNumber\" \n        [isCurrentSection]= \"isViewedItem(outlineItem, outline.items[i+1])\"\n        [endPage]=\"findEndPage(outline.items[i+1])\"\n        (navigationEvent)=\"goToDestination($event)\">\n      </mv-outline-item>\n    </div>\n  </div>\n</div>\n\n" }]
        }], propDecorators: { outline: [{
                type: Input
            }], currentPageNumber: [{
                type: Input
            }], isCurrentSection: [{
                type: Input
            }], endPage: [{
                type: Input
            }], navigationEvent: [{
                type: Output
            }] } });

class SideBarComponent {
    constructor(viewerEvents, store, toolbarEvents) {
        this.viewerEvents = viewerEvents;
        this.store = store;
        this.toolbarEvents = toolbarEvents;
        this.treeChanged = false;
        this.selectedView = 'outline';
        this.subscriptions = [];
    }
    ngOnInit() {
        this.bookmarkNodes$ = this.store.pipe(select(getBookmarkNodes));
        this.subscriptions.push(this.store.pipe(select(getEditableBookmark))
            .subscribe(editable => this.selectedView = editable ? 'bookmarks' : this.selectedView));
        this.subscriptions.push(this.toolbarEvents.sidebarOutlineView.subscribe(toggle => {
            this.selectedView = toggle ? 'outline' : 'bookmarks';
        }), this.toolbarEvents.sidebarOpen.subscribe(toggle => {
            this.sidebarOpen = toggle;
        }));
        this.subscriptions.push(this.store.pipe(select(getScrollTop)).subscribe(scrollTopValue => {
            if (this.sidebarDiv?.nativeElement) {
                this.sidebarDiv.nativeElement.scrollTop = scrollTopValue;
            }
        }));
    }
    ngOnChanges(changes) {
        if (changes.url && this.url) {
            this.store.dispatch(new LoadBookmarks());
        }
    }
    ngOnDestroy() {
        if (this.subscriptions.length > 0) {
            this.subscriptions.forEach(subscription => subscription.unsubscribe());
        }
    }
    onScroll(event) {
        if (!this.treeChanged) {
            this.scrollTop = event.srcElement.scrollTop;
        }
        this.treeChanged = false;
    }
    goToDestination(destination) {
        this.viewerEvents.goToDestination(destination);
    }
    hasTreeChanged(value) {
        this.treeChanged = value;
    }
    toggleSidebarView(sidebarView) {
        this.selectedView = sidebarView;
    }
    isViewedItem(current, next) {
        if (current.pageNumber === this.currentPageNumber) {
            return true;
        }
        return next === undefined ? current.pageNumber <= this.currentPageNumber :
            current.pageNumber <= this.currentPageNumber && (next.pageNumber > this.currentPageNumber);
    }
    findEndPage(next) {
        return next === undefined ? Number.MAX_SAFE_INTEGER : next.pageNumber;
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SideBarComponent, deps: [{ token: ViewerEventService }, { token: i1.Store }, { token: ToolbarEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SideBarComponent, selector: "mv-side-bar", inputs: { annotationsEnabled: "annotationsEnabled", outline: "outline", url: "url", zoom: "zoom", rotate: "rotate", currentPageNumber: "currentPageNumber" }, viewQueries: [{ propertyName: "bookmarks", first: true, predicate: BookmarksComponent, descendants: true }, { propertyName: "sidebarDiv", first: true, predicate: ["sidebar"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div id=\"toolbarSidebar\">\n  <div\n    *ngIf=\"annotationsEnabled && selectedView === 'bookmarks'\"\n    class=\"splitToolbarButton toggled\"\n  >\n    <button\n      id=\"sortBookmarkPosition\"\n      class=\"splitToolbarButton left bookmark__sort__position\"\n      (click)=\"bookmarks.sort(bookmarks.positionSort)\"\n      title=\"Order by place in document\"\n      aria-pressed=\"true\"\n    ></button>\n    <button\n      id=\"sortBookmarkCustom\"\n      class=\"splitToolbarButton left bookmark__sort__custom\"\n      (click)=\"bookmarks.sort(bookmarks.customSort)\"\n      title=\"Order manually\"\n      aria-pressed=\"true\"\n    ></button>\n  </div>\n  <div class=\"splitToolbarButtonSeparator\"></div>\n  <div\n    *ngIf=\"annotationsEnabled && selectedView === 'bookmarks'\"\n    class=\"splitToolbarButton right\"\n  >\n    <button\n      id=\"addBookmark\"\n      class=\"toolbarButton addBookmark\"\n      (click)=\"bookmarks.onAddBookmarkClick()\"\n      title=\"Add bookmark\"\n      tabindex=\"3\"\n      data-l10n-id=\"addBookmark\"\n    >\n      <span data-l10n-id=\"addBookmark_label\">{{\n        \"Add bookmark\" | rpxTranslate\n      }}</span>\n    </button>\n  </div>\n</div>\n<div #sidebar id=\"sidebarContent\" cdkScrollable (scroll)=\"onScroll($event)\" [hidden]=\"!sidebarOpen\">\n  <div id=\"outlineView\" class=\"outlineWithDeepNesting\">\n    <div class=\"outlineItem\" *ngIf=\"selectedView === 'outline'\">\n      <mv-outline-item\n        *ngFor=\"let outlineItem of outline; index as i\"\n        [outline]=\"outlineItem\"\n        [currentPageNumber]=\"currentPageNumber\"\n        [isCurrentSection]=\"isViewedItem(outlineItem, outline[i + 1])\"\n        [endPage]=\"findEndPage(outline[i + 1])\"\n        (navigationEvent)=\"goToDestination($event)\"\n      ></mv-outline-item>\n    </div>\n    <div\n      *ngIf=\"annotationsEnabled && selectedView === 'bookmarks'\"\n      id=\"bookmarkContainer\"\n    >\n      <mv-bookmarks\n        [bookmarkNodes]=\"bookmarkNodes$ | async\"\n        [zoom]=\"zoom\"\n        [rotate]=\"rotate\"\n        [parentScrollTop]=\"scrollTop\"\n        (goToDestination)=\"goToDestination($event)\"\n        (treeHasChanged)=\"hasTreeChanged($event)\"\n      ></mv-bookmarks>\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5$2.CdkScrollable, selector: "[cdk-scrollable], [cdkScrollable]" }, { kind: "component", type: BookmarksComponent, selector: "mv-bookmarks", inputs: ["bookmarkNodes", "zoom", "rotate", "parentScrollTop"], outputs: ["goToDestination", "treeHasChanged"] }, { kind: "component", type: OutlineItemComponent, selector: "mv-outline-item", inputs: ["outline", "currentPageNumber", "isCurrentSection", "endPage"], outputs: ["navigationEvent"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5$1.RpxTranslatePipe, name: "rpxTranslate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SideBarComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-side-bar', template: "<div id=\"toolbarSidebar\">\n  <div\n    *ngIf=\"annotationsEnabled && selectedView === 'bookmarks'\"\n    class=\"splitToolbarButton toggled\"\n  >\n    <button\n      id=\"sortBookmarkPosition\"\n      class=\"splitToolbarButton left bookmark__sort__position\"\n      (click)=\"bookmarks.sort(bookmarks.positionSort)\"\n      title=\"Order by place in document\"\n      aria-pressed=\"true\"\n    ></button>\n    <button\n      id=\"sortBookmarkCustom\"\n      class=\"splitToolbarButton left bookmark__sort__custom\"\n      (click)=\"bookmarks.sort(bookmarks.customSort)\"\n      title=\"Order manually\"\n      aria-pressed=\"true\"\n    ></button>\n  </div>\n  <div class=\"splitToolbarButtonSeparator\"></div>\n  <div\n    *ngIf=\"annotationsEnabled && selectedView === 'bookmarks'\"\n    class=\"splitToolbarButton right\"\n  >\n    <button\n      id=\"addBookmark\"\n      class=\"toolbarButton addBookmark\"\n      (click)=\"bookmarks.onAddBookmarkClick()\"\n      title=\"Add bookmark\"\n      tabindex=\"3\"\n      data-l10n-id=\"addBookmark\"\n    >\n      <span data-l10n-id=\"addBookmark_label\">{{\n        \"Add bookmark\" | rpxTranslate\n      }}</span>\n    </button>\n  </div>\n</div>\n<div #sidebar id=\"sidebarContent\" cdkScrollable (scroll)=\"onScroll($event)\" [hidden]=\"!sidebarOpen\">\n  <div id=\"outlineView\" class=\"outlineWithDeepNesting\">\n    <div class=\"outlineItem\" *ngIf=\"selectedView === 'outline'\">\n      <mv-outline-item\n        *ngFor=\"let outlineItem of outline; index as i\"\n        [outline]=\"outlineItem\"\n        [currentPageNumber]=\"currentPageNumber\"\n        [isCurrentSection]=\"isViewedItem(outlineItem, outline[i + 1])\"\n        [endPage]=\"findEndPage(outline[i + 1])\"\n        (navigationEvent)=\"goToDestination($event)\"\n      ></mv-outline-item>\n    </div>\n    <div\n      *ngIf=\"annotationsEnabled && selectedView === 'bookmarks'\"\n      id=\"bookmarkContainer\"\n    >\n      <mv-bookmarks\n        [bookmarkNodes]=\"bookmarkNodes$ | async\"\n        [zoom]=\"zoom\"\n        [rotate]=\"rotate\"\n        [parentScrollTop]=\"scrollTop\"\n        (goToDestination)=\"goToDestination($event)\"\n        (treeHasChanged)=\"hasTreeChanged($event)\"\n      ></mv-bookmarks>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: ViewerEventService }, { type: i1.Store }, { type: ToolbarEventService }], propDecorators: { annotationsEnabled: [{
                type: Input
            }], outline: [{
                type: Input
            }], url: [{
                type: Input
            }], zoom: [{
                type: Input
            }], rotate: [{
                type: Input
            }], currentPageNumber: [{
                type: Input
            }], bookmarks: [{
                type: ViewChild,
                args: [BookmarksComponent]
            }], sidebarDiv: [{
                type: ViewChild,
                args: ['sidebar']
            }] } });

class GrabNDragDirective {
    constructor(el) {
        this.el = el;
        this.pointerDown = false;
        this.dragEnabled = false;
    }
    onPointerDown(event) {
        if (this.dragEnabled) {
            event.preventDefault();
            this.pointerDown = true;
            this.originalPosition = {
                left: event.clientX + this.el.nativeElement.scrollLeft,
                top: event.clientY + this.el.nativeElement.scrollTop,
            };
        }
    }
    onPointerMove(event) {
        if (this.pointerDown && this.dragEnabled) {
            event.preventDefault();
            const scrollDiff = {
                left: this.originalPosition.left - (event.clientX + this.el.nativeElement.scrollLeft),
                top: this.originalPosition.top - (event.clientY + this.el.nativeElement.scrollTop)
            };
            if (this.dragEnabled) {
                this.dragX.scrollLeft += scrollDiff.left;
                this.el.nativeElement.scrollTop += scrollDiff.top;
            }
        }
    }
    onWindowPointerUp() {
        this.pointerDown = false;
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GrabNDragDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
    /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: GrabNDragDirective, selector: "[mvGrabNDrag]", inputs: { dragEnabled: "dragEnabled", dragX: "dragX" }, host: { listeners: { "pointerdown": "onPointerDown($event)", "window:pointermove": "onPointerMove($event)", "window:pointerup": "onWindowPointerUp()" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GrabNDragDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[mvGrabNDrag]'
                }]
        }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { dragEnabled: [{
                type: Input
            }], dragX: [{
                type: Input
            }], onPointerDown: [{
                type: HostListener,
                args: ['pointerdown', ['$event']]
            }], onPointerMove: [{
                type: HostListener,
                args: ['window:pointermove', ['$event']]
            }], onWindowPointerUp: [{
                type: HostListener,
                args: ['window:pointerup']
            }] } });

class HighlightCreateDirective {
    constructor(element, toolbarEvents, viewerEvents, highlightService, store) {
        this.element = element;
        this.toolbarEvents = toolbarEvents;
        this.viewerEvents = viewerEvents;
        this.highlightService = highlightService;
        this.store = store;
    }
    ngOnInit() {
        this.$subscription = this.store.select(getPages).subscribe((pages) => {
            if (pages[1]) {
                this.allPages = pages;
            }
        });
    }
    ngOnDestroy() {
        if (this.$subscription) {
            this.$subscription.unsubscribe();
        }
    }
    onMouseUp(mouseEvent) {
        let page;
        let currentElement = mouseEvent.target;
        while (currentElement.offsetParent) {
            currentElement = currentElement.offsetParent;
            if (currentElement.getAttribute) {
                page = parseInt(currentElement.getAttribute('data-page-number'), 10);
                if (page) {
                    break;
                }
            }
        }
        if (this.toolbarEvents.highlightModeSubject.getValue()) {
            const rectangles = this.getRectangles(mouseEvent, page);
            this.viewerEvents.textSelected({ page, rectangles });
        }
    }
    onPdfViewerClick(event) {
        this.store.dispatch(new SelectedAnnotation({
            annotationId: '',
            selected: false,
            editable: false,
        }));
        this.viewerEvents.clearCtxToolbar();
    }
    getRectangles(event, page) {
        this.pageHeight = this.allPages[page].styles.height;
        this.pageWidth = this.allPages[page].styles.width;
        this.zoom = parseFloat(this.allPages[page].scaleRotation.scale);
        this.rotate = parseInt(this.allPages[page].scaleRotation.rotation, 10);
        const selection = window.getSelection();
        if (selection) {
            const localElement = event.target;
            this.removeEnhancedTextModeStyling(localElement);
            if (selection.rangeCount && !selection.isCollapsed) {
                const range = selection.getRangeAt(0).cloneRange();
                const clientRects = range.getClientRects();
                if (clientRects) {
                    const parentRect = HtmlTemplatesHelper
                        .getAdjustedBoundingRect(localElement.closest(".textLayer"));
                    const selectionRectangles = [];
                    for (let i = 0; i < clientRects.length; i++) {
                        const selectionRectangle = this.createTextRectangle(clientRects[i], parentRect);
                        const findSelecttionRectangle = selectionRectangles.find((rect) => rect.width === selectionRectangle.width && rect.x === selectionRectangle.x);
                        if (!findSelecttionRectangle) {
                            selectionRectangles.push(selectionRectangle);
                        }
                    }
                    return selectionRectangles;
                }
            }
        }
    }
    createTextRectangle(rect, parentRect) {
        const height = rect.bottom - rect.top;
        const width = rect.right - rect.left;
        const top = rect.top - parentRect.top;
        const left = rect.left - parentRect.left;
        let rectangle = this.highlightService.applyRotation(this.pageHeight, this.pageWidth, height, width, top, left, this.rotate, this.zoom);
        rectangle = { id: v4(), ...rectangle };
        return rectangle;
    }
    removeEnhancedTextModeStyling(element) {
        if (element.parentElement.children) {
            for (let i = 0; i < element.parentElement.children.length; i++) {
                const child = element.parentElement.children[i];
                child.style.padding = '0';
                // regex will be targeting the translate style in string
                // e.g. scaleX(0.969918) translateX(-110.684px) translateY(-105.274px) will become scaleX(0.969918)
                const translateCSSRegex = /translate[XYZ]\(-?\d*(\.\d+)?(px)?\)/g;
                child.style.transform = child.style.transform.replace(translateCSSRegex, '').trim();
            }
        }
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HighlightCreateDirective, deps: [{ token: i0.ElementRef }, { token: ToolbarEventService }, { token: ViewerEventService }, { token: HighlightCreateService }, { token: i1.Store }], target: i0.ɵɵFactoryTarget.Directive }); }
    /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: HighlightCreateDirective, selector: "[mvCreateTextHighlight]", host: { listeners: { "mouseup": "onMouseUp($event)", "mousedown": "onPdfViewerClick($event)" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HighlightCreateDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[mvCreateTextHighlight]'
                }]
        }], ctorParameters: () => [{ type: i0.ElementRef }, { type: ToolbarEventService }, { type: ViewerEventService }, { type: HighlightCreateService }, { type: i1.Store }], propDecorators: { onMouseUp: [{
                type: HostListener,
                args: ['mouseup', ['$event']]
            }], onPdfViewerClick: [{
                type: HostListener,
                args: ['mousedown', ['$event']]
            }] } });

const getRedactionState = createSelector(getMVState, (state) => state.redactions);
const getRedactionPages = createSelector(getRedactionState, getPageEnt);
const getSelected = createSelector(getRedactionState, getSelectedRedaction);
const getRedactedDocumentInfo = createSelector(getRedactionState, getRedactedDocInfo);
const getRedactionEnt = createSelector(getRedactionState, getRedactionEnt$1);
const getRedactionArray = createSelector(getRedactionEnt, getDocumentId, (ent, documentId) => {
    const redactions = Object.keys(ent).map(key => ent[key]);
    return { redactions, documentId };
});
const getRedactionsPerPage = createSelector(getPages, getRedactionPages, (pages, pageEnt) => {
    if (pages && pageEnt) {
        const arr = [];
        Object.keys(pages).forEach(key => {
            arr.push({
                anno: pageEnt[key] ? pageEnt[key] : [],
                styles: pages[key].styles
            });
        });
        return arr;
    }
});

class RedactionComponent {
    constructor(store, viewerEvents, toolbarEvents) {
        this.store = store;
        this.viewerEvents = viewerEvents;
        this.toolbarEvents = toolbarEvents;
    }
    ngOnInit() {
        this.redactionsPerPage$ = this.store.pipe(select(getRedactionsPerPage));
        this.selectedRedaction$ = this.store.pipe(select(getSelected));
        this.$subscription = this.toolbarEvents.drawModeSubject.subscribe(drawMode => this.drawMode = drawMode);
        this.$subscription.add(this.store.pipe(select(getRedactedDocumentInfo), filter(value => !!value))
            .subscribe(redactedDocInfo => this.downloadDocument(redactedDocInfo)));
        this.$subscription.add(this.store.pipe(select(getDocumentId)).subscribe(docId => this.documentId = docId));
        this.$subscription.add(this.viewerEvents.textHighlight.subscribe(highlight => this.markTextRedaction(highlight)));
        this.toolbarEvents.applyRedactToDocument.subscribe(() => {
            this.store.pipe(select(getRedactionArray), take(1)).subscribe(redactions => {
                this.store.dispatch(new Redact(redactions));
            });
        });
        this.toolbarEvents.clearAllRedactMarkers.subscribe(() => {
            this.store.dispatch(new UnmarkAll(this.documentId));
        });
    }
    ngOnDestroy() {
        this.$subscription.unsubscribe();
    }
    markTextRedaction(highlight) {
        const redactionHighlight = highlight.rectangles;
        if (redactionHighlight && redactionHighlight.length) {
            this.saveRedaction(highlight.page, [...redactionHighlight]);
        }
        this.toolbarEvents.highlightModeSubject.next(false);
    }
    markBoxRedaction({ rectangles, page }) {
        this.saveRedaction(page, rectangles);
        this.toolbarEvents.drawModeSubject.next(false);
    }
    saveRedaction(page, rectangles) {
        const redaction = { page, rectangles, redactionId: v4(), documentId: this.documentId };
        this.store.dispatch(new SaveRedaction(redaction));
    }
    onMarkerDelete(event) {
        this.store.dispatch(new DeleteRedaction(event));
    }
    selectRedaction(event) {
        this.store.dispatch(new SelectRedaction(event));
    }
    onMarkerUpdate(redaction) {
        this.store.dispatch(new SaveRedaction(redaction));
    }
    downloadDocument({ blob, filename }) {
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        document.body.appendChild(a);
        a.setAttribute('style', 'display: none');
        a.href = url;
        a.download = filename;
        a.click();
        a.remove();
        URL.revokeObjectURL(url);
        this.store.dispatch(new ResetRedactedDocument());
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedactionComponent, deps: [{ token: i1.Store }, { token: ViewerEventService }, { token: ToolbarEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: RedactionComponent, selector: "mv-redactions", inputs: { zoom: "zoom", rotate: "rotate" }, ngImport: i0, template: "<div class=\"pageContainer\">\n  <div *ngFor=\"let redaction of (redactionsPerPage$ | async);  index as i\"\n       class=\"pageContainer__page\"\n       [ngStyle]=\"{\n       'width.px': redaction.styles.width,\n       'height.px': redaction.styles.height\n       }\"\n       [ngClass]=\"{ 'pageContainer__page--draw' : drawMode }\">\n    <mv-box-highlight-create\n      [page]=\"i + 1\"\n      [pageHeight]=\"redaction.styles.height\"\n      [pageWidth]=\"redaction.styles.width\"\n      [rotate]=\"rotate\"\n      [zoom]=\"zoom\"\n      (saveSelection)=\"markBoxRedaction($event)\">\n    </mv-box-highlight-create>\n    <div class=\"pageContainer__page-item\">\n      <ng-container *ngFor=\"let anno of redaction.anno\">\n        <!--  TODO rename this to selection -->\n        <mv-annotation [annotation]=\"anno\"\n                       [zoom]=\"zoom\"\n                       [rotate]=\"rotate\"\n                       [selectedAnnoId]=\"selectedRedaction$ | async\"\n                       [pageHeight]=\"redaction.styles.height\"\n                       [pageWidth]=\"redaction.styles.width\"\n                       (update)=\"onMarkerUpdate($event)\"\n                       (delete)=\"onMarkerDelete($event)\"\n                       (annotationClick)=\"selectRedaction($event)\">\n        </mv-annotation>\n      </ng-container>\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: AnnotationViewComponent, selector: "mv-annotation", inputs: ["annotation", "zoom", "rotate", "selectedAnnoId", "pageHeight", "pageWidth"], outputs: ["update", "delete", "annotationClick"] }, { kind: "component", type: BoxHighlightCreateComponent, selector: "mv-box-highlight-create", inputs: ["page", "pageHeight", "pageWidth", "rotate", "zoom", "container"], outputs: ["saveSelection"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedactionComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-redactions', template: "<div class=\"pageContainer\">\n  <div *ngFor=\"let redaction of (redactionsPerPage$ | async);  index as i\"\n       class=\"pageContainer__page\"\n       [ngStyle]=\"{\n       'width.px': redaction.styles.width,\n       'height.px': redaction.styles.height\n       }\"\n       [ngClass]=\"{ 'pageContainer__page--draw' : drawMode }\">\n    <mv-box-highlight-create\n      [page]=\"i + 1\"\n      [pageHeight]=\"redaction.styles.height\"\n      [pageWidth]=\"redaction.styles.width\"\n      [rotate]=\"rotate\"\n      [zoom]=\"zoom\"\n      (saveSelection)=\"markBoxRedaction($event)\">\n    </mv-box-highlight-create>\n    <div class=\"pageContainer__page-item\">\n      <ng-container *ngFor=\"let anno of redaction.anno\">\n        <!--  TODO rename this to selection -->\n        <mv-annotation [annotation]=\"anno\"\n                       [zoom]=\"zoom\"\n                       [rotate]=\"rotate\"\n                       [selectedAnnoId]=\"selectedRedaction$ | async\"\n                       [pageHeight]=\"redaction.styles.height\"\n                       [pageWidth]=\"redaction.styles.width\"\n                       (update)=\"onMarkerUpdate($event)\"\n                       (delete)=\"onMarkerDelete($event)\"\n                       (annotationClick)=\"selectRedaction($event)\">\n        </mv-annotation>\n      </ng-container>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: ViewerEventService }, { type: ToolbarEventService }], propDecorators: { zoom: [{
                type: Input
            }], rotate: [{
                type: Input
            }] } });

class BookmarkIconsComponent {
    constructor(store) {
        this.store = store;
    }
    ngOnInit() {
        this.bookmarksPerPage$ = this.store.pipe(select(getBookmarksPerPage));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BookmarkIconsComponent, deps: [{ token: i1.Store }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: BookmarkIconsComponent, selector: "mv-bookmark-icons", inputs: { zoom: "zoom", rotate: "rotate" }, ngImport: i0, template: "<div class=\"pageContainer\">\n  <div *ngFor=\"let bookmarks of (bookmarksPerPage$ | async);  index as i\"\n       class=\"pageContainer__page\"\n       [ngStyle]=\"{\n         'width.px': bookmarks.styles.width,\n         'height.px': bookmarks.styles.height\n       }\">\n    <div class=\"pageContainer__page-item\">\n      <ng-container *ngFor=\"let bMrk of bookmarks.bookmark\">\n        <div class=\"bookmark__here\"\n           [style.width]=\"16 * zoom + 'px'\"\n           [style.height]=\"24 * zoom + 'px'\"\n           [style.top]=\"bMrk.yCoordinate * zoom + 'px'\"\n           [title]=\"bMrk.name\">\n        </div>\n      </ng-container>\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BookmarkIconsComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-bookmark-icons', template: "<div class=\"pageContainer\">\n  <div *ngFor=\"let bookmarks of (bookmarksPerPage$ | async);  index as i\"\n       class=\"pageContainer__page\"\n       [ngStyle]=\"{\n         'width.px': bookmarks.styles.width,\n         'height.px': bookmarks.styles.height\n       }\">\n    <div class=\"pageContainer__page-item\">\n      <ng-container *ngFor=\"let bMrk of bookmarks.bookmark\">\n        <div class=\"bookmark__here\"\n           [style.width]=\"16 * zoom + 'px'\"\n           [style.height]=\"24 * zoom + 'px'\"\n           [style.top]=\"bMrk.yCoordinate * zoom + 'px'\"\n           [title]=\"bMrk.name\">\n        </div>\n      </ng-container>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }], propDecorators: { zoom: [{
                type: Input
            }], rotate: [{
                type: Input
            }] } });

class ParticipantsListComponent {
    constructor(toolbarEvents, store, icpEventService) {
        this.toolbarEvents = toolbarEvents;
        this.store = store;
        this.icpEventService = icpEventService;
        this.showParticipantsList = false;
    }
    ngOnInit() {
        this.participants$ = this.store.pipe(select(getParticipants));
        this.presenter$ = this.store.pipe(select(getPresenter));
        this.isPresenter$ = this.store.pipe(select(isPresenter));
        this.subscription = this.icpEventService.participantsListVisible.subscribe(isVisible => this.showParticipantsList = isVisible);
    }
    ngOnDestroy() {
        this.subscription.unsubscribe();
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ParticipantsListComponent, deps: [{ token: ToolbarEventService }, { token: i1.Store }, { token: IcpEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ParticipantsListComponent, selector: "mv-participants-list", ngImport: i0, template: "<div class=\"comments-panel comment-container icp-mode\" [ngClass]=\"{'expanded': showParticipantsList }\">\n\n  <div class=\"participant__card no-shadow\">\n    <p class=\"participant__name\">All Participants</p>\n  </div>\n\n  <div *ngIf=\"(presenter$ | async)?.username !== ''\" class=\"participant__card\">\n    <div class=\"participant__header\"> Presenting </div>\n    <p class=\"participant__name\">{{(presenter$ | async)?.username}}</p>\n  </div>\n\n  <div *ngIf=\"(participants$ | async).length > 1\" class=\"participant__card\">\n    <div class=\"participant__header\">Following</div>\n    <ng-container *ngFor=\"let participant of (participants$ | async)\">\n        <p *ngIf=\"participant.id !== (presenter$ | async)?.id\" class=\"participant__name\">{{participant.username}}</p>\n    </ng-container>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ParticipantsListComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-participants-list', template: "<div class=\"comments-panel comment-container icp-mode\" [ngClass]=\"{'expanded': showParticipantsList }\">\n\n  <div class=\"participant__card no-shadow\">\n    <p class=\"participant__name\">All Participants</p>\n  </div>\n\n  <div *ngIf=\"(presenter$ | async)?.username !== ''\" class=\"participant__card\">\n    <div class=\"participant__header\"> Presenting </div>\n    <p class=\"participant__name\">{{(presenter$ | async)?.username}}</p>\n  </div>\n\n  <div *ngIf=\"(participants$ | async).length > 1\" class=\"participant__card\">\n    <div class=\"participant__header\">Following</div>\n    <ng-container *ngFor=\"let participant of (participants$ | async)\">\n        <p *ngIf=\"participant.id !== (presenter$ | async)?.id\" class=\"participant__name\">{{participant.username}}</p>\n    </ng-container>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: i1.Store }, { type: IcpEventService }] });

class PdfViewerComponent {
    constructor(store, icpStore, pdfJsWrapperFactory, printService, toolbarEvents, viewerEvents, icpService, toolbarButtons, icpEventService) {
        this.store = store;
        this.icpStore = icpStore;
        this.pdfJsWrapperFactory = pdfJsWrapperFactory;
        this.printService = printService;
        this.toolbarEvents = toolbarEvents;
        this.viewerEvents = viewerEvents;
        this.icpService = icpService;
        this.toolbarButtons = toolbarButtons;
        this.icpEventService = icpEventService;
        this.mediaLoadStatus = new EventEmitter();
        this.pdfViewerException = new EventEmitter();
        this.documentTitle = new EventEmitter();
        this.pageHeights = [];
        this.rotation = 0;
        this.zoom = 1;
        this.loadingDocument = false;
        this.hasDifferentPageSize = false;
        this.enableGrabNDrag = false;
        this.highlightMode = toolbarEvents.highlightModeSubject.pipe(tap(() => {
            this.store.dispatch(new ClearFilterTags());
        }));
        this.drawMode = toolbarEvents.drawModeSubject;
    }
    async ngAfterContentInit() {
        this.pdfWrapper.documentLoadProgress.subscribe(v => this.onDocumentLoadProgress(v));
        this.pdfWrapper.documentLoaded.subscribe(() => this.onDocumentLoaded());
        this.pdfWrapper.documentLoadFailed.subscribe((error) => this.onDocumentLoadFailed(error));
        this.pdfWrapper.outlineLoaded.subscribe(outline => this.documentOutline = outline);
        this.pdfWrapper.pageRendered.subscribe((event) => this.updatePages(event));
        this.$subscription = this.toolbarEvents.printSubject
            .subscribe(() => this.printService.printDocumentNatively(this.url));
        this.$subscription.add(this.toolbarEvents.downloadSubject.subscribe(() => this.pdfWrapper.downloadFile(this.downloadUrl || this.url, this.downloadFileName)));
        this.$subscription.add(this.toolbarEvents.rotateSubject.subscribe(rotate => this.rotateDocument(rotate)));
        this.$subscription.add(this.toolbarEvents.zoomSubject.subscribe(zoom => this.setZoom(zoom)));
        this.$subscription.add(this.toolbarEvents.stepZoomSubject.subscribe(zoom => this.stepZoom(zoom)));
        this.$subscription.add(this.toolbarEvents.searchSubject.subscribe(search => this.pdfWrapper.search(search)));
        this.$subscription.add(this.toolbarEvents.setCurrentPageSubject.subscribe(pageNumber => this.pdfWrapper.setPageNumber(pageNumber)));
        this.$subscription.add(this.toolbarEvents.changePageByDeltaSubject.subscribe(pageNumber => this.pdfWrapper.changePageNumber(pageNumber)));
        this.$subscription.add(this.toolbarEvents.grabNDrag.subscribe(grabNDrag => this.enableGrabNDrag = grabNDrag));
        this.$subscription.add(this.toolbarEvents.commentsPanelVisible.subscribe(toggle => {
            this.showCommentsPanel = toggle;
        }));
        this.$subscription.add(this.viewerEvents.navigationEvent.subscribe(dest => this.goToDestination(dest)));
        this.$subscription.add(this.viewerEvents.navigationEventICP.subscribe(destination => this.goToDestinationICP(destination)));
        this.$subscription.add(this.icpEventService.participantsListVisible.subscribe(toggle => this.showIcpParticipantsList = toggle));
        this.$subscription.add(this.pdfWrapper.positionUpdated.asObservable()
            .pipe(throttleTime(500, asyncScheduler, { leading: true, trailing: true }))
            .subscribe(event => this.store.dispatch(new PdfPositionUpdate(event.location))));
    }
    async ngOnChanges(changes) {
        if (!this.pdfWrapper) {
            this.pdfWrapper = this.pdfJsWrapperFactory.create(this.viewerContainer);
        }
        if (changes.url && this.pdfWrapper) {
            await this.loadDocument();
            if (this.enableRedactions) {
                this.toolbarEvents.redactionMode.pipe(filter(value => !!value))
                    .subscribe(() => this.resetRotation());
            }
        }
        if (changes.caseId) {
            this.icpStore.dispatch(new SetCaseId(this.caseId));
        }
    }
    resetRotation() {
        if (this.hasDifferentPageSize) {
            this.pdfWrapper.resetRotation(0);
            this.rotation = 0;
        }
    }
    ngOnDestroy() {
        this.$subscription.unsubscribe();
    }
    async loadDocument() {
        this.initDocumentProgress();
        await this.pdfWrapper.loadDocument(this.url);
        this.documentTitle.emit(this.pdfWrapper.getCurrentPDFTitle());
        this.setPageHeights();
        this.$subscription.add(this.store.pipe(select(getPageDifference))
            .subscribe(hasDifferentPageSie => this.hasDifferentPageSize = hasDifferentPageSie));
    }
    onDocumentLoadProgress(progress) {
        if (progress.total) {
            this.loadingDocumentProgress = Math.min(100, Math.ceil(progress.loaded / progress.total * 100));
        }
    }
    onDocumentLoaded() {
        this.loadingDocument = false;
        this.mediaLoadStatus.emit(ResponseType.SUCCESS);
    }
    onDocumentLoadFailed(error) {
        this.loadingDocument = false;
        this.viewerException = new ViewerException(error.name, { message: error.message });
        this.errorMessage = `Could not load the document "${this.url}"`;
        this.mediaLoadStatus.emit(ResponseType.FAILURE);
        this.pdfViewerException.emit(this.viewerException);
    }
    updatePages(event) {
        if (this.enableAnnotations) {
            this.store.dispatch(new AddPages(event));
        }
    }
    set searchBarHidden(hidden) {
        if (this.pdfWrapper && hidden) {
            this.pdfWrapper.clearSearch();
        }
    }
    toggleCommentsSummary() {
        this.toolbarEvents.toggleCommentsSummary(!this.toolbarEvents.showCommentSummary.getValue());
    }
    rotateDocument(rotation) {
        const pageNumber = this.pdfWrapper.getPageNumber();
        this.pdfWrapper.rotate(rotation);
        this.pdfWrapper.setPageNumber(pageNumber);
        this.rotation = (this.rotation + rotation) % 360;
        this.setPageHeights();
    }
    initDocumentProgress() {
        this.loadingDocument = true;
        this.loadingDocumentProgress = null;
        this.errorMessage = null;
    }
    setZoom(zoomFactor) {
        if (!isNaN(zoomFactor)) {
            this.pdfWrapper.setZoom(zoomFactor);
            this.zoom = this.calculateZoomValue(zoomFactor);
            this.setPageHeights();
        }
    }
    stepZoom(zoomFactor) {
        if (!isNaN(zoomFactor)) {
            this.pdfWrapper.stepZoom(zoomFactor);
            this.zoom = this.calculateZoomValue(this.zoom, zoomFactor);
            this.setPageHeights();
        }
    }
    setPageHeights() {
        this.pageHeights = [];
        const pdfViewerChildren = this.pdfViewer.nativeElement.children;
        for (let i = 0; i < pdfViewerChildren.length; i++) {
            this.pageHeights.push(pdfViewerChildren[i].clientHeight);
        }
    }
    calculateZoomValue(zoomValue, increment = 0) {
        const newZoomValue = zoomValue + increment;
        if (newZoomValue > 5) {
            return 5;
        }
        if (newZoomValue < 0.1) {
            return 0.1;
        }
        return +newZoomValue.toFixed(2);
    }
    goToDestination(destination) {
        const currentRotation = this.rotation;
        this.rotateDocument(360 - this.rotation);
        this.pdfWrapper.navigateTo(destination);
        setTimeout(() => {
            this.rotateDocument(currentRotation);
        }, 10);
    }
    goToDestinationICP(destination) {
        this.pdfWrapper.nativeNavigate(destination);
    }
    getCurrentPageNumber() {
        return this.pdfWrapper.getPageNumber();
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PdfViewerComponent, deps: [{ token: i1.Store }, { token: i1.Store }, { token: PdfJsWrapperFactory }, { token: PrintService }, { token: ToolbarEventService }, { token: ViewerEventService }, { token: IcpService }, { token: ToolbarButtonVisibilityService }, { token: IcpEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: PdfViewerComponent, selector: "mv-pdf-viewer", inputs: { downloadUrl: "downloadUrl", url: "url", downloadFileName: "downloadFileName", enableAnnotations: "enableAnnotations", enableRedactions: "enableRedactions", enableICP: "enableICP", annotationSet: "annotationSet", enableRedactSearch: "enableRedactSearch", height: "height", caseId: "caseId", searchBarHidden: "searchBarHidden" }, outputs: { mediaLoadStatus: "mediaLoadStatus", pdfViewerException: "pdfViewerException", documentTitle: "documentTitle" }, viewQueries: [{ propertyName: "viewerContainer", first: true, predicate: ["viewerContainer"], descendants: true, static: true }, { propertyName: "pdfViewer", first: true, predicate: ["pdfViewer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<mv-side-bar\n  *ngIf=\"toolbarEvents.sidebarOpen\"\n  id=\"sidebarContainer\"\n  [url]=\"url\"\n  [zoom]=\"zoom\"\n  [rotate]=\"rotation\"\n  [outline]=\"documentOutline\"\n  [annotationsEnabled]=\"enableAnnotations\"\n  [currentPageNumber]=\"getCurrentPageNumber()\"\n>\n</mv-side-bar>\n<mv-comment-set-header\n  *ngIf=\"enableAnnotations\"\n  [ngClass]=\"{ 'show-comments-panel': showCommentsPanel }\"\n  [isHidden]=\"!showCommentsPanel\"\n  [showCommentSummary]=\"toolbarButtons.showCommentSummary\"\n  (showCommentSummaryDialog)=\"toggleCommentsSummary()\"\n>\n</mv-comment-set-header>\n<mv-participants-list></mv-participants-list>\n<div\n  class=\"pdfContainer\"\n  [ngStyle]=\"{ height: height }\"\n  [ngClass]=\"{ pdfContainer: true, hidden: errorMessage }\"\n>\n  <mv-redaction-search-bar></mv-redaction-search-bar>\n  <div\n    #viewerContainer\n    mvGrabNDrag\n    [dragX]=\"viewerContainer\"\n    [dragEnabled]=\"enableGrabNDrag\"\n    id=\"viewerContainer\"\n    class=\"viewer-container\"\n    [class.annotations]=\"enableAnnotations\"\n    [class.show-comments-panel]=\"\n      (showCommentsPanel || showIcpParticipantsList) &&\n      (toolbarEvents.redactionMode | async) !== true\n    \"\n    [class.grabNDrag]=\"enableGrabNDrag\"\n  >\n    <div\n      #pdfViewer\n      class=\"pdfViewer\"\n      mvCreateTextHighlight\n      [ngClass]=\"{\n        hidden: false,\n        highlightMode: highlightMode | async,\n        drawMode: drawMode | async\n      }\"\n    ></div>\n    <mv-redactions\n      *ngIf=\"toolbarEvents.redactionMode | async; else annotationTemplate\"\n      [zoom]=\"zoom\"\n      [rotate]=\"rotation\"\n    ></mv-redactions>\n    <ng-template #annotationTemplate>\n      <mv-metadata-layer\n        *ngIf=\"enableAnnotations && annotationSet\"\n        [zoom]=\"zoom\"\n        [rotate]=\"rotation\"\n      >\n      </mv-metadata-layer>\n      <mv-bookmark-icons [zoom]=\"zoom\" [rotate]=\"rotation\"> </mv-bookmark-icons>\n    </ng-template>\n  </div>\n  <mv-comment-set\n    [contentScrollTop]=\"viewerContainer.scrollTop\"\n    *ngIf=\"\n      enableAnnotations &&\n      annotationSet &&\n      (toolbarEvents.redactionMode | async) !== true\n    \"\n    [annotationSet]=\"annotationSet\"\n    [zoom]=\"zoom\"\n    [rotate]=\"rotation\"\n    [height]=\"pdfViewer.offsetHeight\"\n    [pageHeights]=\"pageHeights\"\n  >\n  </mv-comment-set>\n  <div class=\"loadingMessage\" *ngIf=\"loadingDocument\">\n    <h3 class=\"govuk-heading-m\">\n      {{ \"Loading...\" | rpxTranslate}}{{\n        loadingDocumentProgress ? loadingDocumentProgress + \"%\" : \"\"\n      }}\n    </h3>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: RedactionSearchBarComponent, selector: "mv-redaction-search-bar" }, { kind: "component", type: CommentSetComponent, selector: "mv-comment-set", inputs: ["annotationSet", "zoom", "rotate", "height", "pageHeights", "contentScrollTop"] }, { kind: "component", type: CommentSetHeaderComponent, selector: "mv-comment-set-header", inputs: ["showCommentSummary", "isHidden"], outputs: ["showCommentSummaryDialog"] }, { kind: "component", type: MetadataLayerComponent, selector: "mv-metadata-layer", inputs: ["zoom", "rotate"] }, { kind: "component", type: SideBarComponent, selector: "mv-side-bar", inputs: ["annotationsEnabled", "outline", "url", "zoom", "rotate", "currentPageNumber"] }, { kind: "directive", type: GrabNDragDirective, selector: "[mvGrabNDrag]", inputs: ["dragEnabled", "dragX"] }, { kind: "directive", type: HighlightCreateDirective, selector: "[mvCreateTextHighlight]" }, { kind: "component", type: RedactionComponent, selector: "mv-redactions", inputs: ["zoom", "rotate"] }, { kind: "component", type: BookmarkIconsComponent, selector: "mv-bookmark-icons", inputs: ["zoom", "rotate"] }, { kind: "component", type: ParticipantsListComponent, selector: "mv-participants-list" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5$1.RpxTranslatePipe, name: "rpxTranslate" }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PdfViewerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-pdf-viewer', encapsulation: ViewEncapsulation.None, template: "<mv-side-bar\n  *ngIf=\"toolbarEvents.sidebarOpen\"\n  id=\"sidebarContainer\"\n  [url]=\"url\"\n  [zoom]=\"zoom\"\n  [rotate]=\"rotation\"\n  [outline]=\"documentOutline\"\n  [annotationsEnabled]=\"enableAnnotations\"\n  [currentPageNumber]=\"getCurrentPageNumber()\"\n>\n</mv-side-bar>\n<mv-comment-set-header\n  *ngIf=\"enableAnnotations\"\n  [ngClass]=\"{ 'show-comments-panel': showCommentsPanel }\"\n  [isHidden]=\"!showCommentsPanel\"\n  [showCommentSummary]=\"toolbarButtons.showCommentSummary\"\n  (showCommentSummaryDialog)=\"toggleCommentsSummary()\"\n>\n</mv-comment-set-header>\n<mv-participants-list></mv-participants-list>\n<div\n  class=\"pdfContainer\"\n  [ngStyle]=\"{ height: height }\"\n  [ngClass]=\"{ pdfContainer: true, hidden: errorMessage }\"\n>\n  <mv-redaction-search-bar></mv-redaction-search-bar>\n  <div\n    #viewerContainer\n    mvGrabNDrag\n    [dragX]=\"viewerContainer\"\n    [dragEnabled]=\"enableGrabNDrag\"\n    id=\"viewerContainer\"\n    class=\"viewer-container\"\n    [class.annotations]=\"enableAnnotations\"\n    [class.show-comments-panel]=\"\n      (showCommentsPanel || showIcpParticipantsList) &&\n      (toolbarEvents.redactionMode | async) !== true\n    \"\n    [class.grabNDrag]=\"enableGrabNDrag\"\n  >\n    <div\n      #pdfViewer\n      class=\"pdfViewer\"\n      mvCreateTextHighlight\n      [ngClass]=\"{\n        hidden: false,\n        highlightMode: highlightMode | async,\n        drawMode: drawMode | async\n      }\"\n    ></div>\n    <mv-redactions\n      *ngIf=\"toolbarEvents.redactionMode | async; else annotationTemplate\"\n      [zoom]=\"zoom\"\n      [rotate]=\"rotation\"\n    ></mv-redactions>\n    <ng-template #annotationTemplate>\n      <mv-metadata-layer\n        *ngIf=\"enableAnnotations && annotationSet\"\n        [zoom]=\"zoom\"\n        [rotate]=\"rotation\"\n      >\n      </mv-metadata-layer>\n      <mv-bookmark-icons [zoom]=\"zoom\" [rotate]=\"rotation\"> </mv-bookmark-icons>\n    </ng-template>\n  </div>\n  <mv-comment-set\n    [contentScrollTop]=\"viewerContainer.scrollTop\"\n    *ngIf=\"\n      enableAnnotations &&\n      annotationSet &&\n      (toolbarEvents.redactionMode | async) !== true\n    \"\n    [annotationSet]=\"annotationSet\"\n    [zoom]=\"zoom\"\n    [rotate]=\"rotation\"\n    [height]=\"pdfViewer.offsetHeight\"\n    [pageHeights]=\"pageHeights\"\n  >\n  </mv-comment-set>\n  <div class=\"loadingMessage\" *ngIf=\"loadingDocument\">\n    <h3 class=\"govuk-heading-m\">\n      {{ \"Loading...\" | rpxTranslate}}{{\n        loadingDocumentProgress ? loadingDocumentProgress + \"%\" : \"\"\n      }}\n    </h3>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: i1.Store }, { type: PdfJsWrapperFactory }, { type: PrintService }, { type: ToolbarEventService }, { type: ViewerEventService }, { type: IcpService }, { type: ToolbarButtonVisibilityService }, { type: IcpEventService }], propDecorators: { mediaLoadStatus: [{
                type: Output
            }], pdfViewerException: [{
                type: Output
            }], documentTitle: [{
                type: Output
            }], downloadUrl: [{
                type: Input
            }], url: [{
                type: Input
            }], downloadFileName: [{
                type: Input
            }], enableAnnotations: [{
                type: Input
            }], enableRedactions: [{
                type: Input
            }], enableICP: [{
                type: Input
            }], annotationSet: [{
                type: Input
            }], enableRedactSearch: [{
                type: Input
            }], height: [{
                type: Input
            }], caseId: [{
                type: Input
            }], viewerContainer: [{
                type: ViewChild,
                args: ['viewerContainer', { static: true }]
            }], pdfViewer: [{
                type: ViewChild,
                args: ['pdfViewer', { static: false }]
            }], searchBarHidden: [{
                type: Input
            }] } });

class ViewerUtilService {
    constructor(http) {
        this.http = http;
    }
    validateFile(url) {
        return this.http.head(url);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ViewerUtilService, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ViewerUtilService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ViewerUtilService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [{ type: i1$1.HttpClient }] });

class ImageViewerComponent {
    constructor(store, printService, viewerUtilService, toolbarEvents, toolbarButtons, viewerEvents) {
        this.store = store;
        this.printService = printService;
        this.viewerUtilService = viewerUtilService;
        this.toolbarEvents = toolbarEvents;
        this.toolbarButtons = toolbarButtons;
        this.viewerEvents = viewerEvents;
        this.mediaLoadStatus = new EventEmitter();
        this.imageViewerException = new EventEmitter();
        this.rotation = 0;
        this.zoom = 1;
        this.subscriptions = [];
        this.enableGrabNDrag = false;
    }
    ngOnInit() {
        this.subscriptions.push(this.toolbarEvents.rotateSubject.subscribe(rotation => this.rotateImage(rotation)), this.toolbarEvents.zoomSubject.subscribe(zoom => this.setZoom(zoom)), this.toolbarEvents.stepZoomSubject.subscribe(zoom => this.stepZoom(zoom)), this.toolbarEvents.printSubject.subscribe(() => this.printService.printDocumentNatively(this.url)), this.toolbarEvents.downloadSubject.subscribe(() => this.download()), this.toolbarEvents.grabNDrag.subscribe(grabNDrag => this.enableGrabNDrag = grabNDrag), this.toolbarEvents.commentsPanelVisible.subscribe(toggle => this.showCommentsPanel = toggle));
    }
    onImageViewerClick(event) {
        const classNme = event.target.className;
        if (classNme.startsWith('pageContainer')) {
            this.store.dispatch(new SelectedAnnotation({
                annotationId: '',
                selected: false,
                editable: false,
            }));
            this.viewerEvents.clearCtxToolbar();
        }
    }
    ngOnDestroy() {
        this.subscriptions.filter(subscription => !subscription.closed)
            .forEach(subscription => subscription.unsubscribe());
        if (this.response) {
            this.response.unsubscribe();
        }
    }
    ngOnChanges(changes) {
        if (changes.url) {
            this.errorMessage = null;
            this.toolbarEvents.reset();
        }
    }
    rotateImage(rotation) {
        this.rotation = (this.rotation + rotation) % 360;
        this.initAnnoPage(this.img.nativeElement);
    }
    async setZoom(zoomFactor) {
        if (!isNaN(zoomFactor)) {
            await this.setZoomValue(this.calculateZoomValue(zoomFactor));
            this.img.nativeElement.width = this.img.nativeElement.naturalWidth * this.zoom;
            this.initAnnoPage(this.img.nativeElement);
        }
    }
    async stepZoom(zoomFactor) {
        if (!isNaN(zoomFactor)) {
            await this.setZoomValue(this.calculateZoomValue(this.zoom, zoomFactor));
            this.img.nativeElement.width = this.img.nativeElement.naturalWidth * this.zoom;
            this.initAnnoPage(this.img.nativeElement);
        }
    }
    download() {
        const a = document.createElement('a');
        document.body.appendChild(a);
        a.setAttribute('style', 'display: none');
        a.href = this.url;
        a.download = this.downloadFileName;
        a.click();
        a.remove();
    }
    // the returned promise is a work-around
    setZoomValue(zoomValue) {
        return new Promise((resolve) => {
            this.zoom = zoomValue;
            this.toolbarEvents.zoomValueSubject.next(zoomValue);
            resolve(true);
        });
    }
    calculateZoomValue(zoomValue, increment = 0) {
        const newZoomValue = zoomValue + increment;
        if (newZoomValue > 5) {
            return 5;
        }
        if (newZoomValue < 0.1) {
            return 0.1;
        }
        return +newZoomValue.toFixed(2);
    }
    onLoadError(url) {
        this.response = this.viewerUtilService.validateFile(url)
            .subscribe(next => next, error => {
            this.viewerException = new ViewerException(error.name, { httpResponseCode: error.status, message: error.message });
        });
        this.errorMessage = `Could not load the image "${this.url}"`;
        this.mediaLoadStatus.emit(ResponseType.FAILURE);
        this.imageViewerException.emit(this.viewerException);
    }
    onLoad(img) {
        this.mediaLoadStatus.emit(ResponseType.SUCCESS);
        this.initAnnoPage(img);
    }
    initAnnoPage(img) {
        this.imageHeight = this.rotation % 180 !== 0 ? img.offsetWidth : img.offsetHeight;
        this.imageWidth = this.rotation % 180 !== 0 ? img.offsetHeight : img.offsetWidth;
        this.imageLeft = this.rotation % 180 !== 0 ? img.offsetTop : img.offsetLeft;
        this.imageTop = this.rotation % 180 !== 0 ? img.offsetLeft : img.offsetTop;
        const payload = [{
                div: {
                    scrollHeight: this.imageHeight,
                    scrollWidth: this.imageWidth,
                    offsetLeft: this.imageLeft,
                },
                pageNumber: 1,
                scale: this.zoom,
                rotation: this.rotation,
                id: 1
            }];
        this.store.dispatch(new AddPages(payload));
    }
    toggleCommentsSummary() {
        this.toolbarEvents.toggleCommentsSummary(!this.toolbarEvents.showCommentSummary.getValue());
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageViewerComponent, deps: [{ token: i1.Store }, { token: PrintService }, { token: ViewerUtilService }, { token: ToolbarEventService }, { token: ToolbarButtonVisibilityService }, { token: ViewerEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ImageViewerComponent, selector: "mv-image-viewer", inputs: { url: "url", downloadFileName: "downloadFileName", enableAnnotations: "enableAnnotations", annotationSet: "annotationSet", height: "height" }, outputs: { mediaLoadStatus: "mediaLoadStatus", imageViewerException: "imageViewerException" }, host: { listeners: { "mousedown": "onImageViewerClick($event)" } }, viewQueries: [{ propertyName: "img", first: true, predicate: ["img"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<mv-comment-set-header\n  [ngClass]=\"{ 'show-comments-panel': showCommentsPanel }\"\n  [isHidden]=\"!showCommentsPanel\"\n  [showCommentSummary]=\"toolbarButtons.showCommentSummary\"\n  (showCommentSummaryDialog)=\"toggleCommentsSummary()\"\n>\n</mv-comment-set-header>\n<div\n  id=\"viewer-wrapper\"\n  [ngStyle]=\"{ height: height }\"\n  [ngClass]=\"{ grabNDrag: enableGrabNDrag }\"\n  *ngIf=\"url && !errorMessage\"\n>\n  <div\n    #imageContainer\n    id=\"image-container\"\n    mvGrabNDrag\n    [dragX]=\"imageContainer\"\n    [dragEnabled]=\"enableGrabNDrag\"\n    (scroll)=\"($event)\"\n    [ngClass]=\"{\n      'image-container': true,\n      annotations: enableAnnotations,\n      'show-comments-panel': showCommentsPanel\n    }\"\n  >\n    <img\n      #img\n      alt=\"\"\n      [src]=\"url\"\n      [ngClass]=\"'rot' + rotation\"\n      (error)=\"onLoadError(url)\"\n      (load)=\"onLoad(img)\"\n    />\n    <mv-redactions\n      *ngIf=\"toolbarEvents.redactionMode | async; else annotationTemplate\"\n      [zoom]=\"zoom\"\n      [rotate]=\"rotation\"\n    ></mv-redactions>\n    <ng-template #annotationTemplate>\n      <mv-metadata-layer\n        *ngIf=\"enableAnnotations && annotationSet\"\n        [zoom]=\"zoom\"\n        [rotate]=\"rotation\"\n      >\n      </mv-metadata-layer>\n    </ng-template>\n  </div>\n\n  <mv-comment-set\n    [contentScrollTop]=\"imageContainer.scrollTop\"\n    *ngIf=\"\n      enableAnnotations &&\n      annotationSet &&\n      (toolbarEvents.redactionMode | async) !== true\n    \"\n    [annotationSet]=\"annotationSet\"\n    [zoom]=\"zoom\"\n    [rotate]=\"rotation\"\n    [height]=\"imageHeight\"\n  >\n  </mv-comment-set>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: CommentSetComponent, selector: "mv-comment-set", inputs: ["annotationSet", "zoom", "rotate", "height", "pageHeights", "contentScrollTop"] }, { kind: "component", type: CommentSetHeaderComponent, selector: "mv-comment-set-header", inputs: ["showCommentSummary", "isHidden"], outputs: ["showCommentSummaryDialog"] }, { kind: "component", type: MetadataLayerComponent, selector: "mv-metadata-layer", inputs: ["zoom", "rotate"] }, { kind: "directive", type: GrabNDragDirective, selector: "[mvGrabNDrag]", inputs: ["dragEnabled", "dragX"] }, { kind: "component", type: RedactionComponent, selector: "mv-redactions", inputs: ["zoom", "rotate"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageViewerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-image-viewer', template: "<mv-comment-set-header\n  [ngClass]=\"{ 'show-comments-panel': showCommentsPanel }\"\n  [isHidden]=\"!showCommentsPanel\"\n  [showCommentSummary]=\"toolbarButtons.showCommentSummary\"\n  (showCommentSummaryDialog)=\"toggleCommentsSummary()\"\n>\n</mv-comment-set-header>\n<div\n  id=\"viewer-wrapper\"\n  [ngStyle]=\"{ height: height }\"\n  [ngClass]=\"{ grabNDrag: enableGrabNDrag }\"\n  *ngIf=\"url && !errorMessage\"\n>\n  <div\n    #imageContainer\n    id=\"image-container\"\n    mvGrabNDrag\n    [dragX]=\"imageContainer\"\n    [dragEnabled]=\"enableGrabNDrag\"\n    (scroll)=\"($event)\"\n    [ngClass]=\"{\n      'image-container': true,\n      annotations: enableAnnotations,\n      'show-comments-panel': showCommentsPanel\n    }\"\n  >\n    <img\n      #img\n      alt=\"\"\n      [src]=\"url\"\n      [ngClass]=\"'rot' + rotation\"\n      (error)=\"onLoadError(url)\"\n      (load)=\"onLoad(img)\"\n    />\n    <mv-redactions\n      *ngIf=\"toolbarEvents.redactionMode | async; else annotationTemplate\"\n      [zoom]=\"zoom\"\n      [rotate]=\"rotation\"\n    ></mv-redactions>\n    <ng-template #annotationTemplate>\n      <mv-metadata-layer\n        *ngIf=\"enableAnnotations && annotationSet\"\n        [zoom]=\"zoom\"\n        [rotate]=\"rotation\"\n      >\n      </mv-metadata-layer>\n    </ng-template>\n  </div>\n\n  <mv-comment-set\n    [contentScrollTop]=\"imageContainer.scrollTop\"\n    *ngIf=\"\n      enableAnnotations &&\n      annotationSet &&\n      (toolbarEvents.redactionMode | async) !== true\n    \"\n    [annotationSet]=\"annotationSet\"\n    [zoom]=\"zoom\"\n    [rotate]=\"rotation\"\n    [height]=\"imageHeight\"\n  >\n  </mv-comment-set>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: PrintService }, { type: ViewerUtilService }, { type: ToolbarEventService }, { type: ToolbarButtonVisibilityService }, { type: ViewerEventService }], propDecorators: { url: [{
                type: Input
            }], downloadFileName: [{
                type: Input
            }], enableAnnotations: [{
                type: Input
            }], annotationSet: [{
                type: Input
            }], height: [{
                type: Input
            }], mediaLoadStatus: [{
                type: Output
            }], imageViewerException: [{
                type: Output
            }], img: [{
                type: ViewChild,
                args: ['img', { static: false }]
            }], onImageViewerClick: [{
                type: HostListener,
                args: ['mousedown', ['$event']]
            }] } });

class UnsupportedViewerComponent {
    constructor(toolbarEvents, viewerUtilService) {
        this.toolbarEvents = toolbarEvents;
        this.viewerUtilService = viewerUtilService;
        this.loadStatus = new EventEmitter();
        this.unsupportedViewerException = new EventEmitter();
        this.subscriptions = [];
    }
    ngOnInit() {
        this.subscriptions.push(this.toolbarEvents.downloadSubject.subscribe(() => this.downloadLink.nativeElement.click()), this.viewerUtilService.validateFile(this.url).subscribe(next => next, error => {
            this.viewerException = new ViewerException(error.name, { httpResponseCode: error.status, message: error.message });
        }));
        this.loadStatus.emit(ResponseType.UNSUPPORTED);
        if (!this.typeException) {
            this.unsupportedViewerException.emit(this.viewerException);
        }
    }
    ngOnDestroy() {
        for (const subscription of this.subscriptions) {
            subscription.unsubscribe();
        }
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UnsupportedViewerComponent, deps: [{ token: ToolbarEventService }, { token: ViewerUtilService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UnsupportedViewerComponent, selector: "mv-unsupported-viewer", inputs: { url: "url", downloadFileName: "downloadFileName", typeException: "typeException" }, outputs: { loadStatus: "loadStatus", unsupportedViewerException: "unsupportedViewerException" }, viewQueries: [{ propertyName: "downloadLink", first: true, predicate: ["downloadLink"], descendants: true }], ngImport: i0, template: "<div class=\"govuk-width-container\">\n  <div class=\"govuk-notification-banner__content\">\n    <p>\n      <span *ngIf=\"typeException, else unsupported\">The document could not be displayed, or the file type is unsupported.</span>\n      Please <a #downloadLink [href]=\"url\" [download]=\"downloadFileName\">click here to download</a>.\n    </p>\n    <ng-template #unsupported>\n      <span>This file type is not supported by this viewer.</span>\n    </ng-template>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UnsupportedViewerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-unsupported-viewer', template: "<div class=\"govuk-width-container\">\n  <div class=\"govuk-notification-banner__content\">\n    <p>\n      <span *ngIf=\"typeException, else unsupported\">The document could not be displayed, or the file type is unsupported.</span>\n      Please <a #downloadLink [href]=\"url\" [download]=\"downloadFileName\">click here to download</a>.\n    </p>\n    <ng-template #unsupported>\n      <span>This file type is not supported by this viewer.</span>\n    </ng-template>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: ViewerUtilService }], propDecorators: { url: [{
                type: Input
            }], downloadFileName: [{
                type: Input
            }], typeException: [{
                type: Input
            }], loadStatus: [{
                type: Output
            }], unsupportedViewerException: [{
                type: Output
            }], downloadLink: [{
                type: ViewChild,
                args: ['downloadLink', { static: false }]
            }] } });

class AnnotationApiService {
    constructor(httpClient) {
        this.httpClient = httpClient;
        this.annotationApiUrl = '/em-anno';
        this.annotationSetBaseUrl = '/annotation-sets';
        this.annotationBaseUrl = '/annotations';
    }
    getAnnotationSet(documentId) {
        const fixedUrl = `${this.annotationSetsFullUrl}/filter?documentId=${documentId}`;
        return this.httpClient
            .get(fixedUrl, { observe: 'response', withCredentials: true });
    }
    postAnnotationSet(body) {
        return this.httpClient
            .post(this.annotationSetsFullUrl, body, { observe: 'response', withCredentials: true })
            .pipe(map(response => response.body), catchError(() => []));
    }
    getComments(annotationSet) {
        return annotationSet
            .pipe(map(this.sortAnnotations), map(this.extractComments));
    }
    /**
     * Sort the annotations in the response by page and then y position of their first rectangle
     */
    sortAnnotations(r) {
        return r.annotations.sort((a, b) => a.page !== b.page ? a.page - b.page : a.rectangles[0].y - b.rectangles[0].y);
    }
    extractComments(annotations) {
        return [].concat(...annotations.map(a => a.comments));
    }
    deleteAnnotation(annotationId) {
        const url = `${this.annotationFullsUrl}/${annotationId}`;
        return this.httpClient
            .delete(url, { observe: 'response', withCredentials: true })
            .pipe(map(response => response.body));
    }
    postAnnotation(annotation) {
        return this.httpClient
            .post(this.annotationFullsUrl, annotation, { observe: 'response', withCredentials: true })
            .pipe(map(response => response.body));
    }
    get annotationSetsFullUrl() {
        return this.annotationApiUrl + this.annotationSetBaseUrl;
    }
    get annotationFullsUrl() {
        return this.annotationApiUrl + this.annotationBaseUrl;
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationApiService, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationApiService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationApiService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$1.HttpClient }] });

/**
 * Number Helper Service
 * */
class NumberHelperService {
    constructor() { }
    isNumber(value) {
        return (value !== null
            && value !== undefined
            && value !== ''
            && !isNaN(Number(value.toString())));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NumberHelperService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NumberHelperService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NumberHelperService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [] });

class SearchBarComponent {
    constructor(toolbarButtons, toolbarEvents) {
        this.toolbarButtons = toolbarButtons;
        this.toolbarEvents = toolbarEvents;
        this.highlightAll = true;
        this.matchCase = false;
        this.wholeWord = false;
        this.resultsText = '';
        this.searchText = '';
        this.resultCount = 0;
        this.subscriptions = [];
        this.advancedSearchVisible = false;
    }
    ngOnInit() {
        this.subscriptions.push(this.toolbarEvents.searchResultsCountSubject.subscribe(results => this.setSearchResultsCount(results)));
    }
    ngAfterViewInit() {
        this.findInput.nativeElement.focus();
    }
    ngOnDestroy() {
        for (const subscription of this.subscriptions) {
            subscription.unsubscribe();
        }
    }
    onWindowKeyDown(e) {
        if (e.code === 'F3' || (e.ctrlKey && e.code === 'KeyF')) {
            e.preventDefault();
            this.toolbarEvents.searchBarHidden.next(false);
            setTimeout(() => this.findInput.nativeElement.focus(), 200);
        }
    }
    searchNext() {
        this.toolbarEvents.search({
            searchTerm: this.searchText,
            highlightAll: this.highlightAll,
            matchCase: this.matchCase,
            wholeWord: this.wholeWord,
            previous: false,
            reset: false
        });
    }
    searchPrev() {
        this.toolbarEvents.search({
            searchTerm: this.searchText,
            highlightAll: this.highlightAll,
            matchCase: this.matchCase,
            wholeWord: this.wholeWord,
            previous: true,
            reset: false
        });
    }
    search() {
        this.toolbarEvents.search({
            searchTerm: this.searchText,
            highlightAll: this.highlightAll,
            matchCase: this.matchCase,
            wholeWord: this.wholeWord,
            previous: false,
            reset: true
        });
    }
    setSearchResultsCount(results) {
        this.resultCount = results.total;
        this.resultsText = this.resultCount > 0
            ? `Found ${results.current} of ${results.total}`
            : 'No results found';
        if (this.resultCount && this.resultCount > 0 && !results.isPrevious) {
            setTimeout(() => {
                this.findNext.nativeElement.focus();
            }, 1000);
        }
    }
    onEscapeKeyPress(e) {
        this.toolbarEvents.searchBarHidden.next(true);
    }
    onEnterKeyPress(e) {
        this.search();
    }
    toggleAdvancedSearch() {
        this.advancedSearchVisible = !this.advancedSearchVisible;
    }
    toggleSearchBar() {
        this.toolbarEvents.searchBarHidden.next(!this.toolbarEvents.searchBarHidden.getValue());
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SearchBarComponent, deps: [{ token: ToolbarButtonVisibilityService }, { token: ToolbarEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SearchBarComponent, selector: "mv-search-bar", host: { listeners: { "window:keydown": "onWindowKeyDown($event)" } }, viewQueries: [{ propertyName: "findInput", first: true, predicate: ["findInput"], descendants: true, static: true }, { propertyName: "findNext", first: true, predicate: ["findNext"], descendants: true }], ngImport: i0, template: "<div\n  class=\"searchbar govuk-!-padding-3\"\n  [hidden]=\"toolbarEvents.searchBarHidden | async\"\n>\n  <div class=\"govuk-grid-row\">\n    <div class=\"govuk-grid-column-full\">\n      <input\n        class=\"govuk-input govuk-!-display-inline-block govuk-!-width-three-quarters govuk-!-margin-bottom-5 govuk-!-margin-top-5\"\n        type=\"text\"\n        aria-label=\"Search document\"\n        #findInput\n        [ngModel]=\"searchText\"\n        (ngModelChange)=\"searchText = $event\"\n        (keydown.escape)=\"onEscapeKeyPress($event)\"\n        (keydown.enter)=\"onEnterKeyPress($event)\"\n        title=\"Search document\"\n        placeholder=\"Search document for\u2026\"\n        tabindex=\"0\"\n        data-l10n-id=\"find_input\"\n      />\n      <button\n        class=\"govuk-button govuk-!-display-inline-block govuk-!-margin-bottom-4\"\n        data-module=\"govuk-button\"\n        (click)=\"search()\"\n        style=\"position: absolute; top: 40px; right: 10px\"\n      >\n        Search\n      </button>\n    </div>\n  </div>\n\n  <div class=\"govuk-grid-row\">\n    <div class=\"govuk-grid-column-three-quarters\">\n      <span\n        id=\"findResultsCount\"\n        class=\"govuk-!-display-inline-block govuk-!-margin-right-4\"\n        role=\"status\"\n        >{{ resultsText }}</span\n      >\n      <a\n        *ngIf=\"resultCount > 0\"\n        id=\"findPrevious\"\n        [routerLink]=\"[]\"\n        role=\"button\"\n        class=\"govuk-link govuk-link--no-visited-state govuk-!-margin-right-2\"\n        (click)=\"searchPrev()\"\n        title=\"Find the previous occurrence of the phrase\"\n        data-l10n-id=\"find_previous\"\n        >{{ \"Prev\" | rpxTranslate }}</a\n      >\n      <a\n        *ngIf=\"resultCount > 0\"\n        id=\"findNext\"\n        #findNext\n        [routerLink]=\"[]\"\n        role=\"button\"\n        class=\"govuk-link govuk-link--no-visited-state\"\n        (click)=\"searchNext()\"\n        title=\"Find the next occurrence of the phrase\"\n        data-l10n-id=\"find_next\"\n        >{{ \"Next\" | rpxTranslate }}</a\n      >\n    </div>\n    <div class=\"govuk-grid-column-one-quarter\">\n      <a\n        [routerLink]=\"[]\"\n        class=\"govuk-link govuk-link--no-visited-state\"\n        role=\"button\"\n        (click)=\"toggleAdvancedSearch()\"\n        title=\"Advanced\"\n        [attr.aria-expanded]=\"advancedSearchVisible\"\n        aria-controls=\"advancedSearchVisible\"\n        data-l10n-id=\"find_advanced\"\n        style=\"position: absolute; top: 95px; right: 15px\"\n        >{{ \"Advanced\" | rpxTranslate }}</a\n      >\n    </div>\n  </div>\n\n  <div\n    id=\"advancedSearchVisible\"\n    class=\"govuk-grid-row\"\n    *ngIf=\"advancedSearchVisible\"\n  >\n    <div class=\"govuk-grid-column-full\">\n      <div\n        class=\"govuk-form-group govuk-!-margin-top-3 govuk-!-margin-bottom-1\"\n      >\n        <fieldset class=\"govuk-fieldset\" aria-describedby=\"advanced\">\n          <div class=\"govuk-checkboxes\">\n            <div class=\"govuk-checkboxes__item\">\n              <input\n                class=\"govuk-checkboxes__input\"\n                id=\"findHighlightAll\"\n                name=\"findHighlightAll\"\n                type=\"checkbox\"\n                (change)=\"highlightAll = !highlightAll; search()\"\n                [checked]=\"highlightAll\"\n              />\n              <label\n                class=\"govuk-label govuk-checkboxes__label\"\n                for=\"findHighlightAll\"\n                data-l10n-id=\"find_highlight\"\n              >\n                {{ \"Highlight all\" | rpxTranslate }}\n              </label>\n            </div>\n            <div class=\"govuk-checkboxes__item\">\n              <input\n                class=\"govuk-checkboxes__input\"\n                id=\"findMatchCase\"\n                name=\"findMatchCase\"\n                type=\"checkbox\"\n                (change)=\"matchCase = !matchCase; search()\"\n                [checked]=\"matchCase\"\n              />\n              <label\n                class=\"govuk-label govuk-checkboxes__label\"\n                for=\"findMatchCase\"\n                data-l10n-id=\"find_match_case_label\"\n              >\n                {{ \"Match text (exact case)\" | rpxTranslate }}\n              </label>\n            </div>\n            <div class=\"govuk-checkboxes__item\">\n              <input\n                class=\"govuk-checkboxes__input\"\n                id=\"findEntireWord\"\n                name=\"findMatchCase\"\n                type=\"checkbox\"\n                (change)=\"wholeWord = !wholeWord; search()\"\n                [checked]=\"wholeWord\"\n              />\n              <label\n                class=\"govuk-label govuk-checkboxes__label\"\n                for=\"findEntireWord\"\n                data-l10n-id=\"find_entire_word_label\"\n              >\n                {{ \"Match whole words or sentences\" | rpxTranslate }}\n              </label>\n            </div>\n          </div>\n        </fieldset>\n      </div>\n    </div>\n  </div>\n  <div>\n    <button\n      id=\"mvCloseBtn\"\n      #mvCloseBtn\n      class=\"mv-button searchbar-button--close\"\n      title=\"Close Search\"\n      data-l10n-id=\"mvRedactBtn\"\n      (click)=\"toggleSearchBar()\"\n    ></button>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5$1.RpxTranslatePipe, name: "rpxTranslate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SearchBarComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-search-bar', template: "<div\n  class=\"searchbar govuk-!-padding-3\"\n  [hidden]=\"toolbarEvents.searchBarHidden | async\"\n>\n  <div class=\"govuk-grid-row\">\n    <div class=\"govuk-grid-column-full\">\n      <input\n        class=\"govuk-input govuk-!-display-inline-block govuk-!-width-three-quarters govuk-!-margin-bottom-5 govuk-!-margin-top-5\"\n        type=\"text\"\n        aria-label=\"Search document\"\n        #findInput\n        [ngModel]=\"searchText\"\n        (ngModelChange)=\"searchText = $event\"\n        (keydown.escape)=\"onEscapeKeyPress($event)\"\n        (keydown.enter)=\"onEnterKeyPress($event)\"\n        title=\"Search document\"\n        placeholder=\"Search document for\u2026\"\n        tabindex=\"0\"\n        data-l10n-id=\"find_input\"\n      />\n      <button\n        class=\"govuk-button govuk-!-display-inline-block govuk-!-margin-bottom-4\"\n        data-module=\"govuk-button\"\n        (click)=\"search()\"\n        style=\"position: absolute; top: 40px; right: 10px\"\n      >\n        Search\n      </button>\n    </div>\n  </div>\n\n  <div class=\"govuk-grid-row\">\n    <div class=\"govuk-grid-column-three-quarters\">\n      <span\n        id=\"findResultsCount\"\n        class=\"govuk-!-display-inline-block govuk-!-margin-right-4\"\n        role=\"status\"\n        >{{ resultsText }}</span\n      >\n      <a\n        *ngIf=\"resultCount > 0\"\n        id=\"findPrevious\"\n        [routerLink]=\"[]\"\n        role=\"button\"\n        class=\"govuk-link govuk-link--no-visited-state govuk-!-margin-right-2\"\n        (click)=\"searchPrev()\"\n        title=\"Find the previous occurrence of the phrase\"\n        data-l10n-id=\"find_previous\"\n        >{{ \"Prev\" | rpxTranslate }}</a\n      >\n      <a\n        *ngIf=\"resultCount > 0\"\n        id=\"findNext\"\n        #findNext\n        [routerLink]=\"[]\"\n        role=\"button\"\n        class=\"govuk-link govuk-link--no-visited-state\"\n        (click)=\"searchNext()\"\n        title=\"Find the next occurrence of the phrase\"\n        data-l10n-id=\"find_next\"\n        >{{ \"Next\" | rpxTranslate }}</a\n      >\n    </div>\n    <div class=\"govuk-grid-column-one-quarter\">\n      <a\n        [routerLink]=\"[]\"\n        class=\"govuk-link govuk-link--no-visited-state\"\n        role=\"button\"\n        (click)=\"toggleAdvancedSearch()\"\n        title=\"Advanced\"\n        [attr.aria-expanded]=\"advancedSearchVisible\"\n        aria-controls=\"advancedSearchVisible\"\n        data-l10n-id=\"find_advanced\"\n        style=\"position: absolute; top: 95px; right: 15px\"\n        >{{ \"Advanced\" | rpxTranslate }}</a\n      >\n    </div>\n  </div>\n\n  <div\n    id=\"advancedSearchVisible\"\n    class=\"govuk-grid-row\"\n    *ngIf=\"advancedSearchVisible\"\n  >\n    <div class=\"govuk-grid-column-full\">\n      <div\n        class=\"govuk-form-group govuk-!-margin-top-3 govuk-!-margin-bottom-1\"\n      >\n        <fieldset class=\"govuk-fieldset\" aria-describedby=\"advanced\">\n          <div class=\"govuk-checkboxes\">\n            <div class=\"govuk-checkboxes__item\">\n              <input\n                class=\"govuk-checkboxes__input\"\n                id=\"findHighlightAll\"\n                name=\"findHighlightAll\"\n                type=\"checkbox\"\n                (change)=\"highlightAll = !highlightAll; search()\"\n                [checked]=\"highlightAll\"\n              />\n              <label\n                class=\"govuk-label govuk-checkboxes__label\"\n                for=\"findHighlightAll\"\n                data-l10n-id=\"find_highlight\"\n              >\n                {{ \"Highlight all\" | rpxTranslate }}\n              </label>\n            </div>\n            <div class=\"govuk-checkboxes__item\">\n              <input\n                class=\"govuk-checkboxes__input\"\n                id=\"findMatchCase\"\n                name=\"findMatchCase\"\n                type=\"checkbox\"\n                (change)=\"matchCase = !matchCase; search()\"\n                [checked]=\"matchCase\"\n              />\n              <label\n                class=\"govuk-label govuk-checkboxes__label\"\n                for=\"findMatchCase\"\n                data-l10n-id=\"find_match_case_label\"\n              >\n                {{ \"Match text (exact case)\" | rpxTranslate }}\n              </label>\n            </div>\n            <div class=\"govuk-checkboxes__item\">\n              <input\n                class=\"govuk-checkboxes__input\"\n                id=\"findEntireWord\"\n                name=\"findMatchCase\"\n                type=\"checkbox\"\n                (change)=\"wholeWord = !wholeWord; search()\"\n                [checked]=\"wholeWord\"\n              />\n              <label\n                class=\"govuk-label govuk-checkboxes__label\"\n                for=\"findEntireWord\"\n                data-l10n-id=\"find_entire_word_label\"\n              >\n                {{ \"Match whole words or sentences\" | rpxTranslate }}\n              </label>\n            </div>\n          </div>\n        </fieldset>\n      </div>\n    </div>\n  </div>\n  <div>\n    <button\n      id=\"mvCloseBtn\"\n      #mvCloseBtn\n      class=\"mv-button searchbar-button--close\"\n      title=\"Close Search\"\n      data-l10n-id=\"mvRedactBtn\"\n      (click)=\"toggleSearchBar()\"\n    ></button>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: ToolbarButtonVisibilityService }, { type: ToolbarEventService }], propDecorators: { findInput: [{
                type: ViewChild,
                args: ['findInput', { static: true }]
            }], findNext: [{
                type: ViewChild,
                args: ['findNext', { static: false }]
            }], onWindowKeyDown: [{
                type: HostListener,
                args: ['window:keydown', ['$event']]
            }] } });

class MainToolbarComponent {
    constructor(toolbarEvents, toolbarButtons, cdr, numberHelper, icpEventService) {
        this.toolbarEvents = toolbarEvents;
        this.toolbarButtons = toolbarButtons;
        this.cdr = cdr;
        this.numberHelper = numberHelper;
        this.icpEventService = icpEventService;
        this.enableAnnotations = false;
        this.enableRedactions = false;
        this.enableICP = false;
        this.contentType = null;
        this.subscriptions = [];
        this.icpEnabled = false;
        this.redactionEnabled = false;
        this.pageNumber = 1;
        this.pageCount = 0;
        this.isDropdownMenuOpen = false;
        this.isBookmarksOpen = false;
        this.isIndexOpen = false;
        this.isRedactOpen = false;
        this.isCommentsOpen = false;
        this.dropdownMenuPositions = [
            new ConnectionPositionPair({
                originX: 'end',
                originY: 'bottom'
            }, {
                overlayX: 'end',
                overlayY: 'top'
            }, 0, 3)
        ];
        this.zoomScales = [0.1, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 2.5, 3, 5];
        this.allButtonsWidth = 0;
        this.widthRequiredForBtn = {};
    }
    ngOnInit() {
        this.subscriptions.push(this.toolbarEvents.setCurrentPageSubject.subscribe(pageNumber => this.setCurrentPage(pageNumber)), this.toolbarEvents.setCurrentPageInputValueSubject.subscribe(pageNumber => this.pageNumber = pageNumber), this.toolbarEvents.getPageCount().subscribe(count => this.pageCount = count), this.icpEventService.enabled.subscribe(enabled => {
            this.icpEnabled = enabled;
            if (this.icpEnabled) {
                this.toolbarEvents.toggleCommentsPanel(!enabled);
                this.toolbarEvents.sidebarOpen.next(false);
            }
        }), this.toolbarEvents.redactionMode.subscribe(enabled => {
            this.redactionEnabled = enabled;
        }), this.toolbarEvents.redactAllInProgressSubject.subscribe(disable => {
            this.redactAllInProgress = disable;
        }));
    }
    ngOnDestroy() {
        for (const subscription of this.subscriptions) {
            subscription.unsubscribe();
        }
    }
    ngAfterViewInit() {
        Array.from(this.mvToolbarMain.nativeElement.children).forEach((button) => {
            this.allButtonsWidth += HtmlTemplatesHelper.getAdjustedBoundingRect(button).width;
            this.widthRequiredForBtn[button.id] = this.allButtonsWidth;
        });
        this.cdr.detectChanges();
    }
    onResize() {
        this.cdr.detectChanges();
    }
    onControlPrint(event) {
        event.preventDefault();
        this.printFile();
    }
    onClickHighlightToggle() {
        this.toolbarEvents.toggleHighlightToolbar();
    }
    onClickDrawToggle() {
        this.toolbarEvents.toggleDrawMode();
    }
    toggleIndexSideBar() {
        const sidebarOpen = this.toolbarEvents.sidebarOpen.getValue();
        const sidebarView = this.toolbarEvents.sidebarOutlineView.getValue();
        if (!(sidebarOpen && !sidebarView)) {
            this.toolbarEvents.toggleSideBar(!sidebarOpen);
        }
        this.toolbarEvents.toggleSideBarView(true);
        this.isIndexOpen = !this.isIndexOpen;
    }
    onToolBarOffSetChange(buttonId) {
        if (this.mvToolbarMain && this.mvToolbarMain.nativeElement.offsetWidth < this.widthRequiredForBtn[buttonId]) {
            return "button-hidden-on-toolbar";
        }
        return "button-hidden-on-dropdown";
    }
    toggleBookmarksSideBar() {
        const sidebarOpen = this.toolbarEvents.sidebarOpen.getValue();
        const sidebarView = this.toolbarEvents.sidebarOutlineView.getValue();
        if (!(sidebarOpen && sidebarView)) {
            this.toolbarEvents.toggleSideBar(!sidebarOpen);
        }
        this.toolbarEvents.toggleSideBarView(false);
        this.isBookmarksOpen = !this.isBookmarksOpen;
    }
    togglePresentBar() {
        this.toolbarEvents.searchBarHidden.next(true);
        this.icpEventService.enable();
    }
    increasePageNumber() {
        this.toolbarEvents.incrementPage(1);
    }
    decreasePageNumber() {
        this.toolbarEvents.incrementPage(-1);
    }
    onPageNumberInputChange(pageNumber) {
        if (Number(pageNumber) < 1) {
            pageNumber = '1';
        }
        if (Number(pageNumber) > this.pageCount) {
            pageNumber = this.pageCount.toString();
        }
        this.toolbarEvents.setPage(Number.parseInt(pageNumber, 10));
    }
    setCurrentPage(pageNumber) {
        this.pageNumber = pageNumber;
    }
    rotate(rotation) {
        this.toolbarEvents.rotate(rotation);
    }
    printFile() {
        this.toolbarEvents.print();
    }
    downloadFile() {
        this.toolbarEvents.download();
    }
    zoom(zoomFactor) {
        this.toolbarEvents.zoom(+zoomFactor);
    }
    stepZoom(zoomFactor) {
        this.toolbarEvents.stepZoom(zoomFactor);
        this.zoomSelect.nativeElement.selected = 'selected';
    }
    toggleCommentsPanel() {
        this.toolbarEvents.toggleCommentsPanel(!this.toolbarEvents.commentsPanelVisible.getValue());
        this.isCommentsOpen = !this.isCommentsOpen;
    }
    toggleRedactBar() {
        this.toolbarEvents.toggleRedactionMode();
        this.isRedactOpen = !this.isRedactOpen;
    }
    toggleGrabNDrag() {
        this.toolbarEvents.toggleGrabNDrag();
    }
    isPdf() {
        return this.contentType === 'pdf';
    }
    toggleSearchBar() {
        this.toolbarEvents.searchBarHidden.next(!this.toolbarEvents.searchBarHidden.getValue());
    }
    toggleMoreOptions() {
        this.isDropdownMenuOpen = !this.isDropdownMenuOpen;
        setTimeout(() => {
            if (this.mvMenuItems) {
                this.mvMenuItems.nativeElement.focus();
            }
        }, 100);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MainToolbarComponent, deps: [{ token: ToolbarEventService }, { token: ToolbarButtonVisibilityService }, { token: i0.ChangeDetectorRef }, { token: NumberHelperService }, { token: IcpEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: MainToolbarComponent, selector: "mv-main-toolbar", inputs: { enableAnnotations: "enableAnnotations", enableRedactions: "enableRedactions", enableICP: "enableICP", contentType: "contentType" }, host: { listeners: { "window:resize": "onResize()", "document:keydown.control.p": "onControlPrint($event)", "document:keydown.meta.p": "onControlPrint($event)" } }, viewQueries: [{ propertyName: "zoomSelect", first: true, predicate: ["zoomSelect"], descendants: true }, { propertyName: "mvToolbarMain", first: true, predicate: ["mvToolbarMain"], descendants: true }, { propertyName: "mvMenuItems", first: true, predicate: ["dropdownMenu"], descendants: true }], ngImport: i0, template: "<div class=\"toolbar\">\n  <div id=\"toolbarContainer\">\n    <div class=\"mv-toolbar__container\">\n      <div #mvToolbar class=\"mv-toolbar\" [class.notSupported]=\"!contentType\">\n        <!-- The mvToolbarMain div contains all toolbar buttons except the \"More options\" button. This allows for calculation of the available space to display buttons -->\n        <div id=\"mvToolbarMain\" class=\"mv-toolbar-main\" #mvToolbarMain>\n          <ng-container *ngTemplateOutlet=\"menuItems\"></ng-container>\n        </div>\n        <!-- The mvToolbarMoreOptions div contains the \"More options\" toolbar button (and the overlay template for the dropdown menu).\n            The space occupied by the button (if visible) is excluded from the toolbar space available calculation -->\n        <div id=\"mvToolbarMoreOptions\" class=\"mv-toolbar-more-options\">\n          <button\n            id=\"mvMoreOptionsBtn\"\n            class=\"mv-button mv-toolbar__menu-button--more-options\"\n            [class.mv-toolbar__menu-button--more-options__hidden]=\"\n              mvToolbar.offsetWidth >= allButtonsWidth\n            \"\n            [attr.aria-expanded]=\"isDropdownMenuOpen\"\n            (click)=\"toggleMoreOptions()\"\n            cdkOverlayOrigin\n            #trigger=\"cdkOverlayOrigin\"\n            [disabled]=\"redactAllInProgress\"\n          >\n            <span>{{ \"More options\" | rpxTranslate }}</span>\n          </button>\n          <!-- This template displays the overlay content for the dropdown menu and is connected to the \"More options\" button -->\n          <ng-template\n            cdkConnectedOverlay\n            [cdkConnectedOverlayOrigin]=\"trigger\"\n            [cdkConnectedOverlayOpen]=\"isDropdownMenuOpen\"\n            [cdkConnectedOverlayPositions]=\"dropdownMenuPositions\"\n          >\n            <div class=\"dropdown-menu\" #dropdownMenu tabindex=\"0\">\n              <ng-container *ngTemplateOutlet=\"menuItems\"></ng-container>\n            </div>\n          </ng-template>\n        </div>\n      </div>\n\n      <div id=\"mvMenuItems\" #mvMenuItems>\n        <ng-template #menuItems>\n          <button\n            *ngIf=\"toolbarButtons.showSidebar\"\n            id=\"mvIndexBtn\"\n            title=\"Index\"\n            data-l10n-id=\"index\"\n            #mvIndexBtn\n            class=\"mv-button mv-toolbar__menu-button--index\"\n            [class.button-hidden-on-toolbar]=\"\n              mvToolbarMain.offsetWidth < widthRequiredForBtn['mvIndexBtn']\n            \"\n            [class.button-hidden-on-dropdown]=\"\n              mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvIndexBtn']\n            \"\n            [attr.aria-expanded]=\"isIndexOpen\"\n            [disabled]=\"redactAllInProgress\"\n            (click)=\"toggleIndexSideBar(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Index\" | rpxTranslate }}</span>\n          </button>\n\n          <button\n            *ngIf=\"toolbarButtons.showSidebar\"\n            id=\"mvBookmarksBtn\"\n            title=\"Bookmarks\"\n            data-l10n-id=\"bookmarks\"\n            #mvBookmarksBtn\n            [ngClass]=\"{\n              'mv-button mv-toolbar__menu-button--bookmarks': true,\n              'button-hidden-on-toolbar':\n                mvToolbarMain.offsetWidth <\n                widthRequiredForBtn['mvBookmarksBtn'],\n              'button-hidden-on-dropdown':\n                mvToolbarMain.offsetWidth >=\n                widthRequiredForBtn['mvBookmarksBtn']\n            }\"\n            [attr.aria-expanded]=\"isBookmarksOpen\"\n            [disabled]=\"redactAllInProgress\"\n            (click)=\"toggleBookmarksSideBar(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Bookmarks\" | rpxTranslate }}</span>\n          </button>\n\n          <button\n            *ngIf=\"toolbarButtons.showDrawButton\"\n            [disabled]=\"icpEnabled || redactionEnabled\"\n            id=\"mvDrawBtn\"\n            #mvDrawBtn\n            class=\"mv-button mv-toolbar__menu-button--draw\"\n            title=\"Draw a box\"\n            [class.button-hidden-on-toolbar]=\"\n              mvToolbarMain.offsetWidth < widthRequiredForBtn['mvDrawBtn']\n            \"\n            [class.button-hidden-on-dropdown]=\"\n              mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvDrawBtn']\n            \"\n            [class.toggled]=\"toolbarEvents.drawModeSubject | async\"\n            aria-pressed=\"false\"\n            data-l10n-id=\"toggleDrawButton\"\n            (click)=\"onClickDrawToggle(); isDropdownMenuOpen = false\"\n          >\n            <span data-l10n-id=\"draw_label\">{{\n              \"Draw a box\" | rpxTranslate\n            }}</span>\n          </button>\n\n          <button\n            *ngIf=\"toolbarButtons.showHighlightButton\"\n            [disabled]=\"icpEnabled || redactionEnabled\"\n            id=\"mvHighlightBtn\"\n            #mvHighlightBtn\n            class=\"mv-button mv-toolbar__menu-button--highlight\"\n            title=\"Highlight\"\n            aria-label=\"Highlight\"\n            [class.button-hidden-on-toolbar]=\"\n              mvToolbarMain.offsetWidth < widthRequiredForBtn['mvHighlightBtn']\n            \"\n            [class.button-hidden-on-dropdown]=\"\n              mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvHighlightBtn']\n            \"\n            [class.toggled]=\"toolbarEvents.highlightToolbarSubject | async\"\n            aria-pressed=\"false\"\n            (click)=\"onClickHighlightToggle(); isDropdownMenuOpen = false\"\n            data-l10n-id=\"toggleHighlightButton\"\n          >\n            <span data-l10n-id=\"highlight_label\">{{\n              \"Highlight\" | rpxTranslate\n            }}</span>\n          </button>\n\n          <ng-container *ngIf=\"toolbarButtons.showNavigation\">\n            <div\n              id=\"mvPageBtn\"\n              #mvPageBtn\n              class=\"mv-toolbar__menu-button--page\"\n              [class.button-hidden-on-toolbar]=\"\n                mvToolbarMain.offsetWidth < widthRequiredForBtn['mvPageBtn']\n              \"\n              [class.button-hidden-on-dropdown]=\"\n                mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvPageBtn']\n              \"\n            >\n              <span>{{ \"Page\" | rpxTranslate }}</span>\n\n              <button\n                id=\"mvUpBtn\"\n                [disabled]=\"pageNumber === 1 || redactAllInProgress\"\n                title=\"Previous Page\"\n                class=\"mv-toolbar__menu-button--up button-image\"\n                data-l10n-id=\"previous\"\n                (click)=\"decreasePageNumber()\"\n                [disabled]=\"redactAllInProgress\"\n              >\n                <span></span>\n              </button>\n              <button\n                id=\"mvDownBtn\"\n                [disabled]=\"pageNumber === pageCount || redactAllInProgress\"\n                title=\"Next Page\"\n                class=\"mv-toolbar__menu-button--down button-image\"\n                data-l10n-id=\"next\"\n                (click)=\"increasePageNumber()\"\n              >\n                <span></span>\n              </button>\n\n              <input\n                type=\"number\"\n                id=\"pageNumber\"\n                class=\"hmcts-toolbar-input govuk-input--width-2\"\n                title=\"Page Number\"\n                value=\"1\"\n                size=\"4\"\n                min=\"1\"\n                [value]=\"pageNumber\"\n                aria-label=\"page number\"\n                tabindex=\"0\"\n                data-l10n-id=\"page\"\n                (change)=\"onPageNumberInputChange(pageNumberInput.value)\"\n                [disabled]=\"redactAllInProgress\"\n                #pageNumberInput\n              />\n              <span id=\"numPages\" class=\"toolbarLabel\">/ {{ pageCount }}</span>\n            </div>\n          </ng-container>\n\n          <ng-container *ngIf=\"toolbarButtons.showZoom\">\n            <div\n              id=\"mvZoomBtn\"\n              #mvZoomBtn\n              class=\"mv-toolbar__menu-button--zoom\"\n              aria-pressed=\"false\"\n              [class.button-hidden-on-toolbar]=\"\n                mvToolbarMain.offsetWidth < widthRequiredForBtn['mvZoomBtn']\n              \"\n              [class.button-hidden-on-dropdown]=\"\n                mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvZoomBtn']\n              \"\n            >\n              <button\n                [disabled]=\"\n                  toolbarEvents.zoomValueSubject.value === 0.1 ||\n                  redactAllInProgress\n                \"\n                id=\"mvMinusBtn\"\n                class=\"mv-toolbar__menu-button--zoom-out button-image\"\n                title=\"Zoom Out\"\n                data-l10n-id=\"zoom_out\"\n                (click)=\"stepZoom(-0.1)\"\n              >\n                <span class=\"mv-toolbar__menu-button--zoom-out-text\">{{\n                  \"Zoom Out\" | rpxTranslate\n                }}</span>\n              </button>\n              <select\n                id=\"scaleSelect\"\n                class=\"hmcts-toolbar-select\"\n                title=\"Zoom\"\n                tabindex=\"0\"\n                data-l10n-id=\"zoom\"\n                (change)=\"zoom($event.target.value)\"\n                aria-label=\"zoom\"\n                [disabled]=\"redactAllInProgress\"\n              >\n                <option\n                  #zoomSelect\n                  id=\"customScaleOption\"\n                  title=\"\"\n                  [value]=\"toolbarEvents.zoomValueSubject.value\"\n                >\n                  {{\n                    toolbarEvents.zoomValueSubject.value * 100\n                      | number : \"1.0-0\"\n                  }}%\n                </option>\n                <option\n                  *ngFor=\"let zoomScale of zoomScales\"\n                  title=\"\"\n                  [value]=\"zoomScale\"\n                  [attr.data-l10n-id]=\"'page_scale_percent_' + zoomScale * 100\"\n                >\n                  {{ zoomScale * 100 }}%\n                </option>\n              </select>\n\n              <button\n                [disabled]=\"\n                  toolbarEvents.zoomValueSubject.value === 5 ||\n                  redactAllInProgress\n                \"\n                id=\"mvPlusBtn\"\n                class=\"mv-toolbar__menu-button--zoom-in button-image\"\n                (click)=\"stepZoom(0.1)\"\n                title=\"Zoom In\"\n                data-l10n-id=\"zoom_in\"\n              >\n                <span class=\"mv-toolbar__menu-button--zoom-out-text\">{{\n                  \"Zoom In\" | rpxTranslate\n                }}</span>\n              </button>\n            </div>\n          </ng-container>\n\n          <div\n            *ngIf=\"toolbarButtons.showRotate\"\n            id=\"mvRotateBtn\"\n            #mvRotateBtn\n            class=\"mv-toolbar__menu-button--rotate\"\n            [class.button-hidden-on-toolbar]=\"\n              mvToolbarMain.offsetWidth < widthRequiredForBtn['mvRotateBtn']\n            \"\n            [class.button-hidden-on-dropdown]=\"\n              mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvRotateBtn']\n            \"\n          >\n            <button\n              id=\"mvRotateLeftBtn\"\n              class=\"mv-toolbar__menu-button--rotate_left button-image\"\n              title=\"Rotate Counterclockwise\"\n              data-l10n-id=\"page_rotate_ccw\"\n              (click)=\"rotate(270)\"\n              [disabled]=\"redactAllInProgress\"\n            >\n              <span></span>\n            </button>\n            <button\n              id=\"mvRotateRightBtn\"\n              class=\"mv-toolbar__menu-button--rotate_right button-image\"\n              title=\"Rotate Clockwise\"\n              data-l10n-id=\"page_rotate_cw\"\n              (click)=\"rotate(90)\"\n              [disabled]=\"redactAllInProgress\"\n            >\n              <span></span>\n            </button>\n            <span>{{ \"Rotate\" | rpxTranslate }}</span>\n          </div>\n\n          <button\n            *ngIf=\"toolbarButtons.showSearchBar\"\n            [disabled]=\"icpEnabled || redactAllInProgress\"\n            id=\"mvSearchBtn\"\n            #mvSearchBtn\n            title=\"Search\"\n            data-l10n-id=\"searchbar\"\n            class=\"mv-button mv-toolbar__menu-button--search\"\n            [class.button-hidden-on-toolbar]=\"\n              mvToolbarMain.offsetWidth < widthRequiredForBtn['mvSearchBtn']\n            \"\n            [class.button-hidden-on-dropdown]=\"\n              mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvSearchBtn']\n            \"\n            aria-pressed=\"false\"\n            (click)=\"toggleSearchBar(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Search\" | rpxTranslate }}</span>\n          </button>\n          <mv-search-bar\n            *ngIf=\"!toolbarEvents.searchBarHidden.getValue()\"\n          ></mv-search-bar>\n\n          <button\n            *ngIf=\"enableICP && toolbarButtons.showPresentationMode && isPdf()\"\n            [disabled]=\"icpEnabled || !contentType || redactionEnabled\"\n            id=\"mvPresentBtn\"\n            #mvPresentBtn\n            class=\"mv-button mv-toolbar__menu-button--present\"\n            title=\"In-Court Presentation Mode\"\n            data-l10n-id=\"icpMode_label\"\n            [ngClass]=\"onToolBarOffSetChange('mvPresentBtn')\"\n            aria-pressed=\"false\"\n            (click)=\"togglePresentBar(); isDropdownMenuOpen = false\"\n          >\n            <span data-l10n-id=\"icpMode_label\">{{\n              \"Present\" | rpxTranslate\n            }}</span>\n          </button>\n\n          <button\n            *ngIf=\"enableRedactions && toolbarButtons.showRedact\"\n            [disabled]=\"icpEnabled || redactAllInProgress\"\n            id=\"mvRedactBtn\"\n            #mvRedactBtn\n            title=\"Redact\"\n            data-l10n-id=\"redact\"\n            class=\"mv-button mv-toolbar__menu-button--redact\"\n            [ngClass]=\"onToolBarOffSetChange('mvRedactBtn')\"\n            [attr.aria-expanded]=\"isRedactOpen\"\n            (click)=\"toggleRedactBar(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Redact\" | rpxTranslate }}</span>\n          </button>\n\n          <button\n            *ngIf=\"toolbarButtons.showGrabNDragButton\"\n            [disabled]=\"icpEnabled || redactAllInProgress\"\n            id=\"mvGrabBtn\"\n            #mvGrabBtn\n            class=\"mv-button mv-toolbar__menu-button--grab\"\n            title=\"Grab and drag\"\n            [ngClass]=\"onToolBarOffSetChange('mvGrabBtn')\"\n            aria-pressed=\"false\"\n            (click)=\"toggleGrabNDrag(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Grab and drag\" | rpxTranslate }}</span>\n          </button>\n\n          <button\n            *ngIf=\"toolbarButtons.showDownload\"\n            [disabled]=\"icpEnabled || redactionEnabled\"\n            id=\"mvDownloadBtn\"\n            #mvDownloadBtn\n            class=\"mv-button mv-toolbar__menu-button--download\"\n            title=\"Download\"\n            data-l10n-id=\"download\"\n            [ngClass]=\"onToolBarOffSetChange('mvDownloadBtn')\"\n            aria-pressed=\"false\"\n            (click)=\"downloadFile(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Download\" | rpxTranslate }}</span>\n          </button>\n\n          <button\n            *ngIf=\"toolbarButtons.showPrint\"\n            [disabled]=\"icpEnabled || redactionEnabled\"\n            id=\"mvPrintBtn\"\n            #mvPrintBtn\n            title=\"Print\"\n            data-l10n-id=\"print\"\n            class=\"mv-button mv-toolbar__menu-button--print\"\n            [ngClass]=\"onToolBarOffSetChange('mvPrintBtn')\"\n            aria-pressed=\"false\"\n            (click)=\"printFile(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Print\" | rpxTranslate }}</span>\n          </button>\n\n          <button\n            *ngIf=\"enableAnnotations && toolbarButtons.showCommentSummary\"\n            [disabled]=\"redactionEnabled\"\n            id=\"mvCommentsBtn\"\n            #mvCommentsBtn\n            class=\"mv-button mv-toolbar__menu-button--comments\"\n            title=\"Comments\"\n            data-l10n-id=\"comments\"\n            [ngClass]=\"onToolBarOffSetChange('mvCommentsBtn')\"\n            [attr.aria-expanded]=\"isCommentsOpen\"\n            (click)=\"toggleCommentsPanel(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Comments\" | rpxTranslate }}</span>\n          </button>\n        </ng-template>\n      </div>\n    </div>\n\n    <div id=\"loadingBar\">\n      <div class=\"progress\">\n        <div class=\"glimmer\"></div>\n      </div>\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i7.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i7.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: SearchBarComponent, selector: "mv-search-bar" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.DecimalPipe, name: "number" }, { kind: "pipe", type: i5$1.RpxTranslatePipe, name: "rpxTranslate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MainToolbarComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-main-toolbar', template: "<div class=\"toolbar\">\n  <div id=\"toolbarContainer\">\n    <div class=\"mv-toolbar__container\">\n      <div #mvToolbar class=\"mv-toolbar\" [class.notSupported]=\"!contentType\">\n        <!-- The mvToolbarMain div contains all toolbar buttons except the \"More options\" button. This allows for calculation of the available space to display buttons -->\n        <div id=\"mvToolbarMain\" class=\"mv-toolbar-main\" #mvToolbarMain>\n          <ng-container *ngTemplateOutlet=\"menuItems\"></ng-container>\n        </div>\n        <!-- The mvToolbarMoreOptions div contains the \"More options\" toolbar button (and the overlay template for the dropdown menu).\n            The space occupied by the button (if visible) is excluded from the toolbar space available calculation -->\n        <div id=\"mvToolbarMoreOptions\" class=\"mv-toolbar-more-options\">\n          <button\n            id=\"mvMoreOptionsBtn\"\n            class=\"mv-button mv-toolbar__menu-button--more-options\"\n            [class.mv-toolbar__menu-button--more-options__hidden]=\"\n              mvToolbar.offsetWidth >= allButtonsWidth\n            \"\n            [attr.aria-expanded]=\"isDropdownMenuOpen\"\n            (click)=\"toggleMoreOptions()\"\n            cdkOverlayOrigin\n            #trigger=\"cdkOverlayOrigin\"\n            [disabled]=\"redactAllInProgress\"\n          >\n            <span>{{ \"More options\" | rpxTranslate }}</span>\n          </button>\n          <!-- This template displays the overlay content for the dropdown menu and is connected to the \"More options\" button -->\n          <ng-template\n            cdkConnectedOverlay\n            [cdkConnectedOverlayOrigin]=\"trigger\"\n            [cdkConnectedOverlayOpen]=\"isDropdownMenuOpen\"\n            [cdkConnectedOverlayPositions]=\"dropdownMenuPositions\"\n          >\n            <div class=\"dropdown-menu\" #dropdownMenu tabindex=\"0\">\n              <ng-container *ngTemplateOutlet=\"menuItems\"></ng-container>\n            </div>\n          </ng-template>\n        </div>\n      </div>\n\n      <div id=\"mvMenuItems\" #mvMenuItems>\n        <ng-template #menuItems>\n          <button\n            *ngIf=\"toolbarButtons.showSidebar\"\n            id=\"mvIndexBtn\"\n            title=\"Index\"\n            data-l10n-id=\"index\"\n            #mvIndexBtn\n            class=\"mv-button mv-toolbar__menu-button--index\"\n            [class.button-hidden-on-toolbar]=\"\n              mvToolbarMain.offsetWidth < widthRequiredForBtn['mvIndexBtn']\n            \"\n            [class.button-hidden-on-dropdown]=\"\n              mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvIndexBtn']\n            \"\n            [attr.aria-expanded]=\"isIndexOpen\"\n            [disabled]=\"redactAllInProgress\"\n            (click)=\"toggleIndexSideBar(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Index\" | rpxTranslate }}</span>\n          </button>\n\n          <button\n            *ngIf=\"toolbarButtons.showSidebar\"\n            id=\"mvBookmarksBtn\"\n            title=\"Bookmarks\"\n            data-l10n-id=\"bookmarks\"\n            #mvBookmarksBtn\n            [ngClass]=\"{\n              'mv-button mv-toolbar__menu-button--bookmarks': true,\n              'button-hidden-on-toolbar':\n                mvToolbarMain.offsetWidth <\n                widthRequiredForBtn['mvBookmarksBtn'],\n              'button-hidden-on-dropdown':\n                mvToolbarMain.offsetWidth >=\n                widthRequiredForBtn['mvBookmarksBtn']\n            }\"\n            [attr.aria-expanded]=\"isBookmarksOpen\"\n            [disabled]=\"redactAllInProgress\"\n            (click)=\"toggleBookmarksSideBar(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Bookmarks\" | rpxTranslate }}</span>\n          </button>\n\n          <button\n            *ngIf=\"toolbarButtons.showDrawButton\"\n            [disabled]=\"icpEnabled || redactionEnabled\"\n            id=\"mvDrawBtn\"\n            #mvDrawBtn\n            class=\"mv-button mv-toolbar__menu-button--draw\"\n            title=\"Draw a box\"\n            [class.button-hidden-on-toolbar]=\"\n              mvToolbarMain.offsetWidth < widthRequiredForBtn['mvDrawBtn']\n            \"\n            [class.button-hidden-on-dropdown]=\"\n              mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvDrawBtn']\n            \"\n            [class.toggled]=\"toolbarEvents.drawModeSubject | async\"\n            aria-pressed=\"false\"\n            data-l10n-id=\"toggleDrawButton\"\n            (click)=\"onClickDrawToggle(); isDropdownMenuOpen = false\"\n          >\n            <span data-l10n-id=\"draw_label\">{{\n              \"Draw a box\" | rpxTranslate\n            }}</span>\n          </button>\n\n          <button\n            *ngIf=\"toolbarButtons.showHighlightButton\"\n            [disabled]=\"icpEnabled || redactionEnabled\"\n            id=\"mvHighlightBtn\"\n            #mvHighlightBtn\n            class=\"mv-button mv-toolbar__menu-button--highlight\"\n            title=\"Highlight\"\n            aria-label=\"Highlight\"\n            [class.button-hidden-on-toolbar]=\"\n              mvToolbarMain.offsetWidth < widthRequiredForBtn['mvHighlightBtn']\n            \"\n            [class.button-hidden-on-dropdown]=\"\n              mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvHighlightBtn']\n            \"\n            [class.toggled]=\"toolbarEvents.highlightToolbarSubject | async\"\n            aria-pressed=\"false\"\n            (click)=\"onClickHighlightToggle(); isDropdownMenuOpen = false\"\n            data-l10n-id=\"toggleHighlightButton\"\n          >\n            <span data-l10n-id=\"highlight_label\">{{\n              \"Highlight\" | rpxTranslate\n            }}</span>\n          </button>\n\n          <ng-container *ngIf=\"toolbarButtons.showNavigation\">\n            <div\n              id=\"mvPageBtn\"\n              #mvPageBtn\n              class=\"mv-toolbar__menu-button--page\"\n              [class.button-hidden-on-toolbar]=\"\n                mvToolbarMain.offsetWidth < widthRequiredForBtn['mvPageBtn']\n              \"\n              [class.button-hidden-on-dropdown]=\"\n                mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvPageBtn']\n              \"\n            >\n              <span>{{ \"Page\" | rpxTranslate }}</span>\n\n              <button\n                id=\"mvUpBtn\"\n                [disabled]=\"pageNumber === 1 || redactAllInProgress\"\n                title=\"Previous Page\"\n                class=\"mv-toolbar__menu-button--up button-image\"\n                data-l10n-id=\"previous\"\n                (click)=\"decreasePageNumber()\"\n                [disabled]=\"redactAllInProgress\"\n              >\n                <span></span>\n              </button>\n              <button\n                id=\"mvDownBtn\"\n                [disabled]=\"pageNumber === pageCount || redactAllInProgress\"\n                title=\"Next Page\"\n                class=\"mv-toolbar__menu-button--down button-image\"\n                data-l10n-id=\"next\"\n                (click)=\"increasePageNumber()\"\n              >\n                <span></span>\n              </button>\n\n              <input\n                type=\"number\"\n                id=\"pageNumber\"\n                class=\"hmcts-toolbar-input govuk-input--width-2\"\n                title=\"Page Number\"\n                value=\"1\"\n                size=\"4\"\n                min=\"1\"\n                [value]=\"pageNumber\"\n                aria-label=\"page number\"\n                tabindex=\"0\"\n                data-l10n-id=\"page\"\n                (change)=\"onPageNumberInputChange(pageNumberInput.value)\"\n                [disabled]=\"redactAllInProgress\"\n                #pageNumberInput\n              />\n              <span id=\"numPages\" class=\"toolbarLabel\">/ {{ pageCount }}</span>\n            </div>\n          </ng-container>\n\n          <ng-container *ngIf=\"toolbarButtons.showZoom\">\n            <div\n              id=\"mvZoomBtn\"\n              #mvZoomBtn\n              class=\"mv-toolbar__menu-button--zoom\"\n              aria-pressed=\"false\"\n              [class.button-hidden-on-toolbar]=\"\n                mvToolbarMain.offsetWidth < widthRequiredForBtn['mvZoomBtn']\n              \"\n              [class.button-hidden-on-dropdown]=\"\n                mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvZoomBtn']\n              \"\n            >\n              <button\n                [disabled]=\"\n                  toolbarEvents.zoomValueSubject.value === 0.1 ||\n                  redactAllInProgress\n                \"\n                id=\"mvMinusBtn\"\n                class=\"mv-toolbar__menu-button--zoom-out button-image\"\n                title=\"Zoom Out\"\n                data-l10n-id=\"zoom_out\"\n                (click)=\"stepZoom(-0.1)\"\n              >\n                <span class=\"mv-toolbar__menu-button--zoom-out-text\">{{\n                  \"Zoom Out\" | rpxTranslate\n                }}</span>\n              </button>\n              <select\n                id=\"scaleSelect\"\n                class=\"hmcts-toolbar-select\"\n                title=\"Zoom\"\n                tabindex=\"0\"\n                data-l10n-id=\"zoom\"\n                (change)=\"zoom($event.target.value)\"\n                aria-label=\"zoom\"\n                [disabled]=\"redactAllInProgress\"\n              >\n                <option\n                  #zoomSelect\n                  id=\"customScaleOption\"\n                  title=\"\"\n                  [value]=\"toolbarEvents.zoomValueSubject.value\"\n                >\n                  {{\n                    toolbarEvents.zoomValueSubject.value * 100\n                      | number : \"1.0-0\"\n                  }}%\n                </option>\n                <option\n                  *ngFor=\"let zoomScale of zoomScales\"\n                  title=\"\"\n                  [value]=\"zoomScale\"\n                  [attr.data-l10n-id]=\"'page_scale_percent_' + zoomScale * 100\"\n                >\n                  {{ zoomScale * 100 }}%\n                </option>\n              </select>\n\n              <button\n                [disabled]=\"\n                  toolbarEvents.zoomValueSubject.value === 5 ||\n                  redactAllInProgress\n                \"\n                id=\"mvPlusBtn\"\n                class=\"mv-toolbar__menu-button--zoom-in button-image\"\n                (click)=\"stepZoom(0.1)\"\n                title=\"Zoom In\"\n                data-l10n-id=\"zoom_in\"\n              >\n                <span class=\"mv-toolbar__menu-button--zoom-out-text\">{{\n                  \"Zoom In\" | rpxTranslate\n                }}</span>\n              </button>\n            </div>\n          </ng-container>\n\n          <div\n            *ngIf=\"toolbarButtons.showRotate\"\n            id=\"mvRotateBtn\"\n            #mvRotateBtn\n            class=\"mv-toolbar__menu-button--rotate\"\n            [class.button-hidden-on-toolbar]=\"\n              mvToolbarMain.offsetWidth < widthRequiredForBtn['mvRotateBtn']\n            \"\n            [class.button-hidden-on-dropdown]=\"\n              mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvRotateBtn']\n            \"\n          >\n            <button\n              id=\"mvRotateLeftBtn\"\n              class=\"mv-toolbar__menu-button--rotate_left button-image\"\n              title=\"Rotate Counterclockwise\"\n              data-l10n-id=\"page_rotate_ccw\"\n              (click)=\"rotate(270)\"\n              [disabled]=\"redactAllInProgress\"\n            >\n              <span></span>\n            </button>\n            <button\n              id=\"mvRotateRightBtn\"\n              class=\"mv-toolbar__menu-button--rotate_right button-image\"\n              title=\"Rotate Clockwise\"\n              data-l10n-id=\"page_rotate_cw\"\n              (click)=\"rotate(90)\"\n              [disabled]=\"redactAllInProgress\"\n            >\n              <span></span>\n            </button>\n            <span>{{ \"Rotate\" | rpxTranslate }}</span>\n          </div>\n\n          <button\n            *ngIf=\"toolbarButtons.showSearchBar\"\n            [disabled]=\"icpEnabled || redactAllInProgress\"\n            id=\"mvSearchBtn\"\n            #mvSearchBtn\n            title=\"Search\"\n            data-l10n-id=\"searchbar\"\n            class=\"mv-button mv-toolbar__menu-button--search\"\n            [class.button-hidden-on-toolbar]=\"\n              mvToolbarMain.offsetWidth < widthRequiredForBtn['mvSearchBtn']\n            \"\n            [class.button-hidden-on-dropdown]=\"\n              mvToolbarMain.offsetWidth >= widthRequiredForBtn['mvSearchBtn']\n            \"\n            aria-pressed=\"false\"\n            (click)=\"toggleSearchBar(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Search\" | rpxTranslate }}</span>\n          </button>\n          <mv-search-bar\n            *ngIf=\"!toolbarEvents.searchBarHidden.getValue()\"\n          ></mv-search-bar>\n\n          <button\n            *ngIf=\"enableICP && toolbarButtons.showPresentationMode && isPdf()\"\n            [disabled]=\"icpEnabled || !contentType || redactionEnabled\"\n            id=\"mvPresentBtn\"\n            #mvPresentBtn\n            class=\"mv-button mv-toolbar__menu-button--present\"\n            title=\"In-Court Presentation Mode\"\n            data-l10n-id=\"icpMode_label\"\n            [ngClass]=\"onToolBarOffSetChange('mvPresentBtn')\"\n            aria-pressed=\"false\"\n            (click)=\"togglePresentBar(); isDropdownMenuOpen = false\"\n          >\n            <span data-l10n-id=\"icpMode_label\">{{\n              \"Present\" | rpxTranslate\n            }}</span>\n          </button>\n\n          <button\n            *ngIf=\"enableRedactions && toolbarButtons.showRedact\"\n            [disabled]=\"icpEnabled || redactAllInProgress\"\n            id=\"mvRedactBtn\"\n            #mvRedactBtn\n            title=\"Redact\"\n            data-l10n-id=\"redact\"\n            class=\"mv-button mv-toolbar__menu-button--redact\"\n            [ngClass]=\"onToolBarOffSetChange('mvRedactBtn')\"\n            [attr.aria-expanded]=\"isRedactOpen\"\n            (click)=\"toggleRedactBar(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Redact\" | rpxTranslate }}</span>\n          </button>\n\n          <button\n            *ngIf=\"toolbarButtons.showGrabNDragButton\"\n            [disabled]=\"icpEnabled || redactAllInProgress\"\n            id=\"mvGrabBtn\"\n            #mvGrabBtn\n            class=\"mv-button mv-toolbar__menu-button--grab\"\n            title=\"Grab and drag\"\n            [ngClass]=\"onToolBarOffSetChange('mvGrabBtn')\"\n            aria-pressed=\"false\"\n            (click)=\"toggleGrabNDrag(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Grab and drag\" | rpxTranslate }}</span>\n          </button>\n\n          <button\n            *ngIf=\"toolbarButtons.showDownload\"\n            [disabled]=\"icpEnabled || redactionEnabled\"\n            id=\"mvDownloadBtn\"\n            #mvDownloadBtn\n            class=\"mv-button mv-toolbar__menu-button--download\"\n            title=\"Download\"\n            data-l10n-id=\"download\"\n            [ngClass]=\"onToolBarOffSetChange('mvDownloadBtn')\"\n            aria-pressed=\"false\"\n            (click)=\"downloadFile(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Download\" | rpxTranslate }}</span>\n          </button>\n\n          <button\n            *ngIf=\"toolbarButtons.showPrint\"\n            [disabled]=\"icpEnabled || redactionEnabled\"\n            id=\"mvPrintBtn\"\n            #mvPrintBtn\n            title=\"Print\"\n            data-l10n-id=\"print\"\n            class=\"mv-button mv-toolbar__menu-button--print\"\n            [ngClass]=\"onToolBarOffSetChange('mvPrintBtn')\"\n            aria-pressed=\"false\"\n            (click)=\"printFile(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Print\" | rpxTranslate }}</span>\n          </button>\n\n          <button\n            *ngIf=\"enableAnnotations && toolbarButtons.showCommentSummary\"\n            [disabled]=\"redactionEnabled\"\n            id=\"mvCommentsBtn\"\n            #mvCommentsBtn\n            class=\"mv-button mv-toolbar__menu-button--comments\"\n            title=\"Comments\"\n            data-l10n-id=\"comments\"\n            [ngClass]=\"onToolBarOffSetChange('mvCommentsBtn')\"\n            [attr.aria-expanded]=\"isCommentsOpen\"\n            (click)=\"toggleCommentsPanel(); isDropdownMenuOpen = false\"\n          >\n            <span>{{ \"Comments\" | rpxTranslate }}</span>\n          </button>\n        </ng-template>\n      </div>\n    </div>\n\n    <div id=\"loadingBar\">\n      <div class=\"progress\">\n        <div class=\"glimmer\"></div>\n      </div>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: ToolbarButtonVisibilityService }, { type: i0.ChangeDetectorRef }, { type: NumberHelperService }, { type: IcpEventService }], propDecorators: { enableAnnotations: [{
                type: Input
            }], enableRedactions: [{
                type: Input
            }], enableICP: [{
                type: Input
            }], contentType: [{
                type: Input
            }], zoomSelect: [{
                type: ViewChild,
                args: ['zoomSelect', { static: false }]
            }], mvToolbarMain: [{
                type: ViewChild,
                args: ['mvToolbarMain', { static: false }]
            }], mvMenuItems: [{
                type: ViewChild,
                args: ['dropdownMenu', { static: false }]
            }], onResize: [{
                type: HostListener,
                args: ['window:resize', []]
            }], onControlPrint: [{
                type: HostListener,
                args: ['document:keydown.control.p', ['$event']]
            }, {
                type: HostListener,
                args: ['document:keydown.meta.p', ['$event']]
            }] } });

class RedactionToolbarComponent {
    constructor(toolbarEventService, toolbarButtons, store) {
        this.toolbarEventService = toolbarEventService;
        this.toolbarButtons = toolbarButtons;
        this.store = store;
        this.preview = false;
        this.hasRedactions = false;
        this.subscriptions = [];
    }
    ngOnInit() {
        this.subscriptions.push(this.store.pipe(select(getRedactionArray)).subscribe(redactions => {
            this.hasRedactions = !!redactions.redactions.length;
        }));
        this.subscriptions.push(this.toolbarEventService.redactAllInProgressSubject.subscribe(inprogress => {
            this.redactionAllInProgress = inprogress;
        }));
    }
    onRedactAllSearch() {
        this.toolbarEventService.openRedactionSearch.next({ modeType: SearchType.Redact, isOpen: true });
    }
    toggleTextRedactionMode() {
        this.toolbarEventService.highlightModeSubject.next(true);
    }
    toggleDrawMode() {
        this.toolbarEventService.drawModeSubject.next(true);
    }
    togglePreview() {
        this.preview = !this.preview;
        this.toolbarEventService.toggleRedactionPreview(this.preview);
    }
    unmarkAll() {
        this.toolbarEventService.unmarkAll();
    }
    redact() {
        this.toolbarEventService.applyRedactionToDocument();
    }
    toggleRedactBar() {
        this.toolbarEventService.toggleRedactionMode();
    }
    redactPage() {
        this.toolbarEventService.drawModeSubject.next(true);
        this.toolbarEventService.redactPage();
    }
    ngOnDestroy() {
        for (const subscription of this.subscriptions) {
            subscription.unsubscribe();
        }
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedactionToolbarComponent, deps: [{ token: ToolbarEventService }, { token: ToolbarButtonVisibilityService }, { token: i1.Store }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: RedactionToolbarComponent, selector: "mv-redaction-toolbar", inputs: { showRedactSearch: "showRedactSearch" }, ngImport: i0, template: "<div class=\"redaction\">\n  <label class=\"govuk-label redaction-title\" data-l10n-id=\"redaction_options\">{{\n    \"Redaction options\" | rpxTranslate\n  }}</label>\n  <button\n    id=\"toggleDrawButton\"\n    class=\"mv-button redaction-button--draw\"\n    title=\"{{ 'Draw a box' | rpxTranslate }}}\"\n    data-l10n-id=\"toggleDrawButton\"\n    (click)=\"toggleDrawMode()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"toggleDrawButton_label\">{{\n      \"Draw a box\" | rpxTranslate\n    }}</span>\n  </button>\n\n  <button\n    id=\"redactPageButton\"\n    class=\"mv-button redaction-button--redact-page\"\n    title=\"{{ 'Redact page' | rpxTranslate }}\"\n    data-l10n-id=\"redactPageButton\"\n    (click)=\"redactPage()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"redactPageButton_label\">{{\n      \"Redact page\" | rpxTranslate\n    }}</span>\n  </button>\n  <button\n    *ngIf=\"showRedactSearch\"\n    id=\"mvRedactFromSearchBtn\"\n    title=\"{{ 'From search' | rpxTranslate }}\"\n    data-l10n-id=\"fromSearchButton\"\n    class=\"mv-button redaction-button--search\"\n    (click)=\"onRedactAllSearch()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span style=\"width: 5rem\" data-l10n-id=\"fromSearchButton_label\">{{\n      \"From search\" | rpxTranslate\n    }}</span>\n  </button>\n\n  <button\n    *ngIf=\"toolbarButtons.showHighlightButton\"\n    id=\"toggleHighlightButton\"\n    class=\"mv-button redaction-button--redact\"\n    aria-pressed=\"false\"\n    title=\"{{ 'Redact text' | rpxTranslate }}\"\n    data-l10n-id=\"toggleTextRedactionButton\"\n    (click)=\"toggleTextRedactionMode()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"toggleTextRedactionButton_label\">{{\n      \"Redact text\" | rpxTranslate\n    }}</span>\n  </button>\n\n  <button\n    [disabled]=\"!hasRedactions || redactionAllInProgress\"\n    id=\"mvClearBtn\"\n    #mvClearBtn\n    class=\"mv-button redaction-button--clear\"\n    aria-pressed=\"false\"\n    title=\"{{ 'Clear all' | rpxTranslate }}\"\n    data-l10n-id=\"toggleClearAllButton\"\n    (click)=\"unmarkAll()\"\n  >\n    <span data-l10n-id=\"Clear all\">{{ \"Clear all\" | rpxTranslate }}</span>\n  </button>\n\n  <button\n    [disabled]=\"!hasRedactions || redactionAllInProgress\"\n    id=\"mvPreviewBtn\"\n    class=\"mv-button\"\n    [class.redaction-button--preview]=\"!preview\"\n    [class.redaction-button--hide-preview]=\"preview\"\n    redaction-button--preview\n    aria-pressed=\"false\"\n    title=\"{{ 'Preview' | rpxTranslate }}\"\n    data-l10n-id=\"togglePreviewButton\"\n    (click)=\"togglePreview()\"\n  >\n    <span *ngIf=\"!preview\" data-l10n-id=\"redaction-preview_label\">{{\n      \"Preview\" | rpxTranslate\n    }}</span>\n    <span *ngIf=\"preview\" data-l10n-id=\"redaction-hide-preview_label\">{{\n      \"Hide preview\" | rpxTranslate\n    }}</span>\n  </button>\n\n  <button\n    [disabled]=\"!hasRedactions || redactionAllInProgress\"\n    id=\"mvRedactBtn\"\n    class=\"mv-button redaction-button--download\"\n    aria-pressed=\"false\"\n    title=\"{{ 'Save document' | rpxTranslate }}\"\n    data-l10n-id=\"mvRedactBtn\"\n    (click)=\"redact()\"\n  >\n    <span data-l10n-id=\"Save Document\">{{\n      \"Save document\" | rpxTranslate\n    }}</span>\n  </button>\n\n  <button\n    id=\"mvCloseBtn\"\n    #mvCloseBtn\n    class=\"mv-button redaction-button--close\"\n    title=\"{{ 'Close Redaction' | rpxTranslate }}\"\n    data-l10n-id=\"mvRedactBtn\"\n    (click)=\"toggleRedactBar()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"Close Redaction\">{{\n      \"Close Redaction\" | rpxTranslate\n    }}</span>\n  </button>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i5$1.RpxTranslatePipe, name: "rpxTranslate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedactionToolbarComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-redaction-toolbar', template: "<div class=\"redaction\">\n  <label class=\"govuk-label redaction-title\" data-l10n-id=\"redaction_options\">{{\n    \"Redaction options\" | rpxTranslate\n  }}</label>\n  <button\n    id=\"toggleDrawButton\"\n    class=\"mv-button redaction-button--draw\"\n    title=\"{{ 'Draw a box' | rpxTranslate }}}\"\n    data-l10n-id=\"toggleDrawButton\"\n    (click)=\"toggleDrawMode()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"toggleDrawButton_label\">{{\n      \"Draw a box\" | rpxTranslate\n    }}</span>\n  </button>\n\n  <button\n    id=\"redactPageButton\"\n    class=\"mv-button redaction-button--redact-page\"\n    title=\"{{ 'Redact page' | rpxTranslate }}\"\n    data-l10n-id=\"redactPageButton\"\n    (click)=\"redactPage()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"redactPageButton_label\">{{\n      \"Redact page\" | rpxTranslate\n    }}</span>\n  </button>\n  <button\n    *ngIf=\"showRedactSearch\"\n    id=\"mvRedactFromSearchBtn\"\n    title=\"{{ 'From search' | rpxTranslate }}\"\n    data-l10n-id=\"fromSearchButton\"\n    class=\"mv-button redaction-button--search\"\n    (click)=\"onRedactAllSearch()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span style=\"width: 5rem\" data-l10n-id=\"fromSearchButton_label\">{{\n      \"From search\" | rpxTranslate\n    }}</span>\n  </button>\n\n  <button\n    *ngIf=\"toolbarButtons.showHighlightButton\"\n    id=\"toggleHighlightButton\"\n    class=\"mv-button redaction-button--redact\"\n    aria-pressed=\"false\"\n    title=\"{{ 'Redact text' | rpxTranslate }}\"\n    data-l10n-id=\"toggleTextRedactionButton\"\n    (click)=\"toggleTextRedactionMode()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"toggleTextRedactionButton_label\">{{\n      \"Redact text\" | rpxTranslate\n    }}</span>\n  </button>\n\n  <button\n    [disabled]=\"!hasRedactions || redactionAllInProgress\"\n    id=\"mvClearBtn\"\n    #mvClearBtn\n    class=\"mv-button redaction-button--clear\"\n    aria-pressed=\"false\"\n    title=\"{{ 'Clear all' | rpxTranslate }}\"\n    data-l10n-id=\"toggleClearAllButton\"\n    (click)=\"unmarkAll()\"\n  >\n    <span data-l10n-id=\"Clear all\">{{ \"Clear all\" | rpxTranslate }}</span>\n  </button>\n\n  <button\n    [disabled]=\"!hasRedactions || redactionAllInProgress\"\n    id=\"mvPreviewBtn\"\n    class=\"mv-button\"\n    [class.redaction-button--preview]=\"!preview\"\n    [class.redaction-button--hide-preview]=\"preview\"\n    redaction-button--preview\n    aria-pressed=\"false\"\n    title=\"{{ 'Preview' | rpxTranslate }}\"\n    data-l10n-id=\"togglePreviewButton\"\n    (click)=\"togglePreview()\"\n  >\n    <span *ngIf=\"!preview\" data-l10n-id=\"redaction-preview_label\">{{\n      \"Preview\" | rpxTranslate\n    }}</span>\n    <span *ngIf=\"preview\" data-l10n-id=\"redaction-hide-preview_label\">{{\n      \"Hide preview\" | rpxTranslate\n    }}</span>\n  </button>\n\n  <button\n    [disabled]=\"!hasRedactions || redactionAllInProgress\"\n    id=\"mvRedactBtn\"\n    class=\"mv-button redaction-button--download\"\n    aria-pressed=\"false\"\n    title=\"{{ 'Save document' | rpxTranslate }}\"\n    data-l10n-id=\"mvRedactBtn\"\n    (click)=\"redact()\"\n  >\n    <span data-l10n-id=\"Save Document\">{{\n      \"Save document\" | rpxTranslate\n    }}</span>\n  </button>\n\n  <button\n    id=\"mvCloseBtn\"\n    #mvCloseBtn\n    class=\"mv-button redaction-button--close\"\n    title=\"{{ 'Close Redaction' | rpxTranslate }}\"\n    data-l10n-id=\"mvRedactBtn\"\n    (click)=\"toggleRedactBar()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"Close Redaction\">{{\n      \"Close Redaction\" | rpxTranslate\n    }}</span>\n  </button>\n</div>\n" }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: ToolbarButtonVisibilityService }, { type: i1.Store }], propDecorators: { showRedactSearch: [{
                type: Input
            }] } });

class IcpToolbarComponent {
    constructor(toolbarEventService, store, icpEventService) {
        this.toolbarEventService = toolbarEventService;
        this.store = store;
        this.icpEventService = icpEventService;
    }
    ngOnInit() {
        this.$subscription = this.store.pipe(select(isPresenter))
            .subscribe(isPresenter => this.isPresenter = isPresenter);
        this.$subscription.add(this.store.pipe(select(getPresenterName))
            .subscribe(name => this.presenterName = name));
    }
    ngOnDestroy() {
        this.$subscription.unsubscribe();
    }
    present() {
        this.icpEventService.becomePresenter();
    }
    stopPresenting() {
        this.icpEventService.stopPresenting();
    }
    leaveIcpSession() {
        this.icpEventService.leaveSession();
    }
    showParticipantsList() {
        this.toolbarEventService.toggleParticipantsList(!this.icpEventService.participantsListVisible.getValue());
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpToolbarComponent, deps: [{ token: ToolbarEventService }, { token: i1.Store }, { token: IcpEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: IcpToolbarComponent, selector: "mv-icp-toolbar", ngImport: i0, template: "<div id=\"icp-toolbar\" class=\"icpMode\">\n  <div id=\"toolbar-title\">\n    <label class=\"govuk-label\" data-l10n-id=\"digitalEvidence_label\">Digital evidence presentation</label>\n  </div>\n\n  <div id=\"presentation-mode\">\n    <div class=\"item-label\">\n      <label class=\"govuk-label\" data-l10n-id=\"icpInfo_label\">You are in presentation mode</label>\n    </div>\n    <div class=\"item-button\">\n      <button class=\"govuk-button govuk-button--secondary\" data-module=\"govuk-button\" tabindex=\"0\"\n        title=\"Leave presentation\" (click)=\"leaveIcpSession()\">\n        <span data-l10n-id=\"icp-leave-presentation_label\">Leave presentation</span>\n      </button>\n    </div>\n  </div>\n\n  <div id=\"presenter-info\">\n    <div class=\"item-label\">\n      <label class=\"govuk-label\" *ngIf=\"!presenterName\" data-l10n-id=\"noPresenter_label\">Waiting for presenter</label>\n      <label class=\"govuk-label\" *ngIf=\"presenterName && isPresenter\" data-l10n-id=\"isPresenter_label\">You are\n        presenting</label>\n      <label class=\"govuk-label\" *ngIf=\"presenterName && !isPresenter\"\n        data-l10n-id=\"otherPresenter_label\">{{ presenterName | titlecase }}\n        is presenting</label>\n    </div>\n    <div class=\"item-button\">\n      <button *ngIf=\"!presenterName\" class=\"govuk-button\" id=\"icp-present\" tabindex=\"0\" title=\"Present\"\n        (click)=\"present()\">\n        <span data-l10n-id=\"icp-present_label\">Start presenting</span>\n      </button>\n      <button *ngIf=\"isPresenter\" class=\"govuk-button  govuk-button--warning\" id=\"icp-stop-presenting\" tabindex=\"0\"\n        title=\"Stop presenting\" (click)=\"stopPresenting()\">\n        <span data-l10n-id=\"icp-stop-presenting_label\">Stop Presenting</span>\n      </button>\n    </div>\n  </div>\n\n  <div id=\"participant-list\">\n    <button class=\"govuk-button govuk-button--secondary\" id=\"icp-participants-list\" tabindex=\"0\"\n      title=\"Participants list\" (click)=\"showParticipantsList()\">\n      <span\n        data-l10n-id=\"icp-stop-presenting_label\">{{(icpEventService.participantsListVisible | async) ? 'Hide': 'Show'}}\n        participants</span>\n    </button>\n  </div>\n</div>", dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.TitleCasePipe, name: "titlecase" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpToolbarComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-icp-toolbar', template: "<div id=\"icp-toolbar\" class=\"icpMode\">\n  <div id=\"toolbar-title\">\n    <label class=\"govuk-label\" data-l10n-id=\"digitalEvidence_label\">Digital evidence presentation</label>\n  </div>\n\n  <div id=\"presentation-mode\">\n    <div class=\"item-label\">\n      <label class=\"govuk-label\" data-l10n-id=\"icpInfo_label\">You are in presentation mode</label>\n    </div>\n    <div class=\"item-button\">\n      <button class=\"govuk-button govuk-button--secondary\" data-module=\"govuk-button\" tabindex=\"0\"\n        title=\"Leave presentation\" (click)=\"leaveIcpSession()\">\n        <span data-l10n-id=\"icp-leave-presentation_label\">Leave presentation</span>\n      </button>\n    </div>\n  </div>\n\n  <div id=\"presenter-info\">\n    <div class=\"item-label\">\n      <label class=\"govuk-label\" *ngIf=\"!presenterName\" data-l10n-id=\"noPresenter_label\">Waiting for presenter</label>\n      <label class=\"govuk-label\" *ngIf=\"presenterName && isPresenter\" data-l10n-id=\"isPresenter_label\">You are\n        presenting</label>\n      <label class=\"govuk-label\" *ngIf=\"presenterName && !isPresenter\"\n        data-l10n-id=\"otherPresenter_label\">{{ presenterName | titlecase }}\n        is presenting</label>\n    </div>\n    <div class=\"item-button\">\n      <button *ngIf=\"!presenterName\" class=\"govuk-button\" id=\"icp-present\" tabindex=\"0\" title=\"Present\"\n        (click)=\"present()\">\n        <span data-l10n-id=\"icp-present_label\">Start presenting</span>\n      </button>\n      <button *ngIf=\"isPresenter\" class=\"govuk-button  govuk-button--warning\" id=\"icp-stop-presenting\" tabindex=\"0\"\n        title=\"Stop presenting\" (click)=\"stopPresenting()\">\n        <span data-l10n-id=\"icp-stop-presenting_label\">Stop Presenting</span>\n      </button>\n    </div>\n  </div>\n\n  <div id=\"participant-list\">\n    <button class=\"govuk-button govuk-button--secondary\" id=\"icp-participants-list\" tabindex=\"0\"\n      title=\"Participants list\" (click)=\"showParticipantsList()\">\n      <span\n        data-l10n-id=\"icp-stop-presenting_label\">{{(icpEventService.participantsListVisible | async) ? 'Hide': 'Show'}}\n        participants</span>\n    </button>\n  </div>\n</div>" }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: i1.Store }, { type: IcpEventService }] });

class HighlightToolbarComponent {
    constructor(toolbarEventService, toolbarButtons) {
        this.toolbarEventService = toolbarEventService;
        this.toolbarButtons = toolbarButtons;
        this.subscriptions = [];
    }
    ngOnInit() {
        this.subscriptions.push(this.toolbarEventService.redactAllInProgressSubject.subscribe(inprogress => {
            this.redactionAllInProgress = inprogress;
        }));
    }
    onAllSearch() {
        this.toolbarEventService.openRedactionSearch.next({ modeType: SearchType.Highlight, isOpen: true });
    }
    onHighlight() {
        this.toolbarEventService.toggleHighlightMode();
    }
    onClickDrawToggle() {
        this.toolbarEventService.toggleDrawMode();
    }
    onClose() {
        this.toolbarEventService.highlightToolbarSubject.next(false);
        this.toolbarEventService.highlightModeSubject.next(false);
        this.toolbarEventService.openRedactionSearch.next({ modeType: SearchType.Highlight, isOpen: false });
    }
    ngOnDestroy() {
        for (const subscription of this.subscriptions) {
            subscription.unsubscribe();
        }
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HighlightToolbarComponent, deps: [{ token: ToolbarEventService }, { token: ToolbarButtonVisibilityService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: HighlightToolbarComponent, selector: "mv-highlight-toolbar", ngImport: i0, template: "<div class=\"redaction\">\n  <label class=\"govuk-label redaction-title\" data-l10n-id=\"redaction_options\"\n    >Highlight options</label\n  >\n\n  <button\n    id=\"mvDrawBtn\"\n    #mvDrawBtn\n    class=\"mv-button mv-toolbar__menu-button--draw\"\n    title=\"Draw a box\"\n    [class.toggled]=\"toolbarEventService.drawModeSubject | async\"\n    aria-pressed=\"false\"\n    data-l10n-id=\"mvDrawBtn\"\n    (click)=\"onClickDrawToggle()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"draw_label\">Draw a box</span>\n  </button>\n\n  <button\n    id=\"highlightTextBtn\"\n    class=\"mv-button mv-toolbar__menu-button--highlight\"\n    title=\"Highlight text\"\n    data-l10n-id=\"highlightTextBtn\"\n    (click)=\"onHighlight()\"\n    [class.toggled]=\"toolbarEventService.highlightModeSubject | async\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"highlightTextBtn_label\">Highlight text</span>\n  </button>\n\n  <button\n    id=\"mvHighlightFromSearchBtn\"\n    title=\"From search\"\n    data-l10n-id=\"fromSearchButton\"\n    class=\"mv-button redaction-button--search\"\n    (click)=\"onAllSearch()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span style=\"width: 5rem\" data-l10n-id=\"fromSearchButton_label\"\n      >From search</span\n    >\n  </button>\n\n  <button\n    id=\"mvCloseBtn\"\n    #mvCloseBtn\n    class=\"mv-button redaction-button--close\"\n    title=\"Close Redaction\"\n    data-l10n-id=\"mvRedactBtn\"\n    (click)=\"onClose()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"Close Redaction\">Close Highlight</span>\n  </button>\n</div>\n", styles: [""], dependencies: [{ kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HighlightToolbarComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-highlight-toolbar', template: "<div class=\"redaction\">\n  <label class=\"govuk-label redaction-title\" data-l10n-id=\"redaction_options\"\n    >Highlight options</label\n  >\n\n  <button\n    id=\"mvDrawBtn\"\n    #mvDrawBtn\n    class=\"mv-button mv-toolbar__menu-button--draw\"\n    title=\"Draw a box\"\n    [class.toggled]=\"toolbarEventService.drawModeSubject | async\"\n    aria-pressed=\"false\"\n    data-l10n-id=\"mvDrawBtn\"\n    (click)=\"onClickDrawToggle()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"draw_label\">Draw a box</span>\n  </button>\n\n  <button\n    id=\"highlightTextBtn\"\n    class=\"mv-button mv-toolbar__menu-button--highlight\"\n    title=\"Highlight text\"\n    data-l10n-id=\"highlightTextBtn\"\n    (click)=\"onHighlight()\"\n    [class.toggled]=\"toolbarEventService.highlightModeSubject | async\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"highlightTextBtn_label\">Highlight text</span>\n  </button>\n\n  <button\n    id=\"mvHighlightFromSearchBtn\"\n    title=\"From search\"\n    data-l10n-id=\"fromSearchButton\"\n    class=\"mv-button redaction-button--search\"\n    (click)=\"onAllSearch()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span style=\"width: 5rem\" data-l10n-id=\"fromSearchButton_label\"\n      >From search</span\n    >\n  </button>\n\n  <button\n    id=\"mvCloseBtn\"\n    #mvCloseBtn\n    class=\"mv-button redaction-button--close\"\n    title=\"Close Redaction\"\n    data-l10n-id=\"mvRedactBtn\"\n    (click)=\"onClose()\"\n    [disabled]=\"redactionAllInProgress\"\n  >\n    <span data-l10n-id=\"Close Redaction\">Close Highlight</span>\n  </button>\n</div>\n" }]
        }], ctorParameters: () => [{ type: ToolbarEventService }, { type: ToolbarButtonVisibilityService }] });

/*
* Gov UK Error Message
* Responsible for displaying in-line error messages
* @prop config - obj with properties
* @prop errorMessage - all error bject with messages property that is arry of strings.
* */
class GovUkErrorMessageComponent {
    constructor() { }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GovUkErrorMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GovUkErrorMessageComponent, selector: " mv-gov-uk-error-message", inputs: { config: "config", errorMessage: "errorMessage" }, ngImport: i0, template: `
    <span class="govuk-error-message" [id]="config.id + '-error'" *ngFor="let message of errorMessage?.messages">
      <span class="govuk-visually-hidden">Error:</span>{{message}}
    </span>
  `, isInline: true, dependencies: [{ kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GovUkErrorMessageComponent, decorators: [{
            type: Component,
            args: [{
                    selector: ' mv-gov-uk-error-message',
                    template: `
    <span class="govuk-error-message" [id]="config.id + '-error'" *ngFor="let message of errorMessage?.messages">
      <span class="govuk-visually-hidden">Error:</span>{{message}}
    </span>
  `
                }]
        }], ctorParameters: () => [], propDecorators: { config: [{
                type: Input
            }], errorMessage: [{
                type: Input
            }] } });

/*
* Gov Uk Fieldset Component
* Used to wrap group fieldset elements
* it can conditionally display h1 tag
* @param config
* @param isHeading
* @param errorMessage - used for aria tag
* */
class GovUkFieldsetComponent {
    setDescribedBy() {
        return HtmlTemplatesHelper.setDescribedBy(this.errorMessage, this.config);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GovUkFieldsetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GovUkFieldsetComponent, selector: "mv-gov-uk-fieldset", inputs: { config: "config", isHeading: "isHeading", errorMessage: "errorMessage" }, ngImport: i0, template: `
      <fieldset class="govuk-fieldset" [attr.aria-describedby]="setDescribedBy()">
        <legend [class]="config.classes + ' govuk-fieldset__legend'" *ngIf="!isHeading">
          {{config.legend}}
        </legend>

        <legend [class]="config.classes + ' govuk-fieldset__legend'" *ngIf="isHeading">
          <h1>{{config.legend}}</h1>
        </legend>

        <span [id]="config.id+'-hint'" class="govuk-hint" *ngIf="config.hint">
          {{config.hint}}
        </span>
        <ng-content></ng-content>
      </fieldset>
  `, isInline: true, dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GovUkFieldsetComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'mv-gov-uk-fieldset',
                    template: `
      <fieldset class="govuk-fieldset" [attr.aria-describedby]="setDescribedBy()">
        <legend [class]="config.classes + ' govuk-fieldset__legend'" *ngIf="!isHeading">
          {{config.legend}}
        </legend>

        <legend [class]="config.classes + ' govuk-fieldset__legend'" *ngIf="isHeading">
          <h1>{{config.legend}}</h1>
        </legend>

        <span [id]="config.id+'-hint'" class="govuk-hint" *ngIf="config.hint">
          {{config.hint}}
        </span>
        <ng-content></ng-content>
      </fieldset>
  `
                }]
        }], propDecorators: { config: [{
                type: Input
            }], isHeading: [{
                type: Input
            }], errorMessage: [{
                type: Input
            }] } });

/*
* Gov UK Label component
* Responsible for displaying label tag
* @prop isPageHading - boolean to display h1
* @prop config - obj with properties
* */
class GovUkLabelComponent {
    constructor() { }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GovUkLabelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GovUkLabelComponent, selector: "mv-gov-label", inputs: { config: "config" }, ngImport: i0, template: `<h1 *ngIf="config.isPageHeading else noHeading">
          <label *ngIf="config.label" [class]="config.classes + ' govuk-label'"
                 [for]="config.id" [innerHTML]="config.label">
          </label>
        </h1>
        <ng-template #noHeading>
          <label *ngIf="config.label" [class]="config.classes + ' govuk-label'"
                 [for]="config.id" [innerHTML]="config.label">
          </label>
        </ng-template>
  `, isInline: true, dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GovUkLabelComponent, decorators: [{
            type: Component,
            args: [{
                    selector: 'mv-gov-label',
                    template: `<h1 *ngIf="config.isPageHeading else noHeading">
          <label *ngIf="config.label" [class]="config.classes + ' govuk-label'"
                 [for]="config.id" [innerHTML]="config.label">
          </label>
        </h1>
        <ng-template #noHeading>
          <label *ngIf="config.label" [class]="config.classes + ' govuk-label'"
                 [for]="config.id" [innerHTML]="config.label">
          </label>
        </ng-template>
  `
                }]
        }], ctorParameters: () => [], propDecorators: { config: [{
                type: Input
            }] } });

/*
* Gov UK Date Component
* Responsible for displaying 3 input fields:
* day / month / year
* displaying errorMessage messages
* */
class GovUkDateComponent {
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GovUkDateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GovUkDateComponent, selector: "mv-gov-uk-date", inputs: { config: "config", errorMessage: "errorMessage", formGroup: "formGroup" }, ngImport: i0, template: "<div\n  class=\"govuk-form-group\"\n  [ngClass]=\"{ 'govuk-form-group--error': errorMessage?.isInvalid }\"\n  [formGroup]=\"formGroup\"\n>\n  <mv-gov-uk-fieldset\n    [config]=\"{\n      legend: config.legend,\n      classes: 'govuk-label--m',\n      id: config.id,\n      hint: ' For example, 12 11 2007'\n    }\"\n    [isHeading]=\"false\"\n    [errorMessage]=\"errorMessage\"\n  >\n    <mv-gov-uk-error-message\n      [config]=\"{ id: 'passport' }\"\n      *ngIf=\"errorMessage.isInvalid\"\n      [errorMessage]=\"errorMessage\"\n    >\n    </mv-gov-uk-error-message>\n\n    <div class=\"govuk-date-input\" [id]=\"config.id + '-date'\">\n      <div class=\"govuk-date-input__item\">\n        <div class=\"govuk-form-group\">\n          <mv-gov-label\n            [config]=\"{\n              label: 'Day',\n              name: config.id,\n              id: config.id + '-day',\n              classes: 'govuk-date-input__label'\n            }\"\n          >\n          </mv-gov-label>\n          <input\n            class=\"govuk-input govuk-date-input__input govuk-input--width-2\"\n            [ngClass]=\"{ 'govuk-input--error': errorMessage?.isInvalid }\"\n            [id]=\"config.id + '-day'\"\n            [name]=\"config.id + '-day'\"\n            type=\"number\"\n            value=\"\"\n            pattern=\"[0-9]*\"\n            [formControlName]=\"'day'\"\n          />\n        </div>\n      </div>\n      <div class=\"govuk-date-input__item\">\n        <div class=\"govuk-form-group\">\n          <mv-gov-label\n            [config]=\"{\n              label: 'Month',\n              name: config.id + '-month',\n              id: config.id + '-month',\n              classes: 'govuk-date-input__label'\n            }\"\n          >\n          </mv-gov-label>\n          <input\n            class=\"govuk-input govuk-date-input__input govuk-input--width-2\"\n            [ngClass]=\"{ 'govuk-input--error': errorMessage?.isInvalid }\"\n            [id]=\"config.id + '-month'\"\n            [name]=\"config.id + '-month'\"\n            type=\"number\"\n            value=\"\"\n            pattern=\"[0-9]*\"\n            [formControlName]=\"'month'\"\n          />\n        </div>\n      </div>\n      <div class=\"govuk-date-input__item\">\n        <div class=\"govuk-form-group\">\n          <mv-gov-label\n            [config]=\"{\n              label: 'Year',\n              name: config.id + '-year',\n              id: config.id + '-year',\n              classes: 'govuk-date-input__label'\n            }\"\n          >\n          </mv-gov-label>\n          <input\n            class=\"govuk-input govuk-date-input__input govuk-input--width-4\"\n            [ngClass]=\"{ 'govuk-input--error': errorMessage?.isInvalid }\"\n            [id]=\"config.id + '-year'\"\n            [name]=\"config.id + '-year'\"\n            type=\"number\"\n            value=\"\"\n            pattern=\"[0-9]*\"\n            [formControlName]=\"'year'\"\n          />\n        </div>\n      </div>\n    </div>\n  </mv-gov-uk-fieldset>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: GovUkErrorMessageComponent, selector: " mv-gov-uk-error-message", inputs: ["config", "errorMessage"] }, { kind: "component", type: GovUkFieldsetComponent, selector: "mv-gov-uk-fieldset", inputs: ["config", "isHeading", "errorMessage"] }, { kind: "component", type: GovUkLabelComponent, selector: "mv-gov-label", inputs: ["config"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GovUkDateComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-gov-uk-date', template: "<div\n  class=\"govuk-form-group\"\n  [ngClass]=\"{ 'govuk-form-group--error': errorMessage?.isInvalid }\"\n  [formGroup]=\"formGroup\"\n>\n  <mv-gov-uk-fieldset\n    [config]=\"{\n      legend: config.legend,\n      classes: 'govuk-label--m',\n      id: config.id,\n      hint: ' For example, 12 11 2007'\n    }\"\n    [isHeading]=\"false\"\n    [errorMessage]=\"errorMessage\"\n  >\n    <mv-gov-uk-error-message\n      [config]=\"{ id: 'passport' }\"\n      *ngIf=\"errorMessage.isInvalid\"\n      [errorMessage]=\"errorMessage\"\n    >\n    </mv-gov-uk-error-message>\n\n    <div class=\"govuk-date-input\" [id]=\"config.id + '-date'\">\n      <div class=\"govuk-date-input__item\">\n        <div class=\"govuk-form-group\">\n          <mv-gov-label\n            [config]=\"{\n              label: 'Day',\n              name: config.id,\n              id: config.id + '-day',\n              classes: 'govuk-date-input__label'\n            }\"\n          >\n          </mv-gov-label>\n          <input\n            class=\"govuk-input govuk-date-input__input govuk-input--width-2\"\n            [ngClass]=\"{ 'govuk-input--error': errorMessage?.isInvalid }\"\n            [id]=\"config.id + '-day'\"\n            [name]=\"config.id + '-day'\"\n            type=\"number\"\n            value=\"\"\n            pattern=\"[0-9]*\"\n            [formControlName]=\"'day'\"\n          />\n        </div>\n      </div>\n      <div class=\"govuk-date-input__item\">\n        <div class=\"govuk-form-group\">\n          <mv-gov-label\n            [config]=\"{\n              label: 'Month',\n              name: config.id + '-month',\n              id: config.id + '-month',\n              classes: 'govuk-date-input__label'\n            }\"\n          >\n          </mv-gov-label>\n          <input\n            class=\"govuk-input govuk-date-input__input govuk-input--width-2\"\n            [ngClass]=\"{ 'govuk-input--error': errorMessage?.isInvalid }\"\n            [id]=\"config.id + '-month'\"\n            [name]=\"config.id + '-month'\"\n            type=\"number\"\n            value=\"\"\n            pattern=\"[0-9]*\"\n            [formControlName]=\"'month'\"\n          />\n        </div>\n      </div>\n      <div class=\"govuk-date-input__item\">\n        <div class=\"govuk-form-group\">\n          <mv-gov-label\n            [config]=\"{\n              label: 'Year',\n              name: config.id + '-year',\n              id: config.id + '-year',\n              classes: 'govuk-date-input__label'\n            }\"\n          >\n          </mv-gov-label>\n          <input\n            class=\"govuk-input govuk-date-input__input govuk-input--width-4\"\n            [ngClass]=\"{ 'govuk-input--error': errorMessage?.isInvalid }\"\n            [id]=\"config.id + '-year'\"\n            [name]=\"config.id + '-year'\"\n            type=\"number\"\n            value=\"\"\n            pattern=\"[0-9]*\"\n            [formControlName]=\"'year'\"\n          />\n        </div>\n      </div>\n    </div>\n  </mv-gov-uk-fieldset>\n</div>\n" }]
        }], propDecorators: { config: [{
                type: Input
            }], errorMessage: [{
                type: Input
            }], formGroup: [{
                type: Input
            }] } });

class CommentsSummaryComponent {
    constructor(store, printService, toolbarEvents, fb) {
        this.store = store;
        this.printService = printService;
        this.toolbarEvents = toolbarEvents;
        this.fb = fb;
        this.showFilters = false;
        this.hasFilter = false;
        this.fromFilterValid = true;
        this.toFilterValid = true;
    }
    ngOnInit() {
        this.filtersFg = this.fb.group({
            dateRangeFrom: new FormGroup({
                day: new FormControl('', [Validators.required]),
                month: new FormControl('', [Validators.required]),
                year: new FormControl('', [Validators.required])
            }),
            dateRangeTo: new FormGroup({
                day: new FormControl('', [Validators.required]),
                month: new FormControl('', [Validators.required]),
                year: new FormControl('', [Validators.required])
            }),
            tagFilters: this.fb.group({}),
        });
        this.comments$ = this.store.pipe(select(getCommentSummary));
        this.buildCheckBoxForm();
        this.container.nativeElement.focus();
    }
    buildCheckBoxForm() {
        this.filtersFg.reset();
        const checkboxes = this.filtersFg.get('tagFilters');
        const filters$ = this.store.pipe(select(getCommentSummaryFilters));
        this.allTags$ = this.store.pipe(select(getAllTagsArr));
        this.$subscriptions = combineLatest([this.allTags$, filters$]).subscribe(([tags, filters]) => {
            this.hasFilter = filters.hasFilter;
            tags.forEach((val) => {
                const checkBoxValue = (filters.filters.tagFilters &&
                    filters.filters.tagFilters.hasOwnProperty(val.key)) ?
                    filters.filters.tagFilters[val.key] : false;
                checkboxes.addControl(val.key, new FormControl(checkBoxValue));
            });
            this.filtersFg.updateValueAndValidity();
        });
    }
    onClearFilters() {
        this.store.dispatch(new ClearCommentSummaryFilters());
        this.buildCheckBoxForm();
    }
    onFilter() {
        const { value } = this.filtersFg;
        const hasDateFrom = (value.dateRangeFrom.year && value.dateRangeFrom.month && value.dateRangeFrom.day);
        const hasDateTo = (value.dateRangeTo.year && value.dateRangeTo.month && value.dateRangeTo.day);
        const dateRangeFrom = hasDateFrom ?
            new Date(value.dateRangeFrom.year, value.dateRangeFrom.month - 1, value.dateRangeFrom.day).getTime() : null;
        const dateRangeTo = hasDateTo ?
            new Date(value.dateRangeTo.year, value.dateRangeTo.month - 1, value.dateRangeTo.day).getTime() : null;
        this.fromFilterValid = hasDateFrom ? true : false;
        this.toFilterValid = hasDateTo ? true : false;
        if (this.filtersFg.valid) {
            this.store.dispatch(new ApplyCommentSymmaryFilter({ ...value, dateRangeFrom, dateRangeTo }));
        }
    }
    onFiltersToggle() {
        this.showFilters = !this.showFilters;
    }
    onClose() {
        this.toolbarEvents.toggleCommentsSummary(false);
    }
    onPrint() {
        this.printService.printElementNatively(this.commentsTable.nativeElement, 1000, 900);
    }
    navigateToPage(pageNumber) {
        if (this.contentType === 'pdf') {
            this.toolbarEvents.setPage(pageNumber);
        }
        this.toolbarEvents.toggleCommentsSummary(false);
        this.toolbarEvents.toggleCommentsPanel(true);
    }
    ngOnDestroy() {
        this.$subscriptions.unsubscribe();
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentsSummaryComponent, deps: [{ token: i1.Store }, { token: PrintService }, { token: ToolbarEventService }, { token: i2.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CommentsSummaryComponent, selector: "mv-comments-summary", inputs: { title: "title", contentType: "contentType" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["outerContainer"], descendants: true, static: true }, { propertyName: "commentsTable", first: true, predicate: ["commentContainer"], descendants: true }], ngImport: i0, template: "<div id=\"modal-background\" class=\"modal\" (click)=\"onClose()\">\n  <div\n    #outerContainer\n    id=\"modal\"\n    class=\"modal-content govuk-width-container clearfix\"\n    (click)=\"$event.stopPropagation()\"\n    cdkTrapFocus\n    tabindex=\"0\"\n  >\n    <div id=\"comment-container\" class=\"comment-container\" #commentContainer>\n      <h2 class=\"govuk-heading-m\">{{ title }}</h2>\n      <ng-container *ngIf=\"comments$ | async as comments\">\n        <ng-container *ngIf=\"comments.length\">\n          <button\n            type=\"submit\"\n            class=\"govuk-button govuk-!-margin-right-1\"\n            (click)=\"onFiltersToggle()\"\n          >\n            {{\n              !showFilters\n                ? (\"Show Filters\" | rpxTranslate)\n                : (\"Hide Filters\" | rpxTranslate)\n            }}\n          </button>\n          <button\n            type=\"submit\"\n            class=\"govuk-button govuk-button--secondary\"\n            (click)=\"onClearFilters()\"\n            *ngIf=\"hasFilter\"\n          >\n            {{ \"Clear Filters\" | rpxTranslate }}\n          </button>\n          <ng-container *ngIf=\"showFilters\">\n            <form [formGroup]=\"filtersFg\" (ngSubmit)=\"onFilter()\">\n              <div class=\"dates\">\n                <div class=\"dates__from\">\n                  <mv-gov-uk-date\n                    [config]=\"{ id: 'dateRangeFrom', legend: 'From' }\"\n                    [formGroup]=\"filtersFg.controls['dateRangeFrom']\"\n                    [errorMessage]=\"{\n                      isInvalid: !fromFilterValid,\n                      messages: ['From date is required']\n                    }\"\n                  ></mv-gov-uk-date>\n                </div>\n                <div class=\"dates__to\">\n                  <mv-gov-uk-date\n                    [config]=\"{ id: 'dateRangeTo', legend: 'To' }\"\n                    [formGroup]=\"filtersFg.controls['dateRangeTo']\"\n                    [errorMessage]=\"{\n                      isInvalid: !toFilterValid,\n                      messages: ['To date is required']\n                    }\"\n                  ></mv-gov-uk-date>\n                </div>\n                <div class=\"dates__tags\">\n                  <mv-gov-uk-fieldset\n                    [config]=\"{\n                      legend: 'Tags',\n                      classes: 'govuk-label--m',\n                      id: 'filters'\n                    }\"\n                    [isHeading]=\"false\"\n                  >\n                    <div\n                      class=\"govuk-checkboxes--scroll\"\n                      [formGroup]=\"filtersFg.controls['tagFilters']\"\n                    >\n                      <div class=\"govuk-checkboxes govuk-checkboxes--small\">\n                        <div\n                          class=\"govuk-checkboxes__item\"\n                          *ngFor=\"let item of allTags$ | async\"\n                        >\n                          <input\n                            [formControlName]=\"item.key\"\n                            class=\"govuk-checkboxes__input\"\n                            [value]=\"false\"\n                            type=\"checkbox\"\n                          />\n                          <label class=\"govuk-label govuk-checkboxes__label\">\n                            {{ item.key | unsnake }} ({{ item.length }})\n                          </label>\n                        </div>\n                      </div>\n                    </div>\n                  </mv-gov-uk-fieldset>\n                </div>\n                <div class=\"dates__cta\">\n                  <button type=\"submit\" class=\"govuk-button\">\n                    {{ \"Filter comments\" | rpxTranslate }}\n                  </button>\n                </div>\n              </div>\n            </form>\n          </ng-container>\n          <ng-container *ngIf=\"comments[0]\">\n            <ngx-datatable\n              [rows]=\"comments\"\n              rowHeight=\"auto\"\n              headerHeight=\"auto\"\n              [columnMode]=\"'flex'\"\n              [sorts]=\"[{ prop: 'date', dir: 'desc' }]\"\n            >\n              <ngx-datatable-column\n                name=\"{{ 'User' | rpxTranslate }}\"\n                [flexGrow]=\"1\"\n                [sortable]=\"false\"\n              ></ngx-datatable-column>\n              <ngx-datatable-column\n                name=\"{{ 'Page' | rpxTranslate }}\"\n                [flexGrow]=\"1\"\n              >\n                <ng-template ngx-datatable-cell-template let-value=\"value\">\n                  <a\n                    [routerLink]=\"[]\"\n                    class=\"comment-summary_pages\"\n                    (click)=\"navigateToPage(value)\"\n                    >{{ value }}</a\n                  >\n                </ng-template>\n              </ngx-datatable-column>\n              <ngx-datatable-column\n                name=\"{{ 'Date' | rpxTranslate }}\"\n                [flexGrow]=\"1\"\n              ></ngx-datatable-column>\n              <ngx-datatable-column\n                name=\"{{ 'Comment' | rpxTranslate }}\"\n                [flexGrow]=\"3\"\n                [sortable]=\"false\"\n              ></ngx-datatable-column>\n              <ngx-datatable-column\n                name=\"{{ 'Tags' | rpxTranslate }}\"\n                [flexGrow]=\"1\"\n                [sortable]=\"false\"\n              >\n                <ng-template ngx-datatable-cell-template let-value=\"value\">\n                  <span class=\"hmcts-badge\" *ngFor=\"let tag of value\">{{\n                    tag.label\n                  }}</span>\n                </ng-template>\n              </ngx-datatable-column>\n            </ngx-datatable>\n          </ng-container>\n        </ng-container>\n        <ng-container *ngIf=\"!comments[0]\">\n          <h3 class=\"govuk-heading-s\">\n            {{\n              \"No comments available. Select text to add a highlight or comment.\"\n                | rpxTranslate\n            }}\n          </h3>\n        </ng-container>\n      </ng-container>\n    </div>\n\n    <div class=\"button-container\">\n      <button (click)=\"onPrint()\" class=\"govuk-button govuk-button--secondary\">\n        {{ \"Print\" | rpxTranslate }}\n      </button>\n      <button id=\"modal-close-button\" (click)=\"onClose()\" class=\"govuk-button\">\n        {{ \"Close\" | rpxTranslate }}\n      </button>\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5$3.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i8.DatatableComponent, selector: "ngx-datatable", inputs: ["targetMarkerTemplate", "rows", "groupRowsBy", "groupedRows", "columns", "selected", "scrollbarV", "scrollbarH", "rowHeight", "columnMode", "headerHeight", "footerHeight", "externalPaging", "externalSorting", "limit", "count", "offset", "loadingIndicator", "selectionType", "reorderable", "swapColumns", "sortType", "sorts", "cssClasses", "messages", "rowClass", "selectCheck", "displayCheck", "groupExpansionDefault", "trackByProp", "selectAllRowsOnPage", "virtualization", "treeFromRelation", "treeToRelation", "summaryRow", "summaryHeight", "summaryPosition", "rowIdentity"], outputs: ["scroll", "activate", "select", "sort", "page", "reorder", "resize", "tableContextmenu", "treeAction"] }, { kind: "directive", type: i8.DataTableColumnDirective, selector: "ngx-datatable-column", inputs: ["name", "prop", "frozenLeft", "frozenRight", "flexGrow", "resizeable", "comparator", "pipe", "sortable", "draggable", "canAutoResize", "minWidth", "width", "maxWidth", "checkboxable", "headerCheckboxable", "headerClass", "cellClass", "isTreeColumn", "treeLevelIndent", "summaryFunc", "summaryTemplate", "cellTemplate", "headerTemplate", "treeToggleTemplate"] }, { kind: "directive", type: i8.DataTableColumnCellDirective, selector: "[ngx-datatable-cell-template]" }, { kind: "component", type: GovUkDateComponent, selector: "mv-gov-uk-date", inputs: ["config", "errorMessage", "formGroup"] }, { kind: "component", type: GovUkFieldsetComponent, selector: "mv-gov-uk-fieldset", inputs: ["config", "isHeading", "errorMessage"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5$1.RpxTranslatePipe, name: "rpxTranslate" }, { kind: "pipe", type: UnsnakePipe, name: "unsnake" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CommentsSummaryComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-comments-summary', template: "<div id=\"modal-background\" class=\"modal\" (click)=\"onClose()\">\n  <div\n    #outerContainer\n    id=\"modal\"\n    class=\"modal-content govuk-width-container clearfix\"\n    (click)=\"$event.stopPropagation()\"\n    cdkTrapFocus\n    tabindex=\"0\"\n  >\n    <div id=\"comment-container\" class=\"comment-container\" #commentContainer>\n      <h2 class=\"govuk-heading-m\">{{ title }}</h2>\n      <ng-container *ngIf=\"comments$ | async as comments\">\n        <ng-container *ngIf=\"comments.length\">\n          <button\n            type=\"submit\"\n            class=\"govuk-button govuk-!-margin-right-1\"\n            (click)=\"onFiltersToggle()\"\n          >\n            {{\n              !showFilters\n                ? (\"Show Filters\" | rpxTranslate)\n                : (\"Hide Filters\" | rpxTranslate)\n            }}\n          </button>\n          <button\n            type=\"submit\"\n            class=\"govuk-button govuk-button--secondary\"\n            (click)=\"onClearFilters()\"\n            *ngIf=\"hasFilter\"\n          >\n            {{ \"Clear Filters\" | rpxTranslate }}\n          </button>\n          <ng-container *ngIf=\"showFilters\">\n            <form [formGroup]=\"filtersFg\" (ngSubmit)=\"onFilter()\">\n              <div class=\"dates\">\n                <div class=\"dates__from\">\n                  <mv-gov-uk-date\n                    [config]=\"{ id: 'dateRangeFrom', legend: 'From' }\"\n                    [formGroup]=\"filtersFg.controls['dateRangeFrom']\"\n                    [errorMessage]=\"{\n                      isInvalid: !fromFilterValid,\n                      messages: ['From date is required']\n                    }\"\n                  ></mv-gov-uk-date>\n                </div>\n                <div class=\"dates__to\">\n                  <mv-gov-uk-date\n                    [config]=\"{ id: 'dateRangeTo', legend: 'To' }\"\n                    [formGroup]=\"filtersFg.controls['dateRangeTo']\"\n                    [errorMessage]=\"{\n                      isInvalid: !toFilterValid,\n                      messages: ['To date is required']\n                    }\"\n                  ></mv-gov-uk-date>\n                </div>\n                <div class=\"dates__tags\">\n                  <mv-gov-uk-fieldset\n                    [config]=\"{\n                      legend: 'Tags',\n                      classes: 'govuk-label--m',\n                      id: 'filters'\n                    }\"\n                    [isHeading]=\"false\"\n                  >\n                    <div\n                      class=\"govuk-checkboxes--scroll\"\n                      [formGroup]=\"filtersFg.controls['tagFilters']\"\n                    >\n                      <div class=\"govuk-checkboxes govuk-checkboxes--small\">\n                        <div\n                          class=\"govuk-checkboxes__item\"\n                          *ngFor=\"let item of allTags$ | async\"\n                        >\n                          <input\n                            [formControlName]=\"item.key\"\n                            class=\"govuk-checkboxes__input\"\n                            [value]=\"false\"\n                            type=\"checkbox\"\n                          />\n                          <label class=\"govuk-label govuk-checkboxes__label\">\n                            {{ item.key | unsnake }} ({{ item.length }})\n                          </label>\n                        </div>\n                      </div>\n                    </div>\n                  </mv-gov-uk-fieldset>\n                </div>\n                <div class=\"dates__cta\">\n                  <button type=\"submit\" class=\"govuk-button\">\n                    {{ \"Filter comments\" | rpxTranslate }}\n                  </button>\n                </div>\n              </div>\n            </form>\n          </ng-container>\n          <ng-container *ngIf=\"comments[0]\">\n            <ngx-datatable\n              [rows]=\"comments\"\n              rowHeight=\"auto\"\n              headerHeight=\"auto\"\n              [columnMode]=\"'flex'\"\n              [sorts]=\"[{ prop: 'date', dir: 'desc' }]\"\n            >\n              <ngx-datatable-column\n                name=\"{{ 'User' | rpxTranslate }}\"\n                [flexGrow]=\"1\"\n                [sortable]=\"false\"\n              ></ngx-datatable-column>\n              <ngx-datatable-column\n                name=\"{{ 'Page' | rpxTranslate }}\"\n                [flexGrow]=\"1\"\n              >\n                <ng-template ngx-datatable-cell-template let-value=\"value\">\n                  <a\n                    [routerLink]=\"[]\"\n                    class=\"comment-summary_pages\"\n                    (click)=\"navigateToPage(value)\"\n                    >{{ value }}</a\n                  >\n                </ng-template>\n              </ngx-datatable-column>\n              <ngx-datatable-column\n                name=\"{{ 'Date' | rpxTranslate }}\"\n                [flexGrow]=\"1\"\n              ></ngx-datatable-column>\n              <ngx-datatable-column\n                name=\"{{ 'Comment' | rpxTranslate }}\"\n                [flexGrow]=\"3\"\n                [sortable]=\"false\"\n              ></ngx-datatable-column>\n              <ngx-datatable-column\n                name=\"{{ 'Tags' | rpxTranslate }}\"\n                [flexGrow]=\"1\"\n                [sortable]=\"false\"\n              >\n                <ng-template ngx-datatable-cell-template let-value=\"value\">\n                  <span class=\"hmcts-badge\" *ngFor=\"let tag of value\">{{\n                    tag.label\n                  }}</span>\n                </ng-template>\n              </ngx-datatable-column>\n            </ngx-datatable>\n          </ng-container>\n        </ng-container>\n        <ng-container *ngIf=\"!comments[0]\">\n          <h3 class=\"govuk-heading-s\">\n            {{\n              \"No comments available. Select text to add a highlight or comment.\"\n                | rpxTranslate\n            }}\n          </h3>\n        </ng-container>\n      </ng-container>\n    </div>\n\n    <div class=\"button-container\">\n      <button (click)=\"onPrint()\" class=\"govuk-button govuk-button--secondary\">\n        {{ \"Print\" | rpxTranslate }}\n      </button>\n      <button id=\"modal-close-button\" (click)=\"onClose()\" class=\"govuk-button\">\n        {{ \"Close\" | rpxTranslate }}\n      </button>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: PrintService }, { type: ToolbarEventService }, { type: i2.FormBuilder }], propDecorators: { title: [{
                type: Input
            }], contentType: [{
                type: Input
            }], container: [{
                type: ViewChild,
                args: ['outerContainer', { static: true }]
            }], commentsTable: [{
                type: ViewChild,
                args: ['commentContainer', { static: false }]
            }] } });

class MultimediaPlayerComponent {
    constructor(toolbarEvents) {
        this.toolbarEvents = toolbarEvents;
        this.loadStatus = new EventEmitter();
        this.playbackMsg = 'loading';
    }
    ngOnInit() {
        this.subscription = this.toolbarEvents.downloadSubject
            .subscribe(() => this.downloadLink.nativeElement.click());
        this.loadStatus.emit(ResponseType.SUCCESS);
    }
    ngOnChanges(changes) {
        if (changes.url) {
            this.reloadVideo();
        }
    }
    ngOnDestroy() {
        this.subscription.unsubscribe();
    }
    reloadVideo() {
        if (this.videoPlayer) {
            this.playbackMsg = 'loading';
            this.videoPlayer.nativeElement.load();
        }
    }
    onSuccess() {
        this.playbackMsg = 'success';
    }
    onError() {
        this.playbackMsg = 'error';
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MultimediaPlayerComponent, deps: [{ token: ToolbarEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: MultimediaPlayerComponent, selector: "mv-multimedia-player", inputs: { url: "url", downloadFileName: "downloadFileName", multimediaOn: "multimediaOn" }, outputs: { loadStatus: "loadStatus" }, viewQueries: [{ propertyName: "downloadLink", first: true, predicate: ["downloadLink"], descendants: true }, { propertyName: "videoPlayer", first: true, predicate: ["videoPlayer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"govuk-width-container\">\n  <div class=\"govuk-notification-banner__content\">\n    <p>\n      <span *ngIf=\"multimediaOn && playbackMsg === 'loading'\">{{\n        \"Loading multimedia content ...\" | rpxTranslate\n      }}</span>\n      <span *ngIf=\"!multimediaOn\"\n        >{{ \"Multimedia playback is not enabled, \" | rpxTranslate }}\n      </span>\n      <span *ngIf=\"multimediaOn && playbackMsg === 'success'\"\n        >{{ \"Use the player to play to the file or\" | rpxTranslate }}\n      </span>\n      <span *ngIf=\"multimediaOn && playbackMsg === 'error'\"\n        >{{ \"Mime type not supported.\" | rpxTranslate }}\n      </span>\n      <a\n        *ngIf=\"!multimediaOn || playbackMsg !== 'loading'\"\n        #downloadLink\n        [href]=\"url\"\n        [download]=\"downloadFileName\"\n        >{{ \"Click here to download\" | rpxTranslate }}</a\n      >\n    </p>\n    <video\n      #videoPlayer\n      *ngIf=\"multimediaOn\"\n      width=\"100%\"\n      height=\"100%\"\n      preload=\"auto\"\n      (canplay)=\"onSuccess()\"\n      controls\n    >\n      <source (error)=\"onError()\" [src]=\"url\" type=\"video/mp4\" />\n      <source\n        (error)=\"onError()\"\n        [src]=\"url\"\n        type=\"video/mp4; codecs='avc1, av01, hvc1, hev1, mp4v, mp4a.40.2, opus'\"\n      />\n      <source (error)=\"onError()\" [src]=\"url\" type=\"video/ogg\" />\n      <source\n        (error)=\"onError()\"\n        [src]=\"url\"\n        type=\"video/ogg; codecs='theora, vp8, vp9, flac, opus, vorbis'\"\n      />\n      <source (error)=\"onError()\" [src]=\"url\" type=\"video/webm\" />\n      <source\n        (error)=\"onError()\"\n        [src]=\"url\"\n        type=\"video/webm; codecs='vp8, vp9, vorbis, opus'\"\n      />\n    </video>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i5$1.RpxTranslatePipe, name: "rpxTranslate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MultimediaPlayerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-multimedia-player', template: "<div class=\"govuk-width-container\">\n  <div class=\"govuk-notification-banner__content\">\n    <p>\n      <span *ngIf=\"multimediaOn && playbackMsg === 'loading'\">{{\n        \"Loading multimedia content ...\" | rpxTranslate\n      }}</span>\n      <span *ngIf=\"!multimediaOn\"\n        >{{ \"Multimedia playback is not enabled, \" | rpxTranslate }}\n      </span>\n      <span *ngIf=\"multimediaOn && playbackMsg === 'success'\"\n        >{{ \"Use the player to play to the file or\" | rpxTranslate }}\n      </span>\n      <span *ngIf=\"multimediaOn && playbackMsg === 'error'\"\n        >{{ \"Mime type not supported.\" | rpxTranslate }}\n      </span>\n      <a\n        *ngIf=\"!multimediaOn || playbackMsg !== 'loading'\"\n        #downloadLink\n        [href]=\"url\"\n        [download]=\"downloadFileName\"\n        >{{ \"Click here to download\" | rpxTranslate }}</a\n      >\n    </p>\n    <video\n      #videoPlayer\n      *ngIf=\"multimediaOn\"\n      width=\"100%\"\n      height=\"100%\"\n      preload=\"auto\"\n      (canplay)=\"onSuccess()\"\n      controls\n    >\n      <source (error)=\"onError()\" [src]=\"url\" type=\"video/mp4\" />\n      <source\n        (error)=\"onError()\"\n        [src]=\"url\"\n        type=\"video/mp4; codecs='avc1, av01, hvc1, hev1, mp4v, mp4a.40.2, opus'\"\n      />\n      <source (error)=\"onError()\" [src]=\"url\" type=\"video/ogg\" />\n      <source\n        (error)=\"onError()\"\n        [src]=\"url\"\n        type=\"video/ogg; codecs='theora, vp8, vp9, flac, opus, vorbis'\"\n      />\n      <source (error)=\"onError()\" [src]=\"url\" type=\"video/webm\" />\n      <source\n        (error)=\"onError()\"\n        [src]=\"url\"\n        type=\"video/webm; codecs='vp8, vp9, vorbis, opus'\"\n      />\n    </video>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: ToolbarEventService }], propDecorators: { url: [{
                type: Input
            }], downloadFileName: [{
                type: Input
            }], multimediaOn: [{
                type: Input
            }], loadStatus: [{
                type: Output
            }], downloadLink: [{
                type: ViewChild,
                args: ['downloadLink', { static: false }]
            }], videoPlayer: [{
                type: ViewChild,
                args: ['videoPlayer', { static: false }]
            }] } });

class ConvertibleContentViewerComponent {
    constructor(store) {
        this.store = store;
        this.mediaLoadStatus = new EventEmitter();
        this.viewerException = new EventEmitter();
        this.documentTitle = new EventEmitter();
    }
    ngOnInit() {
        this.$subscription = this.store.pipe(select(getConvertedDocument), filter(value => !!value))
            .subscribe((docInfo) => {
            if (docInfo.url) {
                this.convertedUrl = docInfo.url;
                this.store.dispatch(new ClearConvertDocUrl());
            }
            else {
                this.onLoadException(new ViewerException(docInfo.error));
            }
        });
    }
    ngOnChanges(changes) {
        if (changes.originalUrl?.currentValue && changes.originalUrl.currentValue !== changes.originalUrl.previousValue) {
            this.store.dispatch(new Convert(this.extractDMStoreDocId(this.originalUrl)));
        }
    }
    ngOnDestroy() {
        this.$subscription.unsubscribe();
    }
    onMediaLoad(status) {
        this.mediaLoadStatus.emit(status);
    }
    onLoadException(exception) {
        this.viewerException.emit(exception);
    }
    onDocumentTitleChange(title) {
        this.documentTitle.emit(title);
    }
    // todo move this to common place for media viewer and pdf
    extractDMStoreDocId(url) {
        if (url.includes('/documents/')) {
            url = url.split('/documents/')[1];
        }
        else if (url.includes('/documentsv2/')) {
            url = url.split('/documentsv2/')[1];
        }
        return url.replace('/binary', '');
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ConvertibleContentViewerComponent, deps: [{ token: i1.Store }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ConvertibleContentViewerComponent, selector: "mv-conversion-viewer", inputs: { originalUrl: "originalUrl", downloadFileName: "downloadFileName", height: "height", enableAnnotations: "enableAnnotations", enableRedactions: "enableRedactions", annotationSet: "annotationSet" }, outputs: { mediaLoadStatus: "mediaLoadStatus", viewerException: "viewerException", documentTitle: "documentTitle" }, usesOnChanges: true, ngImport: i0, template: "<mv-pdf-viewer *ngIf=\"convertedUrl\"\n               (mediaLoadStatus)=\"onMediaLoad($event)\"\n               (pdfViewerException)=\"onLoadException($event)\"\n               (documentTitle)=\"onDocumentTitleChange($event)\"\n               [url]=\"convertedUrl\"\n               [downloadUrl]=\"originalUrl\"\n               [enableAnnotations]=\"enableAnnotations\"\n               [enableRedactions]=\"enableRedactions\"\n               [annotationSet]=\"enableAnnotations ? annotationSet : null\"\n               [downloadFileName]=\"downloadFileName\"\n               [height]=\"height\">\n</mv-pdf-viewer>\n", dependencies: [{ kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdfViewerComponent, selector: "mv-pdf-viewer", inputs: ["downloadUrl", "url", "downloadFileName", "enableAnnotations", "enableRedactions", "enableICP", "annotationSet", "enableRedactSearch", "height", "caseId", "searchBarHidden"], outputs: ["mediaLoadStatus", "pdfViewerException", "documentTitle"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ConvertibleContentViewerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-conversion-viewer', encapsulation: ViewEncapsulation.None, template: "<mv-pdf-viewer *ngIf=\"convertedUrl\"\n               (mediaLoadStatus)=\"onMediaLoad($event)\"\n               (pdfViewerException)=\"onLoadException($event)\"\n               (documentTitle)=\"onDocumentTitleChange($event)\"\n               [url]=\"convertedUrl\"\n               [downloadUrl]=\"originalUrl\"\n               [enableAnnotations]=\"enableAnnotations\"\n               [enableRedactions]=\"enableRedactions\"\n               [annotationSet]=\"enableAnnotations ? annotationSet : null\"\n               [downloadFileName]=\"downloadFileName\"\n               [height]=\"height\">\n</mv-pdf-viewer>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }], propDecorators: { originalUrl: [{
                type: Input
            }], downloadFileName: [{
                type: Input
            }], height: [{
                type: Input
            }], enableAnnotations: [{
                type: Input
            }], enableRedactions: [{
                type: Input
            }], annotationSet: [{
                type: Input
            }], mediaLoadStatus: [{
                type: Output
            }], viewerException: [{
                type: Output
            }], documentTitle: [{
                type: Output
            }] } });

class RotationPersistDirective {
    constructor(el, store, toolbarButtons, toolbarEvents) {
        this.el = el;
        this.store = store;
        this.toolbarButtons = toolbarButtons;
        this.toolbarEvents = toolbarEvents;
        this.rotation = 0;
        this.savedRotation = 0;
    }
    ngOnInit() {
        this.$subscriptions = this.toolbarEvents.rotateSubject.pipe(distinctUntilChanged()).subscribe(rotation => this.onRotate(rotation));
        this.$subscriptions.add(this.toolbarEvents.saveRotationSubject.subscribe(() => this.saveRotation()));
        this.$subscriptions.add(this.store.pipe(select(getRotation)).subscribe(rotation => this.savedRotation = rotation));
        this.$subscriptions.add(this.store.pipe(select(getDocumentId)).subscribe(documentId => this.documentId = documentId));
    }
    ngOnDestroy() {
        this.$subscriptions.unsubscribe();
    }
    onMediaLoad(status) {
        this.rotation = 0;
        this.store.dispatch(new LoadRotation(this.documentId));
        this.store.pipe(select(rotationLoaded), filter(value => !!value), take(1))
            .subscribe(() => {
            if (this.savedRotation) {
                this.toolbarEvents.rotateSubject.next(this.savedRotation);
            }
        });
    }
    onRotate(rotation) {
        this.rotation = (this.rotation + rotation) % 360;
        this.toolbarButtons.showSaveRotationButton = this.savedRotation !== this.rotation;
    }
    saveRotation() {
        const payload = {
            documentId: this.documentId,
            rotationAngle: this.rotation
        };
        this.store.dispatch(new SaveRotation(payload));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RotationPersistDirective, deps: [{ token: i0.ElementRef }, { token: i1.Store }, { token: ToolbarButtonVisibilityService }, { token: ToolbarEventService }], target: i0.ɵɵFactoryTarget.Directive }); }
    /** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: RotationPersistDirective, selector: "[mvRotationPersist]", host: { listeners: { "mediaLoadStatus": "onMediaLoad($event)" } }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RotationPersistDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[mvRotationPersist]'
                }]
        }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.Store }, { type: ToolbarButtonVisibilityService }, { type: ToolbarEventService }], propDecorators: { onMediaLoad: [{
                type: HostListener,
                args: ['mediaLoadStatus', ['$event']]
            }] } });

class ConfirmActionDialogComponent {
    constructor(icpEventService) {
        this.icpEventService = icpEventService;
    }
    onCancel() {
        this.icpEventService.leavingSession.next(false);
    }
    onConfirm() {
        this.icpEventService.confirmExit();
        this.icpEventService.leavingSession.next(false);
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ConfirmActionDialogComponent, deps: [{ token: IcpEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ConfirmActionDialogComponent, selector: "mv-confirm-action", ngImport: i0, template: "<div id=\"modal-background\" class=\"modal\" (click)=\"onCancel()\">\n  <div id=\"modal\" class=\"modal-content govuk-width-container clearfix\" (click)=\"$event.stopPropagation()\">\n    <h2 class=\"govuk-heading-s\">Are you sure you want to leave the presentation?</h2>\n    <div class=\"button-container\">\n      <button id=\"modal-close-button\" (click)=\"onConfirm()\" class=\"govuk-button\">Confirm</button>\n      <button (click)=\"onCancel()\" class=\"govuk-button govuk-button--secondary\">Cancel</button>\n    </div>\n  </div>\n</div>\n" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ConfirmActionDialogComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-confirm-action', template: "<div id=\"modal-background\" class=\"modal\" (click)=\"onCancel()\">\n  <div id=\"modal\" class=\"modal-content govuk-width-container clearfix\" (click)=\"$event.stopPropagation()\">\n    <h2 class=\"govuk-heading-s\">Are you sure you want to leave the presentation?</h2>\n    <div class=\"button-container\">\n      <button id=\"modal-close-button\" (click)=\"onConfirm()\" class=\"govuk-button\">Confirm</button>\n      <button (click)=\"onCancel()\" class=\"govuk-button govuk-button--secondary\">Cancel</button>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: IcpEventService }] });

var CoreContentTypes;
(function (CoreContentTypes) {
    CoreContentTypes["PDF"] = "pdf";
    CoreContentTypes["IMAGE"] = "image";
})(CoreContentTypes || (CoreContentTypes = {}));
var MultimediaContentTypes;
(function (MultimediaContentTypes) {
    MultimediaContentTypes["MP4"] = "mp4";
    MultimediaContentTypes["MP3"] = "mp3";
})(MultimediaContentTypes || (MultimediaContentTypes = {}));
var ConvertibleContentTypes;
(function (ConvertibleContentTypes) {
    ConvertibleContentTypes["EXCEL"] = "excel";
    ConvertibleContentTypes["WORD"] = "word";
    ConvertibleContentTypes["POWERPOINT"] = "powerpoint";
    ConvertibleContentTypes["TXT"] = "txt";
    ConvertibleContentTypes["RTF"] = "rtf";
})(ConvertibleContentTypes || (ConvertibleContentTypes = {}));
class MediaViewerComponent {
    constructor(store, toolbarButtons, toolbarEvents, api, commentService, elRef, cdr, icpEventService) {
        this.store = store;
        this.toolbarButtons = toolbarButtons;
        this.toolbarEvents = toolbarEvents;
        this.api = api;
        this.commentService = commentService;
        this.elRef = elRef;
        this.cdr = cdr;
        this.icpEventService = icpEventService;
        this.showToolbar = true;
        this.toolbarButtonOverrides = {};
        this.width = '100%';
        this.mediaLoadStatus = new EventEmitter();
        this.viewerException = new EventEmitter();
        this.toolbarEventsOutput = new EventEmitter();
        this.unsavedChanges = new EventEmitter();
        this.enableAnnotations = false;
        this.enableRedactions = false;
        this.enableICP = false;
        this.multimediaPlayerEnabled = false;
        this.enableRedactSearch = false;
        this.multimediaContent = false;
        this.convertibleContent = false;
        this.unsupportedContent = false;
        this.typeException = false;
        if (this.annotationApiUrl) {
            api.annotationApiUrl = this.annotationApiUrl;
        }
    }
    ngAfterContentInit() {
        this.annotationSet$ = this.store.pipe(select(getAnnotationSet));
        this.hasDifferentPageSize$ = this.store.pipe(select(getPageDifference));
        this.setToolbarButtons();
        this.toolbarEventsOutput.emit(this.toolbarEvents);
        this.$subscriptions = this.commentService.getUnsavedChanges()
            .subscribe(changes => this.onCommentChange(changes));
        this.$subscriptions.add(this.toolbarEvents.getShowCommentSummary()
            .subscribe(changes => this.showCommentSummary = changes));
    }
    ngAfterViewChecked() {
        if (this.height && this.viewerHeight !== this.height) {
            this.viewerHeight = this.height;
            this.cdr.detectChanges();
            return;
        }
        if (!this.height) {
            const compOffsetTop = HtmlTemplatesHelper.getAdjustedBoundingRect(this.elRef.nativeElement).top;
            const viewerOffsetTop = this.viewerRef.nativeElement.offsetTop;
            const offset = compOffsetTop + viewerOffsetTop;
            if (this.prevOffset !== offset) {
                this.viewerHeight = `calc(100vh - ${offset}px)`;
                this.prevOffset = offset;
                this.cdr.detectChanges();
            }
        }
    }
    ngOnChanges(changes) {
        if (changes.annotationApiUrl) {
            this.api.annotationApiUrl = this.annotationApiUrl;
        }
        if (changes.contentType) {
            this.convertibleContent = this.needsConverting();
            this.multimediaContent = this.isMultimedia();
            this.unsupportedContent = !this.isSupported();
        }
        if (changes.url) {
            this.toolbarEvents.reset();
            this.commentService.resetCommentSet();
            this.documentId = this.extractDMStoreDocId(this.url);
            this.store.dispatch(new SetDocumentId(this.documentId));
            if (this.enableAnnotations && !(this.multimediaContent || this.unsupportedContent)) {
                this.store.dispatch(new LoadAnnotationSet(this.documentId));
            }
            if (this.enableRedactions && !(this.multimediaContent || this.unsupportedContent) && this.documentId) {
                this.store.dispatch(new LoadRedactions(this.documentId));
            }
            if (this.contentType === 'image') {
                this.documentTitle = null;
            }
        }
        this.setToolbarButtons();
        this.detectOs();
        this.typeException = false;
    }
    ngOnDestroy() {
        this.$subscriptions.unsubscribe();
    }
    needsConverting() {
        return this.contentType !== null && Object.keys(ConvertibleContentTypes).includes(this.contentType.toUpperCase());
    }
    isMultimedia() {
        return this.contentType !== null && Object.keys(MultimediaContentTypes).includes(this.contentType.toUpperCase());
    }
    isSupported() {
        const supportedTypes = Object.assign({}, MultimediaContentTypes, ConvertibleContentTypes, CoreContentTypes);
        return this.contentType !== null && Object.keys(supportedTypes).includes(this.contentType.toUpperCase());
    }
    onMediaLoad(status) {
        this.mediaLoadStatus.emit(status);
    }
    setToolbarButtons() {
        if (this.contentType === CoreContentTypes.PDF || this.needsConverting()) {
            this.toolbarButtons.setup({
                ...defaultPdfOptions, showHighlightButton: this.enableAnnotations, showDrawButton: false,
                ...this.toolbarButtonOverrides
            });
        }
        else if (this.contentType === CoreContentTypes.IMAGE) {
            this.toolbarButtons.setup({
                ...defaultImageOptions, showDrawButton: this.enableAnnotations,
                ...this.toolbarButtonOverrides
            });
        }
        else if (this.isMultimedia()) {
            this.toolbarButtons.setup({
                ...defaultMultimediaOptions,
                ...this.toolbarButtonOverrides
            });
        }
        else {
            this.toolbarButtons.setup({
                ...defaultUnsupportedOptions,
                ...this.toolbarButtonOverrides
            });
        }
    }
    onLoadException(exception) {
        this.viewerException.emit(exception);
        if (!this.isSupported()) {
            this.typeException = false;
        }
        else {
            this.typeException = true;
            this.contentType = null;
            this.setToolbarButtons();
        }
    }
    onCommentChange(changes) {
        this.unsavedChanges.emit(changes);
    }
    onDocumentTitleChange(title) {
        this.documentTitle = title;
    }
    // If secure mode is enabled (which adds "documentsv2" to the documentId), get rid of it
    extractDMStoreDocId(url) {
        url = url.includes('/documents/') ? url.split('/documents/')[1] : url;
        url = url.includes('/documentsv2/') ? url.split('/documentsv2/')[1] : url;
        return url.replace('/binary', '');
    }
    detectOs() {
        this.hasScrollBar = window.navigator.userAgent.indexOf('Win') !== -1;
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MediaViewerComponent, deps: [{ token: i1.Store }, { token: ToolbarButtonVisibilityService }, { token: ToolbarEventService }, { token: AnnotationApiService }, { token: CommentService }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: IcpEventService }], target: i0.ɵɵFactoryTarget.Component }); }
    /** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: MediaViewerComponent, selector: "mv-media-viewer", inputs: { url: "url", downloadFileName: "downloadFileName", contentType: "contentType", showToolbar: "showToolbar", toolbarButtonOverrides: "toolbarButtonOverrides", height: "height", width: "width", enableAnnotations: "enableAnnotations", annotationApiUrl: "annotationApiUrl", enableRedactions: "enableRedactions", enableICP: "enableICP", multimediaPlayerEnabled: "multimediaPlayerEnabled", enableRedactSearch: "enableRedactSearch", caseId: "caseId" }, outputs: { mediaLoadStatus: "mediaLoadStatus", viewerException: "viewerException", toolbarEventsOutput: "toolbarEventsOutput", unsavedChanges: "unsavedChanges" }, viewQueries: [{ propertyName: "viewerRef", first: true, predicate: ["viewerRef"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n  id=\"outerContainer\"\n  [ngClass]=\"{\n    'has-redact-bar': toolbarEvents.redactionMode | async,\n    'icp-mode': icpEventService.enabled | async,\n    'is-redaction-preview': toolbarEvents.redactionPreview | async,\n    sidebarOpen: toolbarEvents.sidebarOpen | async,\n    'has-scroll-bar': hasScrollBar,\n    'has-different-page-size': hasDifferentPageSize$ | async\n  }\"\n  [ngStyle]=\"{ width: width }\"\n>\n  <mv-comments-summary\n    *ngIf=\"showCommentSummary\"\n    [title]=\"documentTitle || 'Comment Summary'\"\n    [contentType]=\"contentType\"\n  >\n  </mv-comments-summary>\n\n  <mv-confirm-action\n    *ngIf=\"icpEventService.leavingSession | async\"\n  ></mv-confirm-action>\n\n  <div id=\"mainContainer\">\n    <mv-main-toolbar\n      *ngIf=\"showToolbar\"\n      [enableAnnotations]=\"enableAnnotations\"\n      [enableICP]=\"enableICP\"\n      [enableRedactions]=\"enableRedactions\"\n      [contentType]=\"contentType\"\n    >\n    </mv-main-toolbar>\n    <mv-redaction-toolbar\n      [showRedactSearch]=\"enableRedactSearch\"\n      *ngIf=\"toolbarEvents.redactionMode | async\"\n    ></mv-redaction-toolbar>\n    <mv-highlight-toolbar\n      *ngIf=\"toolbarEvents.highlightToolbarSubject | async\"\n    ></mv-highlight-toolbar>\n    <mv-icp-toolbar *ngIf=\"icpEventService.enabled | async\"></mv-icp-toolbar>\n\n    <div #viewerRef>\n      <mv-conversion-viewer\n        *ngIf=\"convertibleContent\"\n        (documentTitle)=\"onDocumentTitleChange($event)\"\n        (mediaLoadStatus)=\"onMediaLoad($event)\"\n        (viewerException)=\"onLoadException($event)\"\n        [enableAnnotations]=\"enableAnnotations\"\n        [enableRedactions]=\"enableRedactions\"\n        [annotationSet]=\"enableAnnotations ? (annotationSet$ | async) : null\"\n        [originalUrl]=\"url\"\n        [downloadFileName]=\"downloadFileName\"\n        [height]=\"viewerHeight\"\n        mvRotationPersist\n      >\n      </mv-conversion-viewer>\n      <mv-pdf-viewer\n        *ngIf=\"contentType === 'pdf'\"\n        #pdfViewer\n        (mediaLoadStatus)=\"onMediaLoad($event)\"\n        (pdfViewerException)=\"onLoadException($event)\"\n        (documentTitle)=\"onDocumentTitleChange($event)\"\n        [url]=\"url\"\n        [enableAnnotations]=\"enableAnnotations\"\n        [enableRedactions]=\"enableRedactions\"\n        [enableICP]=\"enableICP\"\n        [annotationSet]=\"enableAnnotations ? (annotationSet$ | async) : null\"\n        [downloadFileName]=\"downloadFileName\"\n        [height]=\"viewerHeight\"\n        [caseId]=\"caseId\"\n        mvRotationPersist\n      >\n      </mv-pdf-viewer>\n      <mv-image-viewer\n        *ngIf=\"contentType === 'image'\"\n        (mediaLoadStatus)=\"onMediaLoad($event)\"\n        (imageViewerException)=\"onLoadException($event)\"\n        [url]=\"url\"\n        [enableAnnotations]=\"enableAnnotations\"\n        [annotationSet]=\"enableAnnotations ? (annotationSet$ | async) : null\"\n        [downloadFileName]=\"downloadFileName\"\n        [height]=\"viewerHeight\"\n        mvRotationPersist\n      >\n      </mv-image-viewer>\n      <mv-multimedia-player\n        *ngIf=\"multimediaContent\"\n        [multimediaOn]=\"multimediaPlayerEnabled\"\n        [url]=\"url\"\n        [downloadFileName]=\"downloadFileName\"\n        (loadStatus)=\"onMediaLoad($event)\"\n      >\n      </mv-multimedia-player>\n      <mv-unsupported-viewer\n        *ngIf=\"unsupportedContent\"\n        [url]=\"url\"\n        [typeException]=\"typeException\"\n        [downloadFileName]=\"downloadFileName\"\n        (loadStatus)=\"onMediaLoad($event)\"\n        (unsupportedViewerException)=\"onLoadException($event)\"\n      >\n      </mv-unsupported-viewer>\n    </div>\n  </div>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: MainToolbarComponent, selector: "mv-main-toolbar", inputs: ["enableAnnotations", "enableRedactions", "enableICP", "contentType"] }, { kind: "component", type: RedactionToolbarComponent, selector: "mv-redaction-toolbar", inputs: ["showRedactSearch"] }, { kind: "component", type: IcpToolbarComponent, selector: "mv-icp-toolbar" }, { kind: "component", type: HighlightToolbarComponent, selector: "mv-highlight-toolbar" }, { kind: "component", type: CommentsSummaryComponent, selector: "mv-comments-summary", inputs: ["title", "contentType"] }, { kind: "component", type: PdfViewerComponent, selector: "mv-pdf-viewer", inputs: ["downloadUrl", "url", "downloadFileName", "enableAnnotations", "enableRedactions", "enableICP", "annotationSet", "enableRedactSearch", "height", "caseId", "searchBarHidden"], outputs: ["mediaLoadStatus", "pdfViewerException", "documentTitle"] }, { kind: "component", type: ImageViewerComponent, selector: "mv-image-viewer", inputs: ["url", "downloadFileName", "enableAnnotations", "annotationSet", "height"], outputs: ["mediaLoadStatus", "imageViewerException"] }, { kind: "component", type: UnsupportedViewerComponent, selector: "mv-unsupported-viewer", inputs: ["url", "downloadFileName", "typeException"], outputs: ["loadStatus", "unsupportedViewerException"] }, { kind: "component", type: MultimediaPlayerComponent, selector: "mv-multimedia-player", inputs: ["url", "downloadFileName", "multimediaOn"], outputs: ["loadStatus"] }, { kind: "component", type: ConvertibleContentViewerComponent, selector: "mv-conversion-viewer", inputs: ["originalUrl", "downloadFileName", "height", "enableAnnotations", "enableRedactions", "annotationSet"], outputs: ["mediaLoadStatus", "viewerException", "documentTitle"] }, { kind: "directive", type: RotationPersistDirective, selector: "[mvRotationPersist]" }, { kind: "component", type: ConfirmActionDialogComponent, selector: "mv-confirm-action" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MediaViewerComponent, decorators: [{
            type: Component,
            args: [{ selector: 'mv-media-viewer', encapsulation: ViewEncapsulation.None, template: "<div\n  id=\"outerContainer\"\n  [ngClass]=\"{\n    'has-redact-bar': toolbarEvents.redactionMode | async,\n    'icp-mode': icpEventService.enabled | async,\n    'is-redaction-preview': toolbarEvents.redactionPreview | async,\n    sidebarOpen: toolbarEvents.sidebarOpen | async,\n    'has-scroll-bar': hasScrollBar,\n    'has-different-page-size': hasDifferentPageSize$ | async\n  }\"\n  [ngStyle]=\"{ width: width }\"\n>\n  <mv-comments-summary\n    *ngIf=\"showCommentSummary\"\n    [title]=\"documentTitle || 'Comment Summary'\"\n    [contentType]=\"contentType\"\n  >\n  </mv-comments-summary>\n\n  <mv-confirm-action\n    *ngIf=\"icpEventService.leavingSession | async\"\n  ></mv-confirm-action>\n\n  <div id=\"mainContainer\">\n    <mv-main-toolbar\n      *ngIf=\"showToolbar\"\n      [enableAnnotations]=\"enableAnnotations\"\n      [enableICP]=\"enableICP\"\n      [enableRedactions]=\"enableRedactions\"\n      [contentType]=\"contentType\"\n    >\n    </mv-main-toolbar>\n    <mv-redaction-toolbar\n      [showRedactSearch]=\"enableRedactSearch\"\n      *ngIf=\"toolbarEvents.redactionMode | async\"\n    ></mv-redaction-toolbar>\n    <mv-highlight-toolbar\n      *ngIf=\"toolbarEvents.highlightToolbarSubject | async\"\n    ></mv-highlight-toolbar>\n    <mv-icp-toolbar *ngIf=\"icpEventService.enabled | async\"></mv-icp-toolbar>\n\n    <div #viewerRef>\n      <mv-conversion-viewer\n        *ngIf=\"convertibleContent\"\n        (documentTitle)=\"onDocumentTitleChange($event)\"\n        (mediaLoadStatus)=\"onMediaLoad($event)\"\n        (viewerException)=\"onLoadException($event)\"\n        [enableAnnotations]=\"enableAnnotations\"\n        [enableRedactions]=\"enableRedactions\"\n        [annotationSet]=\"enableAnnotations ? (annotationSet$ | async) : null\"\n        [originalUrl]=\"url\"\n        [downloadFileName]=\"downloadFileName\"\n        [height]=\"viewerHeight\"\n        mvRotationPersist\n      >\n      </mv-conversion-viewer>\n      <mv-pdf-viewer\n        *ngIf=\"contentType === 'pdf'\"\n        #pdfViewer\n        (mediaLoadStatus)=\"onMediaLoad($event)\"\n        (pdfViewerException)=\"onLoadException($event)\"\n        (documentTitle)=\"onDocumentTitleChange($event)\"\n        [url]=\"url\"\n        [enableAnnotations]=\"enableAnnotations\"\n        [enableRedactions]=\"enableRedactions\"\n        [enableICP]=\"enableICP\"\n        [annotationSet]=\"enableAnnotations ? (annotationSet$ | async) : null\"\n        [downloadFileName]=\"downloadFileName\"\n        [height]=\"viewerHeight\"\n        [caseId]=\"caseId\"\n        mvRotationPersist\n      >\n      </mv-pdf-viewer>\n      <mv-image-viewer\n        *ngIf=\"contentType === 'image'\"\n        (mediaLoadStatus)=\"onMediaLoad($event)\"\n        (imageViewerException)=\"onLoadException($event)\"\n        [url]=\"url\"\n        [enableAnnotations]=\"enableAnnotations\"\n        [annotationSet]=\"enableAnnotations ? (annotationSet$ | async) : null\"\n        [downloadFileName]=\"downloadFileName\"\n        [height]=\"viewerHeight\"\n        mvRotationPersist\n      >\n      </mv-image-viewer>\n      <mv-multimedia-player\n        *ngIf=\"multimediaContent\"\n        [multimediaOn]=\"multimediaPlayerEnabled\"\n        [url]=\"url\"\n        [downloadFileName]=\"downloadFileName\"\n        (loadStatus)=\"onMediaLoad($event)\"\n      >\n      </mv-multimedia-player>\n      <mv-unsupported-viewer\n        *ngIf=\"unsupportedContent\"\n        [url]=\"url\"\n        [typeException]=\"typeException\"\n        [downloadFileName]=\"downloadFileName\"\n        (loadStatus)=\"onMediaLoad($event)\"\n        (unsupportedViewerException)=\"onLoadException($event)\"\n      >\n      </mv-unsupported-viewer>\n    </div>\n  </div>\n</div>\n" }]
        }], ctorParameters: () => [{ type: i1.Store }, { type: ToolbarButtonVisibilityService }, { type: ToolbarEventService }, { type: AnnotationApiService }, { type: CommentService }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: IcpEventService }], propDecorators: { viewerRef: [{
                type: ViewChild,
                args: ['viewerRef', { static: false }]
            }], url: [{
                type: Input
            }], downloadFileName: [{
                type: Input
            }], contentType: [{
                type: Input
            }], showToolbar: [{
                type: Input
            }], toolbarButtonOverrides: [{
                type: Input
            }], height: [{
                type: Input
            }], width: [{
                type: Input
            }], mediaLoadStatus: [{
                type: Output
            }], viewerException: [{
                type: Output
            }], toolbarEventsOutput: [{
                type: Output
            }], unsavedChanges: [{
                type: Output
            }], enableAnnotations: [{
                type: Input
            }], annotationApiUrl: [{
                type: Input
            }], enableRedactions: [{
                type: Input
            }], enableICP: [{
                type: Input
            }], multimediaPlayerEnabled: [{
                type: Input
            }], enableRedactSearch: [{
                type: Input
            }], caseId: [{
                type: Input
            }] } });

class ToolbarModule {
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ToolbarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: ToolbarModule, declarations: [SearchBarComponent,
            MainToolbarComponent,
            RedactionToolbarComponent,
            IcpToolbarComponent,
            RedactionSearchBarComponent,
            HighlightToolbarComponent], imports: [CommonModule,
            FormsModule,
            OverlayModule,
            RouterModule, i5$1.RpxTranslationModule], exports: [MainToolbarComponent,
            SearchBarComponent,
            RedactionToolbarComponent,
            IcpToolbarComponent,
            RedactionSearchBarComponent,
            HighlightToolbarComponent] }); }
    /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ToolbarModule, providers: [
            ToolbarButtonVisibilityService
        ], imports: [CommonModule,
            FormsModule,
            OverlayModule,
            RouterModule,
            RpxTranslationModule.forChild()] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ToolbarModule, decorators: [{
            type: NgModule,
            args: [{
                    declarations: [
                        SearchBarComponent,
                        MainToolbarComponent,
                        RedactionToolbarComponent,
                        IcpToolbarComponent,
                        RedactionSearchBarComponent,
                        HighlightToolbarComponent
                    ],
                    providers: [
                        ToolbarButtonVisibilityService
                    ],
                    exports: [
                        MainToolbarComponent,
                        SearchBarComponent,
                        RedactionToolbarComponent,
                        IcpToolbarComponent,
                        RedactionSearchBarComponent,
                        HighlightToolbarComponent
                    ],
                    imports: [
                        CommonModule,
                        FormsModule,
                        OverlayModule,
                        RouterModule,
                        RpxTranslationModule.forChild(),
                    ]
                }]
        }] });

class BookmarksApiService {
    constructor(httpClient) {
        this.httpClient = httpClient;
        this.ANNOTATIONS_API = '/em-anno';
    }
    getBookmarks(documentId) {
        return this.httpClient
            .get(`${this.ANNOTATIONS_API}/${documentId}/bookmarks`, { observe: 'response', withCredentials: true });
    }
    createBookmark(bookmark) {
        return this.httpClient
            .post(`${this.ANNOTATIONS_API}/bookmarks`, bookmark, { observe: 'response', withCredentials: true })
            .pipe(map(response => response.body));
    }
    updateBookmark(bookmark) {
        return this.httpClient
            .put(`${this.ANNOTATIONS_API}/bookmarks`, bookmark, { observe: 'response', withCredentials: true })
            .pipe(map(response => response.body));
    }
    updateMultipleBookmarks(bookmarks) {
        return this.httpClient
            .put(`${this.ANNOTATIONS_API}/bookmarks_multiple`, bookmarks, { observe: 'response', withCredentials: true })
            .pipe(map(response => response.body));
    }
    deleteBookmark(bookmarkId) {
        return this.httpClient
            .delete(`${this.ANNOTATIONS_API}/bookmarks/${bookmarkId}`, { observe: 'response', withCredentials: true })
            .pipe(map(response => response.body));
    }
    deleteMultipleBookmarks(payload) {
        return this.httpClient
            .request('DELETE', `${this.ANNOTATIONS_API}/bookmarks_multiple`, { body: payload, observe: 'response', withCredentials: true })
            .pipe(map(response => response.body));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BookmarksApiService, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BookmarksApiService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BookmarksApiService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$1.HttpClient }] });

class SharedModule {
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SharedModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: SharedModule, declarations: [GovUkDateComponent,
            GovUkErrorMessageComponent,
            GovUkFieldsetComponent,
            GovUkLabelComponent], imports: [CommonModule,
            FormsModule,
            ReactiveFormsModule,
            CommonModule,
            RouterModule], exports: [GovUkDateComponent,
            GovUkErrorMessageComponent,
            GovUkFieldsetComponent,
            GovUkLabelComponent] }); }
    /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SharedModule, imports: [CommonModule,
            FormsModule,
            ReactiveFormsModule,
            CommonModule,
            RouterModule] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SharedModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        CommonModule,
                        FormsModule,
                        ReactiveFormsModule,
                        CommonModule,
                        RouterModule
                    ],
                    declarations: [
                        GovUkDateComponent,
                        GovUkErrorMessageComponent,
                        GovUkFieldsetComponent,
                        GovUkLabelComponent
                    ],
                    exports: [
                        GovUkDateComponent,
                        GovUkErrorMessageComponent,
                        GovUkFieldsetComponent,
                        GovUkLabelComponent
                    ]
                }]
        }] });

class AnnotationsModule {
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: AnnotationsModule, declarations: [MetadataLayerComponent,
            AnnotationViewComponent,
            BoxHighlightCreateComponent,
            AnnotationSetComponent,
            RectangleComponent,
            CommentComponent,
            CommentSetHeaderComponent,
            CommentSearchComponent,
            TextHighlightDirective,
            CtxToolbarComponent,
            CommentSetComponent,
            CommentsNavigateComponent,
            TextareaAutoExpandDirective,
            CommentsSummaryComponent,
            TagsComponent,
            MomentDatePipe,
            CommentFilterComponent,
            FilterPipe,
            UnsnakePipe], imports: [A11yModule,
            CommonModule,
            FormsModule,
            HttpClientModule,
            MutableDivModule,
            TagInputModule,
            RouterModule,
            ReactiveFormsModule,
            NgxDatatableModule,
            SharedModule, i5$1.RpxTranslationModule], exports: [AnnotationViewComponent,
            BoxHighlightCreateComponent,
            AnnotationSetComponent,
            CommentSetComponent,
            CommentSetHeaderComponent,
            CommentSearchComponent,
            CommentsSummaryComponent,
            TagsComponent,
            CommentFilterComponent,
            MomentDatePipe,
            FilterPipe,
            UnsnakePipe,
            MetadataLayerComponent] }); }
    /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationsModule, providers: [
            AnnotationApiService,
            BookmarksApiService,
            CommentSetRenderService,
            HighlightCreateService,
            CommentService,
            TagsServices
        ], imports: [A11yModule,
            CommonModule,
            FormsModule,
            HttpClientModule,
            MutableDivModule,
            TagInputModule,
            RouterModule,
            ReactiveFormsModule,
            NgxDatatableModule,
            SharedModule,
            RpxTranslationModule.forChild()] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationsModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        A11yModule,
                        CommonModule,
                        FormsModule,
                        HttpClientModule,
                        MutableDivModule,
                        TagInputModule,
                        RouterModule,
                        ReactiveFormsModule,
                        NgxDatatableModule,
                        SharedModule,
                        RpxTranslationModule.forChild()
                    ],
                    declarations: [
                        MetadataLayerComponent,
                        AnnotationViewComponent,
                        BoxHighlightCreateComponent,
                        AnnotationSetComponent,
                        RectangleComponent,
                        CommentComponent,
                        CommentSetHeaderComponent,
                        CommentSearchComponent,
                        TextHighlightDirective,
                        CtxToolbarComponent,
                        CommentSetComponent,
                        CommentsNavigateComponent,
                        TextareaAutoExpandDirective,
                        CommentsSummaryComponent,
                        TagsComponent,
                        MomentDatePipe,
                        CommentFilterComponent,
                        FilterPipe,
                        UnsnakePipe
                    ],
                    providers: [
                        AnnotationApiService,
                        BookmarksApiService,
                        CommentSetRenderService,
                        HighlightCreateService,
                        CommentService,
                        TagsServices
                    ],
                    exports: [
                        AnnotationViewComponent,
                        BoxHighlightCreateComponent,
                        AnnotationSetComponent,
                        CommentSetComponent,
                        CommentSetHeaderComponent,
                        CommentSearchComponent,
                        CommentsSummaryComponent,
                        TagsComponent,
                        CommentFilterComponent,
                        MomentDatePipe,
                        FilterPipe,
                        UnsnakePipe,
                        MetadataLayerComponent
                    ]
                }]
        }] });

class AnnotationEffects {
    constructor(actions$, annotationApiService) {
        this.actions$ = actions$;
        this.annotationApiService = annotationApiService;
        this.loadAnnotation$ = createEffect(() => this.actions$.pipe(ofType(LOAD_ANNOTATION_SET), map((action) => action.payload), switchMap((documentId) => {
            return this.annotationApiService.getAnnotationSet(documentId).pipe(map(res => {
                if (res.status === 204) {
                    return new LoadAnnotationSetFail(res);
                }
                return new LoadAnnotationSetSucess(res);
            }), catchError(error => {
                return of(new LoadAnnotationSetFail(error));
            }));
        })));
        this.postAnnotation$ = createEffect(() => this.actions$.pipe(ofType(SAVE_ANNOTATION), concatMap((action) => {
            return this.annotationApiService.postAnnotation(action.payload).pipe(map(annotations => {
                return new SaveAnnotationSuccess(annotations);
            }), catchError(error => {
                return of(new LoadAnnotationSetFail(error));
            }));
        })));
        this.deleteAnnotation$ = createEffect(() => this.actions$.pipe(ofType(DELETE_ANNOTATION), map((action) => action.payload), exhaustMap((annotation) => {
            return this.annotationApiService.deleteAnnotation(annotation).pipe(map(result => {
                return new DeleteAnnotationSuccess(annotation);
            }), catchError(error => {
                return of(new DeleteAnnotationFail(error));
            }));
        })));
        this.saveAnnotationSet$ = createEffect(() => this.actions$.pipe(ofType(SAVE_ANNOTATION_SET), map((action) => action.payload), switchMap((annotationSet) => {
            return this.annotationApiService.postAnnotationSet(annotationSet).pipe(map(res => {
                return new SaveAnnotationSetSuccess(res);
            }), catchError(error => {
                return of(new SaveAnnotationSetFail(error));
            }));
        })));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationEffects, deps: [{ token: i1$2.Actions }, { token: AnnotationApiService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationEffects }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AnnotationEffects, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$2.Actions }, { type: AnnotationApiService }] });

class BookmarksEffects {
    constructor(actions$, store, bookmarksApiService) {
        this.actions$ = actions$;
        this.store = store;
        this.bookmarksApiService = bookmarksApiService;
        this.loadBookmarks$ = createEffect(() => this.actions$.pipe(ofType(LOAD_BOOKMARKS), withLatestFrom(this.store.pipe(select(getDocumentId))), map(([, documentId]) => documentId), exhaustMap((documentId) => this.bookmarksApiService.getBookmarks(documentId)
            .pipe(map(res => new LoadBookmarksSuccess(res)), catchError(err => of(new LoadBookmarksFailure(err)))))));
        this.createBookmark$ = createEffect(() => this.actions$.pipe(ofType(CREATE_BOOKMARK), map((action) => action.payload), exhaustMap((bookmark) => this.bookmarksApiService.createBookmark(bookmark)
            .pipe(map(bmrk => new CreateBookmarkSuccess(bmrk)), catchError(error => of(new CreateBookmarkFailure(error)))))));
        this.moveBookmark$ = createEffect(() => this.actions$.pipe(ofType(MOVE_BOOKMARK), map((action) => action.payload), exhaustMap((bookmarks) => this.bookmarksApiService.updateMultipleBookmarks(bookmarks)
            .pipe(map(bmrks => new MoveBookmarkSuccess(bmrks)), catchError(error => of(new MoveBookmarkFailure(error)))))));
        this.deleteBookmark$ = createEffect(() => this.actions$.pipe(ofType(DELETE_BOOKMARK), map((action) => action.payload), exhaustMap(({ deleted, updated }) => this.bookmarksApiService.deleteMultipleBookmarks({ deleted, updated })
            .pipe(switchMap(() => {
            if (updated) {
                return [
                    new DeleteBookmarkSuccess(deleted),
                    new UpdateBookmarkSuccess(updated)
                ];
            }
            else {
                return [new DeleteBookmarkSuccess(deleted)];
            }
        }), catchError(error => of(new DeleteBookmarkFailure(error)))))));
        this.updateBookmark$ = createEffect(() => this.actions$.pipe(ofType(UPDATE_BOOKMARK), map((action) => action.payload), switchMap((bookmark) => this.bookmarksApiService.updateBookmark(bookmark)
            .pipe(map(bmrk => new UpdateBookmarkSuccess(bmrk)), catchError(error => of(new UpdateBookmarkFailure(error)))))));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BookmarksEffects, deps: [{ token: i1$2.Actions }, { token: i1.Store }, { token: BookmarksApiService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BookmarksEffects }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BookmarksEffects, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$2.Actions }, { type: i1.Store }, { type: BookmarksApiService }] });

class RedactionApiService {
    constructor(httpClient) {
        this.httpClient = httpClient;
        this.markupsApiUrl = '/api/markups';
        this.redactApiUrl = '/api/redaction';
        this.markupsSearchApiUrl = '/api/markups/search';
    }
    getRedactions(documentId) {
        const fixedUrl = `${this.markupsApiUrl}/${documentId}`;
        return this.httpClient
            .get(fixedUrl, { observe: 'response', withCredentials: true });
    }
    saveRedaction(body) {
        return this.httpClient
            .post(this.markupsApiUrl, body, { observe: 'response', withCredentials: true })
            .pipe(map(response => response.body), catchError(() => []));
    }
    saveBulkRedaction(body) {
        return this.httpClient
            .post(this.markupsSearchApiUrl, body, { observe: 'response', withCredentials: true })
            .pipe(map(response => response.body), catchError(() => []));
    }
    deleteRedaction(payload) {
        const url = `${this.markupsApiUrl}/${payload.documentId}/${payload.redactionId}`;
        return this.httpClient
            .delete(url, { observe: 'response', withCredentials: true })
            .pipe(map(response => response.body));
    }
    deleteAllMarkers(documentId) {
        const url = `${this.markupsApiUrl}/${documentId}`;
        return this.httpClient
            .delete(url, { observe: 'response', withCredentials: true })
            .pipe(map(response => response.body));
    }
    redact(payload) {
        return this.httpClient
            .post(this.redactApiUrl, payload, { observe: 'response', withCredentials: true, responseType: 'blob' })
            .pipe(map(response => response), catchError(() => []));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedactionApiService, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedactionApiService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedactionApiService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$1.HttpClient }] });

class RedactionEffects {
    constructor(actions$, redactionApiService, toolbarEvents) {
        this.actions$ = actions$;
        this.redactionApiService = redactionApiService;
        this.toolbarEvents = toolbarEvents;
        this.loadRedactions$ = createEffect(() => this.actions$.pipe(ofType(LOAD_REDACTIONS), map((action) => action.payload), switchMap((documentId) => {
            return this.redactionApiService.getRedactions(documentId).pipe(map(resp => {
                return new LoadRedactionSuccess(resp.body);
            }), catchError(error => {
                return of(new LoadRedactionFailure(error));
            }));
        })));
        this.saveRedaction$ = createEffect(() => this.actions$.pipe(ofType(SAVE_REDACTION), map((action) => action.payload), exhaustMap((redaction) => {
            return this.redactionApiService.saveRedaction(redaction).pipe(map(resp => {
                return new SaveRedactionSuccess(resp);
            }), catchError(error => {
                return of(new SaveRedactionFailure(error));
            }));
        })));
        this.saveBulkRedaction$ = createEffect(() => this.actions$.pipe(ofType(SAVE_BULK_REDACTION), map((action) => action.payload), exhaustMap((redaction) => {
            return this.redactionApiService.saveBulkRedaction(redaction).pipe(tap(() => this.toolbarEvents.redactAllInProgressSubject.next(false))).pipe(map(resp => {
                return new SaveBulkRedactionSuccess(resp);
            }), catchError(error => {
                return of(new SaveBulkRedactionFailure(error));
            }));
        })));
        this.deleteRedaction$ = createEffect(() => this.actions$.pipe(ofType(DELETE_REDACTION), map((action) => action.payload), exhaustMap((redactionPayload) => {
            return this.redactionApiService.deleteRedaction(redactionPayload).pipe(map(() => {
                return new DeleteRedactionSuccess(redactionPayload);
            }), catchError(error => {
                return of(new DeleteRedactionFailure(error));
            }));
        })));
        this.redact$ = createEffect(() => this.actions$.pipe(ofType(REDACT), map((action) => action.payload), exhaustMap((redactionPayload) => {
            return this.redactionApiService.redact(redactionPayload).pipe(map((result) => {
                const header = result.headers.get('content-disposition').split('filename=');
                const filename = header.length > 1 ? header[1].replace(/"/g, '')
                    : `redacted-document-${redactionPayload.documentId}`;
                return new RedactSuccess({ blob: result.body, filename });
            }), catchError(error => {
                return of(new RedactFailure(error));
            }));
        })));
        this.unmarkAll$ = createEffect(() => this.actions$.pipe(ofType(UNMARK_ALL), map((action) => action.payload), exhaustMap((documentId) => {
            return this.redactionApiService.deleteAllMarkers(documentId).pipe(map(result => {
                return new UnmarkAllSuccess();
            }), catchError(error => {
                return of(new DeleteRedactionFailure(error));
            }));
        })));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedactionEffects, deps: [{ token: i1$2.Actions }, { token: RedactionApiService }, { token: ToolbarEventService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedactionEffects }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RedactionEffects, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$2.Actions }, { type: RedactionApiService }, { type: ToolbarEventService }] });

class DocumentConversionApiService {
    constructor(httpClient) {
        this.httpClient = httpClient;
        this.documentConversionUrl = '/doc-assembly/convert';
    }
    convert(documentId) {
        return this.httpClient
            .post(`${this.documentConversionUrl}/${documentId}`, {}, { observe: 'response', withCredentials: true, responseType: 'blob' })
            .pipe(map(response => response), catchError(error => of(error)));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentConversionApiService, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentConversionApiService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentConversionApiService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$1.HttpClient }] });

class RotationApiService {
    constructor(httpClient) {
        this.httpClient = httpClient;
        this.rotationApiUrl = '/em-anno/metadata';
    }
    getRotation(documentId) {
        const fixedUrl = `${this.rotationApiUrl}/${documentId}`;
        return this.httpClient
            .get(fixedUrl, { observe: 'response', withCredentials: true });
    }
    saveRotation(payload) {
        const fixedUrl = `${this.rotationApiUrl}/`;
        return this.httpClient
            .post(fixedUrl, payload, { observe: 'response', withCredentials: true })
            .pipe(map(response => response), catchError(() => []));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RotationApiService, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RotationApiService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RotationApiService, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$1.HttpClient }] });

class DocumentEffects {
    constructor(actions$, documentConversionService, rotationApiService) {
        this.actions$ = actions$;
        this.documentConversionService = documentConversionService;
        this.rotationApiService = rotationApiService;
        this.convert$ = createEffect(() => this.actions$.pipe(ofType(CONVERT), map((action) => action.payload), exhaustMap((documentId) => {
            return this.documentConversionService.convert(documentId).pipe(map((result) => {
                const url = URL.createObjectURL(result.body);
                return new ConvertSuccess(url);
            }), catchError(error => {
                return of(new ConvertFailure(error));
            }));
        })));
        this.loadRotation$ = createEffect(() => this.actions$.pipe(ofType(LOAD_ROTATION), map((action) => action.payload), switchMap((documentId) => {
            return this.rotationApiService.getRotation(documentId).pipe(map(resp => {
                return new LoadRotationSuccess(resp.body);
            }), catchError(error => {
                return of(new LoadRotationFailure(error));
            }));
        })));
        this.saveRotation$ = createEffect(() => this.actions$.pipe(ofType(SAVE_ROTATION), map((action) => action.payload), switchMap((payload) => {
            return this.rotationApiService.saveRotation(payload).pipe(map(resp => {
                return new SaveRotationSuccess(resp.body);
            }), catchError(error => {
                return of(new SaveRotationFailure(error));
            }));
        })));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentEffects, deps: [{ token: i1$2.Actions }, { token: DocumentConversionApiService }, { token: RotationApiService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentEffects }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DocumentEffects, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$2.Actions }, { type: DocumentConversionApiService }, { type: RotationApiService }] });

class IcpSessionApiService {
    constructor(httpClient) {
        this.httpClient = httpClient;
        this.ICP_SESSION_API = '/icp/sessions';
    }
    loadSession(payload) {
        return this.httpClient
            .get(`${this.ICP_SESSION_API}/${payload.caseId}/${payload.documentId}`, { observe: 'response', withCredentials: true })
            .pipe(map(response => {
            const token = response.headers.get('X-Access-Token');
            return {
                ...response.body,
                token
            };
        }));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpSessionApiService, deps: [{ token: i1$1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpSessionApiService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpSessionApiService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }], ctorParameters: () => [{ type: i1$1.HttpClient }] });

class IcpEffects {
    constructor(actions$, icpApiService, icpUpdateService) {
        this.actions$ = actions$;
        this.icpApiService = icpApiService;
        this.icpUpdateService = icpUpdateService;
        this.loadIcpSession$ = createEffect(() => this.actions$.pipe(ofType(LOAD_ICP_SESSION), map((action) => action.payload), exhaustMap((payload) => this.icpApiService.loadSession(payload)
            .pipe(map(res => new JoinIcpSocketSession(res)), catchError(error => of(new LoadIcpSessionFailure(error)))))));
        this.joinIcpSocketSession$ = createEffect(() => this.actions$.pipe(ofType(JOIN_ICP_SOCKET_SESSION), map((action) => action.payload), switchMap((res) => this.icpUpdateService.joinSession(res.username, res.session, res.token)
            .pipe(map(participants => new IcpSocketSessionJoined({ session: res.session, participantInfo: participants }))))));
    }
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpEffects, deps: [{ token: i1$2.Actions }, { token: IcpSessionApiService }, { token: IcpUpdateService }], target: i0.ɵɵFactoryTarget.Injectable }); }
    /** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpEffects }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: IcpEffects, decorators: [{
            type: Injectable
        }], ctorParameters: () => [{ type: i1$2.Actions }, { type: IcpSessionApiService }, { type: IcpUpdateService }] });

const effects = [AnnotationEffects, BookmarksEffects, RedactionEffects, DocumentEffects, IcpEffects];

class MediaViewerModule {
    /** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MediaViewerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
    /** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: MediaViewerModule, declarations: [PdfViewerComponent,
            SideBarComponent,
            BookmarksComponent,
            OutlineItemComponent,
            ImageViewerComponent,
            UnsupportedViewerComponent,
            MultimediaPlayerComponent,
            MediaViewerComponent,
            ConvertibleContentViewerComponent,
            GrabNDragDirective,
            RotationPersistDirective,
            HighlightCreateDirective,
            ConfirmActionDialogComponent,
            RedactionComponent,
            BookmarkIconsComponent,
            ParticipantsListComponent], imports: [CommonModule,
            HttpClientModule,
            ToolbarModule,
            AnnotationsModule,
            TagInputModule,
            FormsModule,
            ReactiveFormsModule,
            RouterModule, i1.StoreFeatureModule, i1$2.EffectsFeatureModule, MutableDivModule,
            CdkTreeModule,
            DragDropModule, i5$1.RpxTranslationModule], exports: [MediaViewerComponent] }); }
    /** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MediaViewerModule, providers: [
            PdfJsWrapperFactory,
            CommentService,
            RedactionApiService,
            DocumentConversionApiService,
            RotationApiService,
        ], imports: [CommonModule,
            HttpClientModule,
            ToolbarModule,
            AnnotationsModule,
            TagInputModule,
            FormsModule,
            ReactiveFormsModule,
            RouterModule,
            StoreModule.forFeature('media-viewer', reducers),
            EffectsModule.forFeature(effects),
            MutableDivModule,
            CdkTreeModule,
            DragDropModule,
            RpxTranslationModule.forChild()] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MediaViewerModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [
                        CommonModule,
                        HttpClientModule,
                        ToolbarModule,
                        AnnotationsModule,
                        TagInputModule,
                        FormsModule,
                        ReactiveFormsModule,
                        RouterModule,
                        StoreModule.forFeature('media-viewer', reducers),
                        EffectsModule.forFeature(effects),
                        MutableDivModule,
                        CdkTreeModule,
                        DragDropModule,
                        RpxTranslationModule.forChild()
                    ],
                    declarations: [
                        PdfViewerComponent,
                        SideBarComponent,
                        BookmarksComponent,
                        OutlineItemComponent,
                        ImageViewerComponent,
                        UnsupportedViewerComponent,
                        MultimediaPlayerComponent,
                        MediaViewerComponent,
                        ConvertibleContentViewerComponent,
                        GrabNDragDirective,
                        RotationPersistDirective,
                        HighlightCreateDirective,
                        ConfirmActionDialogComponent,
                        RedactionComponent,
                        BookmarkIconsComponent,
                        ParticipantsListComponent
                    ],
                    providers: [
                        PdfJsWrapperFactory,
                        CommentService,
                        RedactionApiService,
                        DocumentConversionApiService,
                        RotationApiService,
                    ],
                    exports: [
                        MediaViewerComponent
                    ]
                }]
        }] });

/*
 * Public API Surface of media-viewer
 */

/**
 * Generated bundle index. Do not edit.
 */

export { ADD_OR_EDIT_COMMENT, APPLY_COMMENT_SUMMARY_FILTER, AddOrEditComment, AnnotationApiService, AnnotationEffects, AnnotationSetComponent, AnnotationViewComponent, AnnotationsModule, ApplyCommentSymmaryFilter, BoxHighlightCreateComponent, CLEAR_COMMENT_SUMMARY_FILTER, ClearCommentSummaryFilters, CommentFilterComponent, CommentSearchComponent, CommentSetComponent, CommentSetHeaderComponent, CommentsSummaryComponent, DELETE_ANNOTATION, DELETE_ANNOTATION_FAIL, DELETE_ANNOTATION_SUCCESS, DeleteAnnotation, DeleteAnnotationFail, DeleteAnnotationSuccess, FilterPipe, HighlightToolbarComponent, IcpToolbarComponent, LOAD_ANNOTATION_SET, LOAD_ANNOTATION_SET_FAIL, LOAD_ANNOTATION_SET_SUCCESS, LoadAnnotationSet, LoadAnnotationSetFail, LoadAnnotationSetSucess, MainToolbarComponent, MediaViewerComponent, MediaViewerModule, MetadataLayerComponent, MomentDatePipe, RedactionSearchBarComponent, RedactionToolbarComponent, ResponseType, SAVE_ANNOTATION, SAVE_ANNOTATION_FAIL, SAVE_ANNOTATION_SET, SAVE_ANNOTATION_SET_FAIL, SAVE_ANNOTATION_SET_SUCCESS, SAVE_ANNOTATION_SUCCESS, SEARCH_COMMENT, SELECT_ANNOTATION, SaveAnnotation, SaveAnnotationFail, SaveAnnotationSet, SaveAnnotationSetFail, SaveAnnotationSetSuccess, SaveAnnotationSuccess, SearchBarComponent, SearchComment, SelectedAnnotation, TagsComponent, ToolbarButtonVisibilityService, ToolbarModule, UnsnakePipe, ViewerException, commentSearchQ, getAnnoEnt, getAnnoPageEnt, getAnnoPerPage, getAnnoSet, getAnnotationEntities, getAnnotationSet, getAnnotationsSetState, getCommentEntities, getCommentEnts, getCommentSummary, getCommentSummaryFilters, getCommentsArray, getComponentSearchQueries, getComponentSearchText, getDocumentIdSetId, getFilteredAnnotations, getPageEntities, getSelectedAnno, getSelectedAnnotation, getSet, getSummaryFilters, initialState, reducer };
//# sourceMappingURL=hmcts-media-viewer.mjs.map