import React from 'react';
import ListGroup from 'react-bootstrap/ListGroup';

import { url } from '../../shared/jokes-api';
import Loading from '../../shared/loading';

function reducer(state, action) {
  switch (action.type) {
    case 'loaded':
      return { ...state, loading: false, jokes: action.payload };
    case 'error-loading':
      return { ...state, loading: false, error: action.payload };
    default:
      return state;
  }
}

function useThunkedReducer(reducer, initialState) {
  const [state, dispatch] = React.useReducer(reducer, initialState);

  const thunkedDispatch = React.useCallback(
    action => {
      if (typeof action === 'function') {
        action(thunkedDispatch, state);
      } else {
        dispatch(action);
      }
    },
    [dispatch, state]
  );

  return [state, thunkedDispatch];
}

async function fetchData(dispatch, state) {
  if (state.jokes) return;

  try {
    const rsp = await fetch(url);
    if (rsp.ok) {
      const data = await rsp.json();
      dispatch({ type: 'loaded', payload: data.value });
    } else {
      throw new Error(rsp.statusText);
    }
  } catch (e) {
    dispatch({ type: 'error-loading', payload: e });
  }
}

function useJokes(url) {
  const [state, dispatch] = useThunkedReducer(reducer, {
    jokes: null,
    error: null,
    loading: true
  });

  React.useEffect(() => {
    dispatch(fetchData);
  }); 

  return state;
}

const FetchWithCustomHooks = () => {
  const { loading, error, jokes } = useJokes(url);

  if (loading) {
    return <Loading />;
  }

  if (error) {
    return <div>{error && error.message}</div>;
  }
  return (
    <ListGroup>
      {jokes.map(item => (
        <ListGroup.Item key={item.id}>{item.joke}</ListGroup.Item>
      ))}
    </ListGroup>
  );
};

export default FetchWithCustomHooks;