/**
 * Download box container that wraps a chart
 * @author Gabe Abrams
 * @author Jackson Parsells
 */

// Import React
import React, { useReducer } from 'react';

// Import DownloadButton
import DownloadButton from './DownloadButton';

/*------------------------------------------------------------------------*/
/*                                  Style                                 */
/*------------------------------------------------------------------------*/

const style = `
  .DownloadBox-download {
    position: absolute;
    top: 0;
    right: 15px;
    cursor: pointer;
  }

  .DownloadBox-no-outline {
    border: 1px solid transparent;
  }

  .DownloadBox-outlined {
    border: 1px solid #007bff;
  }
`;

/*------------------------------------------------------------------------*/
/*                                  Types                                 */
/*------------------------------------------------------------------------*/

// Props definition
type Props = {
  // Title of the chart
  title: string,
  // Chart Data for papa parse
  chartData: {
    [k: string]: string | number
  }[],
  // Chart element to show
  children: React.ReactNode,
};

/*------------------------------------------------------------------------*/
/*                                  State                                 */
/*------------------------------------------------------------------------*/

/* -------- State Definition -------- */

type State = {
  // True if user is hovering over the chart
  hovering: boolean,
};

/* ------------- Actions ------------ */

// Types of actions
enum ActionType {
  // Start hovering
  StartHovering = 'start-hovering',
  // Stop hovering
  StopHovering = 'stop-hovering',
}

// Action definitions
type Action = (
  | {
    // Action type
    type: (
      | ActionType.StartHovering
      | ActionType.StopHovering
    ),
  }
);

/**
 * Reducer that executes actions
 * @author Gabe Abrams
 * @param state current state
 * @param action action to execute
 */
const reducer = (state: State, action: Action): State => {
  switch (action.type) {
    case ActionType.StartHovering: {
      return {
        ...state,
        hovering: true,
      };
    }
    case ActionType.StopHovering: {
      return {
        ...state,
        hovering: false,
      };
    }
    default: {
      return state;
    }
  }
};

/*------------------------------------------------------------------------*/
/*                                Component                               */
/*------------------------------------------------------------------------*/

const DownloadBox: React.FC<Props> = (props) => {
  /*------------------------------------------------------------------------*/
  /*                                  Setup                                 */
  /*------------------------------------------------------------------------*/

  /* -------------- Props ------------- */

  // Destructure all props
  const {
    title,
    chartData,
    children,
  } = props;

  /* -------------- State ------------- */

  // Initial state
  const initialState: State = {
    hovering: false,
  };

  // Initialize state
  const [state, dispatch] = useReducer(reducer, initialState);

  // Destructure common state
  const {
    hovering,
  } = state;

  /*------------------------------------------------------------------------*/
  /*                                 Render                                 */
  /*------------------------------------------------------------------------*/

  /*----------------------------------------*/
  /*                 Main UI                */
  /*----------------------------------------*/

  return (
    <div
      // use similar logic to below to add for focus and hovering
      className={hovering ? 'DownloadBox-outlined' : 'DownloadBox-no-outline'}
      onMouseEnter={() => {
        dispatch({ type: ActionType.StartHovering });
      }}
      onFocus={() => {
        dispatch({ type: ActionType.StartHovering });
      }}
      onMouseLeave={() => {
        dispatch({ type: ActionType.StopHovering });
      }}
      onBlur={() => {
        dispatch({ type: ActionType.StopHovering });
      }}
    >
      {/* Style */}
      <style>
        {style}
      </style>

      {/* Chart */}
      {children}

      {/* Download Button */}
      <div className={`DownloadBox-download ${hovering ? '' : 'sr-only'}`}>
        <DownloadButton
          title={title}
          chartData={chartData}
          filename={`${title}.csv`}
        />
      </div>
    </div>
  );
};

/*------------------------------------------------------------------------*/
/*                                 Wrap Up                                */
/*------------------------------------------------------------------------*/

// Export component
export default DownloadBox;
