import { EditorState, Selection, TextSelection, Transaction, EditorView, Schema } from '../../prosemirror';
import uuid from '../../plugins/tasks-and-decisions/uuid';

const getListTypes = (listType: TaskDecisionListType, schema: Schema<any,any>): { list, item } => {
  const { decisionList, decisionItem, taskList, taskItem } = schema.nodes;
  if (listType === 'taskList') {
    return {
      list: taskList,
      item: taskItem,
    };
  }

  return {
    list: decisionList,
    item: decisionItem,
  };
};

export type TaskDecisionListType = 'taskList' | 'decisionList';

const isSelectionInAList = (listType: TaskDecisionListType, selection: Selection) => {
  const fromNode = selection.$from.node(selection.$from.depth - 2);
  const endNode = selection.$to.node(selection.$to.depth - 2);

  return fromNode && fromNode.type.name === listType
      && endNode  && endNode.type.name !== listType;
};

export const changeToTaskDecision = (
  view: EditorView,
  listType: TaskDecisionListType
): boolean => {
  const { state } = view;
  const { selection, schema } = state;
  const { list, item } = getListTypes(listType, schema);
  const { tr } = state;

  if (!isSelectionInAList(listType, selection)) {
    // Not a list - convert to one.
    const created = createListAtSelection(tr, list, item, schema, state);
    view.dispatch(tr);
    return created;
  }

  return false;
};

export const createListAtSelection = (tr: Transaction, list: any, item: any, schema: Schema<any, any>, state: EditorState<any>): boolean => {
  const { selection: { $from, $to } } = state;

  if ($from.parent !== $to.parent) {
    // ignore selections across multiple nodes
    return false;
  }

  const { decisionList, taskList } = schema.nodes;
  const isAlreadyDecisionTask = $from.parent.type === decisionList || $from.parent.type === taskList;

  if (isAlreadyDecisionTask) {
    return false;
  }

  const where = $from.before($from.depth);
  const content = $from.node($from.depth).content;

  tr
    .delete(where, $from.end($from.depth))
    .replaceSelectionWith(list.create({ localId: uuid.generate() }, [item.create({}, content)]))
  ;

  // Adjust selection into new item, if not there (e.g. in full page editor)
  const newSelection = tr.selection;
  if (newSelection.$from.parent.type !== item) {
    tr.setSelection(TextSelection.create(tr.doc, newSelection.$from.pos - 2));
  }

  return true;
};
