import { InpTyp, PktEl } from './PktEl';
import { savePKTAction } from "~t/FormEditor/reducer";

// Represents the path to an element in a nested json structure.
// E.g. in the object { typ: 'form', items: [{typ: 'time'}, {typ: 'list'}]},
// the path [items, 0] would refer to the item {typ: 'time'}.
export type Path = Array<string | number>;

const LOAD_PKT_JSON = 'LOAD_PKT_JSON';
export function loadPktJson(pktJson: PktEl, pktName: string, pktId: number) {
  return {
    type: LOAD_PKT_JSON as typeof LOAD_PKT_JSON,
    pktJson,
    pktName,
    pktId,
  };
}

const LOAD_EMPTY_FORM = 'LOAD_EMPTY_FORM';
export function loadEmptyForm() {
  return {
    type: LOAD_EMPTY_FORM as typeof LOAD_EMPTY_FORM,
  };
}

const TOGGLE_EDIT_MODE = 'TOGGLE_EDIT_MODE';
export function toggleEditMode() {
  return {
    type: TOGGLE_EDIT_MODE as typeof TOGGLE_EDIT_MODE,
  };
}

const TOGGLE_DEBUG_INFO = 'TOGGLE_DEBUG_INFO';
export function toggleDebugInfo() {
  return {
    type: TOGGLE_DEBUG_INFO as typeof TOGGLE_DEBUG_INFO,
  };
}
/**
 * @ahmedkortas
 */
// const TOOGLE_TIME_CONTROL = 'TOOGLE_TIME_CONTROL';
// export function toggleTimeControl() {
//   return {
//     type: TOOGLE_TIME_CONTROL as typeof TOOGLE_TIME_CONTROL,
//   };
// }

const TOGGLE_REQUIRED = 'TOGGLE_REQUIRED';
export function toggleRequired(path: Path) {
  return {
    type: TOGGLE_REQUIRED as typeof TOGGLE_REQUIRED,
    path,
  };
}

const INSERT_ELEMENT = 'INSERT_ELEMENT';
export function insertElement(
  elTyp: PktEl['typ'],
  path: Path,
  newItemIndex: number,
  itemType: 'items' | 'tmp'
) {
  return {
    type: 'INSERT_ELEMENT' as typeof INSERT_ELEMENT,
    elTyp,
    path,
    newItemIndex,
    itemType,
  };
}

const DELETE_ELEMENT = 'DELETE_ELEMENT';
export function deleteElement(path: Path) {
  return {
    type: 'DELETE_ELEMENT' as typeof DELETE_ELEMENT,
    path,
  };
}

const SAVE_MODAL_CONTENT = 'SAVE_MODAL_CONTENT';
export function saveModalContent(content: string) {
  return {
    type: 'SAVE_MODAL_CONTENT' as typeof SAVE_MODAL_CONTENT,
    content,
  };
}

const TOGGLE_EDITING = 'TOGGLE_EDITING';
export function toggleEditing(path: Path) {
  return {
    type: TOGGLE_EDITING as typeof TOGGLE_EDITING,
    path,
  };
}

const RENAME_ELEMENT = 'RENAME_ELEMENT';
export function renameElement(path: Path, newName: string) {
  return {
    type: RENAME_ELEMENT as typeof RENAME_ELEMENT,
    path,
    newName,
  };
}

const SET_SPINNER_OPTION_NAME = 'SET_SPINNER_OPTION_NAME';
export function setSpinnerOptionName(
  newName: string,
  spinnerPath: Path,
  optionIndex: number
) {
  return {
    type: SET_SPINNER_OPTION_NAME as typeof SET_SPINNER_OPTION_NAME,
    spinnerPath,
    optionIndex,
    newName,
  };
}

const SET_SPINNER_OPTION_VALUE = 'SET_SPINNER_OPTION_VALUE';
export function setSpinnerOptionValue(
  newValue: string,
  spinnerPath: Path,
  optionIndex: number
) {
  return {
    type: SET_SPINNER_OPTION_VALUE as typeof SET_SPINNER_OPTION_VALUE,
    spinnerPath,
    optionIndex,
    newValue,
  };
}

const SET_SPINNER_OPTION_REQUIRED = 'SET_SPINNER_OPTION_REQUIRED';
export function setSpinnerOptionRequired(
  newValue: boolean,
  spinnerPath: Path,
  optionIndex: number
) {
  return {
    type: SET_SPINNER_OPTION_REQUIRED as typeof SET_SPINNER_OPTION_REQUIRED,
    spinnerPath,
    optionIndex,
    newValue,
  };
}

const ADD_SPINNER_OPTION = 'ADD_SPINNER_OPTION';
export function addSpinnerOption(spinnerPath: Path, optionIndex: number) {
  return {
    type: ADD_SPINNER_OPTION as typeof ADD_SPINNER_OPTION,
    spinnerPath,
    optionIndex,
  };
}

const DELETE_SPINNER_OPTION = 'DELETE_SPINNER_OPTION';
export function deleteSpinnerOption(spinnerPath: Path, optionIndex: number) {
  return {
    type: DELETE_SPINNER_OPTION as typeof DELETE_SPINNER_OPTION,
    spinnerPath,
    optionIndex,
  };
}

