import { FieldArray as FormikFieldArray } from "formik";
import React, { useState } from "react";
import {
  SortableContainer,
  SortableElement,
  SortableHandle,
} from "react-sortable-hoc";

import theme from "mazlo-theme";

import { Button } from "../Button";
import { Icon } from "../Icon";
import { View } from "../View";
import styles from "./styles";

type ItemProps = {
  arrayHelpers: any;
  item: any;
  itemDisabled?: boolean;
  itemPadding?: number;
  renderItem: (params: {
    disabled?: boolean;
    item: any;
    index: number;
  }) => React.ReactNode;
  sortIndex: number;
  sorting: boolean;
  value?: any[];
};

const DragHandle = SortableHandle(() => (
  <Icon color={theme.colors.border} name="grip" style={styles.dragHandle} />
));

const Item = SortableElement(
  ({
    sortIndex,
    arrayHelpers,
    item,
    itemDisabled,
    itemPadding = theme.space[4],
    renderItem,
  }: ItemProps) => {
    return (
      <View row style={[styles.itemContainer, { padding: itemPadding }]}>
        <DragHandle />
        <View style={styles.item}>
          {renderItem({ disabled: itemDisabled, item, index: sortIndex })}
        </View>
        <View style={styles.buttonContainer}>
          {!itemDisabled && (
            <Button
              title="✕"
              textStyle={styles.buttonText}
              style={styles.button}
              onPress={() => arrayHelpers.remove(sortIndex)}
              variant="tertiary"
            />
          )}
        </View>
      </View>
    );
  }
);

interface ContainerProps extends Props {
  allowAdd?: boolean;
  arrayHelpers: any;
  sorting: boolean;
}

const ItemContainer = SortableContainer(
  ({
    allowAdd = true,
    arrayHelpers,
    disabled,
    sorting,
    value,
    name,
    buttonTitleAdd = "Add New",
    onAdd,
    ...props
  }: ContainerProps) => {
    return (
      <View style={styles.container}>
        {value &&
          Array.isArray(value) &&
          value.map((item, index) => (
            <Item
              {...props}
              disabled={disabled}
              itemDisabled={disabled}
              key={index}
              index={index}
              sortIndex={index}
              item={item}
              value={value}
              arrayHelpers={arrayHelpers}
              sorting={sorting}
            />
          ))}
        {!disabled && allowAdd && (
          <View style={styles.addButtonContainer}>
            <Button
              variant="secondary"
              title={buttonTitleAdd}
              onPress={() => onAdd(arrayHelpers)}
            />
          </View>
        )}
      </View>
    );
  }
);

type Props = {
  disabled?: boolean;
  itemPadding?: number;
  maxItems?: number;
  name?: string;
  onAdd: (arrayHelpers: any) => any;
  renderItem: (params: {
    disabled?: boolean;
    item: any;
    index: number;
  }) => React.ReactNode;
  value?: any[];
  buttonTitleAdd?: string;
};

const FormArray = ({ maxItems, ...props }: Props) => {
  const [sorting, setSorting] = useState(false);

  return (
    <FormikFieldArray name={props.name}>
      {(arrayHelpers) => (
        <ItemContainer
          {...props}
          allowAdd={
            !maxItems || (maxItems && maxItems > (props.value?.length || 0))
          }
          useDragHandle
          lockAxis="y"
          arrayHelpers={arrayHelpers}
          onSortStart={() => setSorting(true)}
          onSortEnd={({ oldIndex, newIndex }) => {
            setSorting(false);
            arrayHelpers.move(oldIndex, newIndex);
          }}
          sorting={sorting}
        />
      )}
    </FormikFieldArray>
  );
};

export default FormArray;
