import React, { useContext, createContext, useReducer, Provider, useCallback, useEffect, useMemo } from "react"
import { Route, Routes, useLocation, useNavigate } from "react-router-dom";
import env from "../env";
import Home from "./home";
import Navbar from "./nav";

const jsonRegex = /^application\/json/
const textRegex = /^text\/plain/
const request = async (url: string, method: string, body: any) => {
  const headers = new Headers();
  if (method !== 'GET') {
    headers.append('Content-Type', 'application/json');
    body = typeof body === 'object' ? JSON.stringify(body) : body;
  }
  return fetch(env.API_HOST + url, {
    method,
    headers,
    body
  }).then(response => {
    if (!response.ok) throw new Error(response.statusText)
    if (textRegex.test(response.headers.get('content-type') || '')) {
      return response.text()
    } else if (jsonRegex.test(response.headers.get('content-type') || '')) {
      return response.json()
    } else {
      return response.blob()
    }
  })
}

const AppContext = createContext(null);
export const useAppContext = () => useContext(AppContext);
type AppState = {
  error: string | null,
  loading: boolean
}
const AppProvider: Provider<any> = AppContext.Provider
export default function App() {
  const [state, setState] = useReducer((state: AppState, newState: AppState) => ({ ...state, ...newState }), {
    error: null,
    loading: false
  }) as any
  const location = useLocation()
  const { pathname, search } = location
  const queries = useMemo(() => {
    const q = new URLSearchParams(search)
    const o: any = {}
    q.forEach((v, k) => o[k] = v)
    return o
  }, [search])
  const redirect = useNavigate()
  return (
    <AppProvider value={{
      state,
      setState,
      request,
      pathname,
      queries,
      redirect
    }}>
      <Navbar />
      <Routes>
        <Route path="*" element={<Home />} />
      </Routes>
    </AppProvider >
  )
}