const UPDATE_LIST_ELEMENT = 'UPDATE_LIST_ELEMENT';
export function updateListElement(path: Path, newValue: any) {
  return {
    type: UPDATE_LIST_ELEMENT as typeof UPDATE_LIST_ELEMENT,
    path,
    newValue,
  };
}
const SET_HINT = 'SET_HINT';
export function setHint(path: Path, newHint: string) {
  return {
    type: SET_HINT as typeof SET_HINT,
    path,
    newHint,
  };
}
const SET_LISTSRC = 'SET_LISTSRC';
export function setListsrc(path: Path, newListsrc: string) {
  return {
    type: SET_LISTSRC as typeof SET_LISTSRC,
    path,
    newListsrc,
  };
}
const SET_DEFAULT = 'SET_DEFAULT';
export function setDefault(path: Path, newDefault: string) {
  return {
    type: SET_DEFAULT as typeof SET_DEFAULT,
    path,
    newDefault,
  };
}
const SET_EL_TYPE = 'SET_EL_TYPE';
export function setElType(path: Path, newType: PktEl['typ']) {
  return {
    type: SET_EL_TYPE as typeof SET_EL_TYPE,
    path,
    newType,
  };
}

export type Toggle =
  | 'required'
  | 'isdescription'
  | 'movedya'
  | 'addToTag'
  | 'emailsend'
  | 'unfolded'
  | 'en_timestamp'
  | 'isBarcode';

const defaultToggles = ['required'] as Array<Toggle>;
const togglesForElType: { [typ in PktEl['typ']]: Array<Toggle> } = {
  txt: ['isdescription', 'emailsend', 'isBarcode', 'addToTag'],
  num: ['isdescription'],
  spin: ['isdescription', 'en_timestamp', 'addToTag'],
  chk: ['isdescription', 'addToTag'],
  media: [],
  date: ['movedya', 'isdescription'],
  sign: [],
  form: ['unfolded', 'isdescription'],
  ext: [],
  list: [],
  time: [],
  info: [],
  gps: [],
  lovibond: [],
  address: []
};

// Some PKT files in the wild may have invalid typ attributes, e.g. "list".
// To handle that, we just return defaultToggles in that case.
export function getTogglesForElType(typ: PktEl['typ'] | string): Toggle[] {
  if (togglesForElType.hasOwnProperty(typ)) {
    return defaultToggles.concat(togglesForElType[typ]);
  } else {
    return defaultToggles;
  }
}

const TOGGLE_PROPERTY = 'TOGGLE_PROPERTY';
export function toggleProperty(toggle: Toggle, path: Path) {
  return {
    type: TOGGLE_PROPERTY as typeof TOGGLE_PROPERTY,
    path,
    toggle,
  };
}

const SET_PROPERTY = 'SET_PROPERTY';
export function setProperty(path: Path, name: string, value: any) {
  return {
    type: SET_PROPERTY as typeof SET_PROPERTY,
    path,
    name,
    value,
  };
}

const REMOVE_PROPERTY = 'REMOVE_PROPERTY';
export function removeProperty(path: Path, name: string) {
  return {
    type: REMOVE_PROPERTY as typeof REMOVE_PROPERTY,
    path,
    name,
  };
}

const SET_FROM_DATE = 'SET_FROM_DATE';
export function setFromDate(path: Path, offset: number) {
  return {
    type: SET_FROM_DATE as typeof SET_FROM_DATE,
    path,
    offset,
  };
}

const SET_TO_DATE = 'SET_TO_DATE';
export function setToDate(path: Path, offset: number) {
  return {
    type: SET_TO_DATE as typeof SET_TO_DATE,
    path,
    offset,
  };
}

const SAVE_PKT = 'SAVE_PKT';
export function savePkt(pktName: string, pktJson: PktEl) {
  return (dispatch) => {
    dispatch({ type: SAVE_PKT as typeof SAVE_PKT, pktName, pktJson });
    dispatch(savePKTAction(pktName, pktJson));
  };
}

const SAVED_PKT_SUCCESS = 'SAVED_PKT_SUCCESS';
export function savedPktSuccess(pktName: string, pktId: number) {
  return {
    type: SAVED_PKT_SUCCESS as typeof SAVED_PKT_SUCCESS,
    pktName,
    pktId,
  };
}
const SAVED_PKT_FAILURE = 'SAVED_PKT_FAILURE';
export function savedPktFailure(error) {
  return {
    type: SAVED_PKT_FAILURE as typeof SAVED_PKT_FAILURE,
    error,
  };
}

const SET_INPTYP = 'SET_INPTYP';
export function setInpTyp(path: Path, inpTyp: InpTyp | 'none') {
  return {
    type: SET_INPTYP as typeof SET_INPTYP,
    path,
    inpTyp,
  };
}

export type FormEditorAction =
  | ReturnType<typeof loadPktJson>
  | ReturnType<typeof loadEmptyForm>
  | ReturnType<typeof toggleEditMode>
  | ReturnType<typeof toggleDebugInfo>
  | ReturnType<typeof toggleRequired>
  | ReturnType<typeof insertElement>
  | ReturnType<typeof deleteElement>
  | ReturnType<typeof saveModalContent>
  | ReturnType<typeof toggleEditing>
  | ReturnType<typeof renameElement>
  | ReturnType<typeof setSpinnerOptionName>
  | ReturnType<typeof setSpinnerOptionValue>
  | ReturnType<typeof setSpinnerOptionRequired>
  | ReturnType<typeof addSpinnerOption>
  | ReturnType<typeof deleteSpinnerOption>
  | ReturnType<typeof toggleProperty>
  | ReturnType<typeof setHint>
  | ReturnType<typeof setListsrc>
  | ReturnType<typeof setDefault>
  | ReturnType<typeof setElType>
  | ReturnType<typeof setProperty>
  | ReturnType<typeof setFromDate>
  | ReturnType<typeof setToDate>
  | ReturnType<typeof removeProperty>
  | ReturnType<typeof setInpTyp>
  | ReturnType<typeof savePkt>
  | ReturnType<typeof savedPktSuccess>
  | ReturnType<typeof savedPktFailure>;
