/**
 * Displays a QR code card, with your choice of URL and specified width.
 * @author Benedikt Arnarsson
 * @author Gabe Abrams
 */

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

// Import dce-reactkit tools
import { LoadingSpinner } from '../../../dce-reactkit';

// Import types
import ErrorWithCode from '../../shared/errors/ErrorWithCode';
import ErrorCode from '../../shared/types/ErrorCode';

// Import helpers
import getQrCardImg from './getQrCardImg';

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

// Props definition
type Props = {
  // The URL to display in the QR code
  url: string,
  // Optional sub-text
  subText?: string,
};

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

/* -------------- Views ------------- */

enum View {
  // When the QR code is being generated
  Loading = 'Loading',
  // Display the QR code
  Displaying = 'Displaying',
}

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

type State = (
  | {
    // Current view
    view: View.Loading,
  }
  | {
    // Current view
    view: View.Displaying,
    // QR code that is being displayed (DataURL)
    qrCode: string,
  }
);

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

// Types of actions
enum ActionType {
  // Set QR code data URL (and stop loading, if applicable)
  DisplayQrCode = 'DisplayQrCode',
  // Start loading QR code
  StartLoading = 'StartLoading',
}

// Action definitions
type Action = (
  | {
    // Action type
    type: ActionType.DisplayQrCode,
    // The data URL that contains the QR code
    qrCodeDataURL: string,
  }
  | {
    // Action type
    type: ActionType.StartLoading,
  }
);

/**
 * Reducer for setting the QR code
 * @author Benedikt Arnarsson
 * @param state current state
 * @param action action to execute
 * @returns updated state
 */
const reducer = (state: State, action: Action): State => {
  switch (action.type) {
    case ActionType.DisplayQrCode: {
      return {
        view: View.Displaying,
        qrCode: action.qrCodeDataURL,
      };
    }
    case ActionType.StartLoading: {
      return {
        view: View.Loading,
      };
    }
    default: {
      return state;
    }
  }
};

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

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

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

  // Destructure all props
  const {
    url,
  } = props;

  const subText = props.subText ?? '';

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

  // Initial state
  const initialState: State = {
    view: View.Loading,
  };

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

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

  /*------------------------------------------------------------------------*/
  /* ------------------------- Lifecycle Functions ------------------------ */
  /*------------------------------------------------------------------------*/

  /**
   * Starts creation of QR code.
   * @author Benedikt Arnarsson
   */
  useEffect(
    () => {
      (async () => {
        if (view === View.Displaying) {
          dispatch({ type: ActionType.StartLoading });
        }
        // const qrCode = await QRCode.toDataURL(value.href, { version: 10 });
        const qrCode = await getQrCardImg(url, subText);
        // console.log('QR code data URL: ', qrCode);
        dispatch({
          type: ActionType.DisplayQrCode,
          qrCodeDataURL: qrCode,
        });
      })();
    },
    [url],
  );

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

  /*----------------------------------------*/
  /* ------------- Validation ------------- */
  /*----------------------------------------*/

  try {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const checkURL = new URL(url);
  } catch (err) {
    const newErr = new ErrorWithCode('Invalid check-in URL', ErrorCode.InvalidURL);
    // TODO: replace
    alert(newErr);
    return <div className="DceQrCode-invalid-URL" />;
  }

  /*----------------------------------------*/
  /* ---------------- Views --------------- */
  /*----------------------------------------*/

  // Body that will be filled with the current view
  let body: React.ReactNode;

  /* ------------- Displaying ------------- */

  if (view === View.Displaying) {
    // Display QR code with card describing it
    body = (
      <a
        id="DCHUI-qr-code"
        download={`CheckIn QR Code for ${subText}.png`}
        href={state.qrCode}
        title='CheckIn QR Code'
        // @ts-ignore
        qrCodeUrl={url}
      >
        <img
          style={{
            width: '100%',
          }}
          src={state.qrCode}
          alt="Sign-in QR code"
        />
      </a>
    );
  }

  /* -------------- Loading --------------- */

  if (view === View.Loading) {
    // Loading...
    body = (
      <LoadingSpinner />
    );
  }

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

  return (
    <div>
      {body}
    </div>
  );
};

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

// Export component
export default QrCard;
