/*
 * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
 *
 * SPDX-License-Identifier: AGPL-3.0-only
 */

import { store } from '..'
import type { Note, NotePermissions } from '../../api/notes/types'
import type {
  AddTableAtCursorAction,
  FormatSelectionAction,
  FormatType,
  InsertTextAtCursorAction,
  ReplaceInMarkdownContentAction,
  SetNoteDetailsFromServerAction,
  SetNoteDocumentContentAction,
  SetNotePermissionsFromServerAction,
  UpdateCursorPositionAction,
  UpdateNoteTitleByFirstHeadingAction,
  UpdateTaskListCheckboxAction
} from './types'
import { NoteDetailsActionType } from './types'
import type { CursorSelection } from '../editor/types'

/**
 * Sets the content of the current note, extracts and parses the frontmatter and extracts the markdown content part.
 * @param content The note content as it is written inside the editor pane.
 */
export const setNoteContent = (content: string): void => {
  store.dispatch({
    type: NoteDetailsActionType.SET_DOCUMENT_CONTENT,
    content: content
  } as SetNoteDocumentContentAction)
}

/**
 * Sets the note metadata for the current note from an API response DTO to the redux.
 * @param apiResponse The NoteDTO received from the API to store into redux.
 */
export const setNoteDataFromServer = (apiResponse: Note): void => {
  store.dispatch({
    type: NoteDetailsActionType.SET_NOTE_DATA_FROM_SERVER,
    noteFromServer: apiResponse
  } as SetNoteDetailsFromServerAction)
}

/**
 * Sets the note permissions for the current note from an API response DTO to the redux.
 * @param apiResponse The NotePermissionsDTO received from the API to store into redux.
 */
export const setNotePermissionsFromServer = (apiResponse: NotePermissions): void => {
  store.dispatch({
    type: NoteDetailsActionType.SET_NOTE_PERMISSIONS_FROM_SERVER,
    notePermissionsFromServer: apiResponse
  } as SetNotePermissionsFromServerAction)
}

/**
 * Updates the note title in the redux by the first heading found in the markdown content.
 * @param firstHeading The content of the first heading found in the markdown content.
 */
export const updateNoteTitleByFirstHeading = (firstHeading?: string): void => {
  store.dispatch({
    type: NoteDetailsActionType.UPDATE_NOTE_TITLE_BY_FIRST_HEADING,
    firstHeading: firstHeading
  } as UpdateNoteTitleByFirstHeadingAction)
}

/**
 * Changes a checkbox state in the note document content. Triggered when a checkbox in the rendering is clicked.
 *
 * @param lineInDocumentContent The line in the document content to change.
 * @param checked true if the checkbox is checked, false otherwise.
 */
export const setCheckboxInMarkdownContent = (lineInDocumentContent: number, checked: boolean): void => {
  store.dispatch({
    type: NoteDetailsActionType.UPDATE_TASK_LIST_CHECKBOX,
    checkboxChecked: checked,
    changedLine: lineInDocumentContent
  } as UpdateTaskListCheckboxAction)
}

/**
 * Replaces a string in the markdown content in the global application state.
 *
 * @param replaceable The string that should be replaced
 * @param replacement The replacement for the replaceable
 */
export const replaceInMarkdownContent = (replaceable: string, replacement: string): void => {
  store.dispatch({
    type: NoteDetailsActionType.REPLACE_IN_MARKDOWN_CONTENT,
    placeholder: replaceable,
    replacement
  } as ReplaceInMarkdownContentAction)
}

export const updateCursorPositions = (selection: CursorSelection): void => {
  store.dispatch({
    type: NoteDetailsActionType.UPDATE_CURSOR_POSITION,
    selection
  } as UpdateCursorPositionAction)
}

export const formatSelection = (formatType: FormatType): void => {
  store.dispatch({
    type: NoteDetailsActionType.FORMAT_SELECTION,
    formatType
  } as FormatSelectionAction)
}

export const addTableAtCursor = (rows: number, columns: number): void => {
  store.dispatch({
    type: NoteDetailsActionType.ADD_TABLE_AT_CURSOR,
    rows,
    columns
  } as AddTableAtCursorAction)
}

export const replaceSelection = (text: string, cursorSelection?: CursorSelection): void => {
  store.dispatch({
    type: NoteDetailsActionType.REPLACE_SELECTION,
    text,
    cursorSelection
  } as InsertTextAtCursorAction)
}
