"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const Setting_1 = require("../../models/Setting");
const Tag_1 = require("../../models/Tag");
const BaseModel_1 = require("../../BaseModel");
const Note_1 = require("../../models/Note");
const registry_1 = require("../../registry");
const ResourceFetcher_1 = require("../../services/ResourceFetcher");
const DecryptionWorker_1 = require("../../services/DecryptionWorker");
const eventManager_1 = require("../../eventManager");
const BaseItem_1 = require("../../models/BaseItem");
const shim_1 = require("../../shim");
const syncInfoUtils_1 = require("../../services/synchronizer/syncInfoUtils");
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
let sortNoteListTimeout = null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
exports.default = async (store, _next, action, dispatch) => {
    const newState = store.getState();
    eventManager_1.default.appStateEmit(newState);
    let refreshTags = false;
    let sortNoteList = false;
    if (action.type === 'FOLDER_SET_COLLAPSED' || action.type === 'FOLDER_TOGGLE') {
        Setting_1.default.setValue('collapsedFolderIds', newState.collapsedFolderIds);
    }
    if (action.type === 'SETTING_UPDATE_ONE' && !!action.key.match(/^sync\.\d+\.path$/)) {
        registry_1.reg.resetSyncTarget();
    }
    if (action.type === 'SETTING_UPDATE_ONE') {
        (0, syncInfoUtils_1.onRevisionServiceSettingsChanged)(action.key, action.value);
    }
    let mustAutoAddResources = false;
    if (action.type === 'SETTING_UPDATE_ONE' && action.key === 'sync.resourceDownloadMode') {
        mustAutoAddResources = true;
    }
    if (action.type === 'DECRYPTION_WORKER_SET' && action.state === 'idle' && action.decryptedItemCounts && !!action.decryptedItemCounts[BaseModel_1.default.TYPE_NOTE]) {
        mustAutoAddResources = true;
    }
    // In general the DecryptionWorker is started via events, such as when an encrypted note
    // is received via sync, or after an encrypted has been downloaded. However, in some cases,
    // in particular when an item cannot be decrypted, the service won't retry automatically,
    // since it's not useful because the data most likely is corrupted. In some
    // cases the user might want to retry anyway, so we enable this by starting the service
    // automatically after each full sync (which is triggered when the user presses the sync
    // button, but not when a note is saved).
    if (action.type === 'SYNC_COMPLETED' && action.isFullSync) {
        void DecryptionWorker_1.default.instance().scheduleStart();
    }
    if (action.type === 'NOTE_DELETE' ||
        action.type === 'NOTE_UPDATE_ALL' ||
        action.type === 'NOTE_TAG_REMOVE' ||
        action.type === 'TAG_UPDATE_ONE') {
        refreshTags = true;
    }
    // handle the case when the selected note has been moved to another
    // folder and a new one is now selected, need to show correct tags for it
    if (action.type === 'NOTE_UPDATE_ONE' && action.changedFields.indexOf('parent_id') >= 0) {
        refreshTags = true;
    }
    if (action.type === 'NOTE_UPDATE_ONE') {
        sortNoteList = true;
    }
    if (action.type === 'NOTE_SELECT' || action.type === 'NAV_BACK') {
        const noteIds = newState.provisionalNoteIds.slice();
        for (const noteId of noteIds) {
            if (action.id === noteId)
                continue;
            registry_1.reg.logger().info('Provisional was not modified - deleting it');
            await Note_1.default.delete(noteId, { sourceDescription: 'reduxSharedMiddleware: Delete provisional note' });
        }
    }
    if (action.type === 'NOTE_DELETE' ||
        action.type === 'NOTE_SELECT' ||
        action.type === 'NOTE_SELECT_TOGGLE' ||
        action.type === 'TAG_UPDATE_ONE' ||
        action.type === 'TAG_UPDATE_ALL') {
        let noteTags = [];
        // We don't need to show tags unless only one note is selected.
        // For new notes, the old note is still selected, but we don't want to show any tags.
        if (newState.selectedNoteIds &&
            newState.selectedNoteIds.length === 1) {
            noteTags = await Tag_1.default.tagsByNoteId(newState.selectedNoteIds[0]);
        }
        store.dispatch({
            type: 'SET_NOTE_TAGS',
            items: noteTags,
        });
    }
    if (mustAutoAddResources) {
        void ResourceFetcher_1.default.instance().autoAddResources();
    }
    if (refreshTags) {
        store.dispatch({
            type: 'TAG_UPDATE_ALL',
            items: await Tag_1.default.allWithNotes(),
        });
    }
    if (sortNoteList) {
        if (sortNoteListTimeout)
            shim_1.default.clearTimeout(sortNoteListTimeout);
        sortNoteListTimeout = null;
        // We sort the note lists with two seconds debounce because doing can be
        // very slow and would have to be done every time a note is added.
        if (Date.now() - newState.noteListLastSortTime > 10000) {
            dispatch({ type: 'NOTE_SORT' });
        }
        else {
            sortNoteListTimeout = shim_1.default.setTimeout(() => {
                sortNoteListTimeout = null;
                dispatch({ type: 'NOTE_SORT' });
            }, 2000);
        }
    }
    if (action.type.startsWith('SHARE_') && action.type !== 'SHARE_CACHE_RESTORE') {
        const serialized = JSON.stringify(newState.shareService);
        Setting_1.default.setValue('sync.shareCache', serialized);
        BaseItem_1.default.syncShareCache = JSON.parse(serialized);
    }
    // For debugging purposes: it seems in some case an empty note is saved to
    // the note array, so in that case display a log statements so that it can
    // be debugged.
    // https://discourse.joplinapp.org/t/how-to-recover-corrupted-database/9367/3?u=laurent
    if (action.type.indexOf('NOTE_') === 0) {
        for (const note of newState.notes) {
            if (!note) {
                registry_1.reg.logger().error('Detected empty element in note array', action);
            }
        }
    }
    if (action.type === 'WINDOW_OPEN') {
        eventManager_1.default.emit(eventManager_1.EventName.WindowOpen, {
            windowId: action.windowId,
        });
    }
    else if (action.type === 'WINDOW_CLOSE') {
        eventManager_1.default.emit(eventManager_1.EventName.WindowClose, {
            windowId: action.windowId,
        });
    }
};
//# sourceMappingURL=reduxSharedMiddleware.js.map