import { createSelector } from "redux-bundler";

export default (opts) => {
  const defaults = {
    addons: {},
    name: "panel",
    onClose: null,
    size: 300,
  };

  const config = Object.assign({}, defaults, opts);
  const uCaseName = config.name.charAt(0).toUpperCase() + config.name.slice(1);
  const baseType = config.name.toUpperCase();

  // actions
  const OPENED = `${baseType}_OPENED`;
  const CLOSED = `${baseType}_CLOSED`;
  const RESIZED = `${baseType}_RESIZED`;

  // selectors
  const selectContents = `select${uCaseName}Contents`;
  const selectSize = `select${uCaseName}Size`;
  const selectIsOpen = `select${uCaseName}IsOpen`;

  // actionCreators
  const doOpen = `do${uCaseName}Open`;
  const doClose = `do${uCaseName}Close`;
  const doSetSize = `do${uCaseName}SetSize`;

  // reactors

  return Object.assign(
    {
      name: config.name,

      getReducer: () => {
        const initialData = {
          contents: null,
          onClose: config.onClose,
          size: config.size,
        };

        return (state = initialData, { type, payload }) => {
          switch (type) {
            case OPENED:
            case CLOSED:
            case RESIZED:
              return Object.assign({}, state, payload);
            default:
              return state;
          }
        };
      },

      [doOpen]: (contents) => ({ dispatch }) => {
        dispatch({
          type: OPENED,
          payload: {
            contents: contents,
          },
        });
      },

      [doClose]: () => ({ dispatch }) => {
        dispatch({
          type: CLOSED,
          payload: {
            contents: null,
          },
        });
      },

      [doSetSize]: (size) => ({ dispatch }) => {
        dispatch({
          type: RESIZED,
          payload: {
            size: size,
          },
        });
      },

      [selectIsOpen]: createSelector(selectContents, (contents) => {
        return !!contents;
      }),

      [selectContents]: (state) => {
        return state[config.name].contents;
      },

      [selectSize]: (state) => {
        if (!state[config.name].contents) return 0;
        return state[config.name].size;
      },
    },
    config.addons
  );
};
