import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import {
  faTasks,
  faVial,
} from '@fortawesome/free-solid-svg-icons';
import { ThemeProvider } from '@material-ui/core/styles';
import AppBar from './Components/AppBar/AppBar';
import LocationModal from './Components/LocationModal/LocationModal';
// import Header from './Components/Header';
// import LegalModal from './Components/LegalModal';
import theme from './theme';
import getViewportHeight from './utils/getViewportHeight';
import { trackGuideStatus } from './utils/tracking';
import GuideModal from './Components/GuideModal';
import Map from './Components/Map/Map';
import PathwayFlow from './Components/PathwayFlow';
import AppointmentFlow from './Components/AppointmentFlow';
import ActionType from './Components/Types/ActionType';
import LabelMapType from './Components/Types/LabelMapType';
import SearchFilterType from './Components/Types/SearchFilterType';
import DataUpdateSnackbar from './Components/DataUpdateSnackbar';
import fetchLocation from './utils/fetchLocation';

// Layout Component styles
const LayoutContainer = styled.div`
  width: 100vw;
  display: flex;
  flex-direction: column;
`;

const MapContainer = styled.div`
  flex-basis: 100%;
  flex-grow: 1;
  position: relative;
`;

const AppBarContainer = styled.div`
  z-index: 120;
  position: relative;
`;

// Map for toggles and modal line items
export const labelMap: LabelMapType = {
  is_ordering_tests_only_for_those_who_meeting_criteria: {
    sidebar: 'Tests only those meeting criteria',
    card: 'Testing criteria',
    icon: faTasks,
  },
  is_collecting_samples: {
    sidebar: 'Collects samples for testing',
    card: 'Collects samples',
    icon: faVial,
  },
};

// Initial state
const defaultFilters: SearchFilterType = {
  // is_ordering_tests_only_for_those_who_meeting_criteria: false,
  // is_collecting_samples: false,
};

const uuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
const locationIdRegex = /^[a-zA-Z]{2}-.+$/;

export const SearchContext = React.createContext<SearchFilterType>(defaultFilters);
const geocoderContainerRef = React.createRef<any>();

let windowListener: any; // store event handler for resize events
let popListener: any;
let appointmentFlowUrl = '';
let actionType: ActionType;
const App = () => {
  const [viewportHeight, setViewportHeight] = useState(0);
  const [selectedPlace, setSelectedPlace] = useState(null);
  const [guideModalOpen, setGuideModalOpen] = useState(false);
  const [globalMap, setGlobalMap] = useState<any>([]);
  const [showPathwayFlow, setShowPathwayFlow] = useState(false);
  const [showAppointmentFlow, setShowAppointmentFlow] = useState(false);
  const [showLocationModal, setShowLocationModal] = useState(true);
  const [filters, setFilters] = useState(defaultFilters);
  const [filterApplied, setFilterApplied] = useState(false);
  const [fromAssistant, setFromAssistant] = useState(false);
  const [isFirstLoad, setFirstLoad] = useState(true);

  function toggleGuide() {
    setGuideModalOpen((prevState) => !prevState);
    trackGuideStatus(guideModalOpen);
  }

  function runAppointmentFlow(typeFromButton: ActionType, ctaLink: string) {
    setShowLocationModal(false);
    appointmentFlowUrl = ctaLink;
    actionType = typeFromButton;
    setShowAppointmentFlow(true);
  }

  useEffect(() => {
    function triggerRouter() {
      let currentPath = document.location.pathname.substr(1);
      let uriPlace = (selectedPlace as any);
      if ((uuidRegex.test(currentPath) || (locationIdRegex.test(currentPath)))
        && (!selectedPlace || (selectedPlace as any).location_id !== currentPath)) {
  
        fetchLocation(currentPath).then(newPlace => {
          if (isFirstLoad ||
            (uriPlace && uriPlace.location_id === newPlace.location_id)) {
            setSelectedPlace(newPlace);
            globalMap.panTo({lat: newPlace.location_latitude, lng: newPlace.location_longitude});
          }
        });
      }
    }

    if (isFirstLoad && typeof globalMap.panTo === 'function') {
      popListener = window.addEventListener('popstate', e => {
        triggerRouter();
      });

      triggerRouter();
      setFirstLoad(false);

      return function cleanup() {
        window.removeEventListener('popState', popListener);
      }
    }
  }, [globalMap, isFirstLoad, selectedPlace]);

  useEffect(() => {
    const place = (selectedPlace as any);
    if (place) {
      window.history.pushState({}, `COVID-19 Testing Locations - ${place.location_name}`, `/${place.location_id}`);
    } else if (!isFirstLoad) {
      window.history.pushState({}, 'COVID-19 Testing Locations', '/');
    }
  }, [selectedPlace, isFirstLoad]);

  useEffect(() => {
    windowListener = window.addEventListener('resize', () =>
      setViewportHeight(getViewportHeight())
    );
    setViewportHeight(getViewportHeight());
    return function cleanup() {
      window.removeEventListener('resize', windowListener);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <ThemeProvider theme={theme}>
      <SearchContext.Provider value={filters}>
        <LayoutContainer style={{ height: viewportHeight }}>
          <GuideModal
            modalShouldOpen={guideModalOpen}
            handleYesResponse={() => {
              setGuideModalOpen(false);
            }}
            handleNoResponse={() => {
              setFromAssistant(true);
              setShowPathwayFlow(true);
              setGuideModalOpen(false);
            }}
            handleClose={() => {
              setGuideModalOpen(false);
            }}
          />

          {/* <LegalModal /> */}

          <MapContainer>
            <Map
              onClickPin={(place: any) => {
                fetchLocation(place.location_id)
                  .then((data: any) => {
                    setSelectedPlace(data)
                  });
              }}
              setMap={setGlobalMap}
            />
          </MapContainer>
          {selectedPlace !== null && showLocationModal && (
            <LocationModal
              location={selectedPlace}
              onClose={() => {
                setSelectedPlace(null);
              }}
              showPathwayFlow={(shouldShowPathwayFlow: boolean) => {
                if (shouldShowPathwayFlow) {
                  setShowLocationModal(false);
                  setShowPathwayFlow(shouldShowPathwayFlow);
                }
              }}
              runAppointmentFlow={runAppointmentFlow}
              filterApplied={filterApplied}
            />
          )}
          {showPathwayFlow && (
            <PathwayFlow
              fromAssistant={fromAssistant}
              location={selectedPlace}
              setFilter={(
                filterKey: keyof SearchFilterType,
                filterValue: boolean
              ) => {
                setFilters((prevState) => {
                  const newState: SearchFilterType = {
                    ...prevState,
                    [filterKey]: filterValue,
                  };
                  if (
                    newState.is_collecting_samples ||
                    newState.is_ordering_tests_only_for_those_who_meeting_criteria
                  ) {
                    setFilterApplied(true);
                  } else {
                    setFilterApplied(false);
                  }
                  return newState;
                });
              }}
              setFlowFinished={() => {
                setShowLocationModal(true);
                setSelectedPlace(null);
                setShowPathwayFlow(false);
              }}
            />
          )}
          {showAppointmentFlow && (
            <AppointmentFlow
              urlToRender={appointmentFlowUrl}
              actionType={actionType}
              setFlowFinished={() => {
                setShowLocationModal(true);
                setSelectedPlace(null);
                setShowAppointmentFlow(false);
              }}
            />
          )}
          <AppBarContainer>
            <AppBar
              filterApplied={filterApplied}
              geocoderContainerRef={geocoderContainerRef}
              toggleGuide={toggleGuide}
              clearFilters={() => {
                setFilters(defaultFilters);
                setFilterApplied(false);
              }}
              map={globalMap}
            />
          </AppBarContainer>
        </LayoutContainer>
      </SearchContext.Provider>
      <DataUpdateSnackbar />
    </ThemeProvider>
  );
};

export default App;