import React, { useEffect } from "react"
import Fuse from "fuse.js"
import { graphql } from "gatsby"
import { useBreakpoint } from "gatsby-plugin-breakpoints"
import { navigate } from "@reach/router"

import "./index.css"

import Layout from "../layouts/layout"
import OrgCard from "../components/org-card"
import SEO from "../components/seo"
import Notification from "../components/notification"
import { Grid } from "semantic-ui-react"
import { useAppDispatch, useAppSelector } from "../store"
import { getSearch, setSearch } from "../store/search"
import { getFilters, setFilters } from "../store/filters"

const getOrganizations = data => {
  return data.allOrganization.edges.map(orgNode => {
    let org = orgNode.node
    for (const yearKey of Object.keys(org.years)) {
      if (yearKey[0] === "_") {
        if (org.years[yearKey] !== null) {
          let year = yearKey.slice(1)
          org.years[year] = org.years[yearKey]
        }
        delete org.years[yearKey]
      }
    }
    return org
  })
}

const getFuseSearch = organizations => {
  const options = {
    threshold: 0.3,
    keys: ["name"],
  }

  return new Fuse(organizations, options)
}

const getFilteredOrganizations = (data, searchQuery, filters) => {
  const organizations = getOrganizations(data)
  let filteredOrganizations = organizations

  if (searchQuery !== "") {
    const fuse = getFuseSearch(organizations)
    filteredOrganizations = fuse.search(searchQuery).map(res => res.item)
  }

  // NOTE: YEARS - intersection, REST - union.
  const { years, categories, technologies, topics } = filters

  if (years.length > 0) {
    let newFilteredOrganizations = []
    for (const organization of filteredOrganizations) {
      let matches = 0
      for (const year of years) {
        if (Object.keys(organization.years).includes(year)) {
          matches++
        }
      }
      if (matches === years.length) {
        newFilteredOrganizations.push(organization)
      }
    }
    filteredOrganizations = newFilteredOrganizations
  }

  if (categories.length > 0) {
    let newFilteredOrganizations = []
    for (const organization of filteredOrganizations) {
      for (const category of categories) {
        if (organization.category === category) {
          newFilteredOrganizations.push(organization)
          break
        }
      }
    }
    filteredOrganizations = newFilteredOrganizations
  }

  if (technologies.length > 0) {
    let newFilteredOrganizations = []
    for (const organization of filteredOrganizations) {
      for (const technology of technologies) {
        if (organization.technologies.includes(technology)) {
          newFilteredOrganizations.push(organization)
          break
        }
      }
    }
    filteredOrganizations = newFilteredOrganizations
  }

  if (topics.length > 0) {
    let newFilteredOrganizations = []
    for (const organization of filteredOrganizations) {
      for (const topic of topics) {
        if (organization.topics.includes(topic)) {
          newFilteredOrganizations.push(organization)
          break
        }
      }
    }
    filteredOrganizations = newFilteredOrganizations
  }

  return filteredOrganizations
}

const IndexPage = ({ data, location }) => {
  const dispatch = useAppDispatch()
  const searchQuery = useAppSelector(getSearch)
  const filters = useAppSelector(getFilters)

  // Any url would work here.
  const currentURL = new URL("https://www.gsocorganizations.dev/")

  try {
    currentURL.search = location.search
  } catch (err) {}

  const getSearchQueryInUrl = () => {
    return currentURL.searchParams.get("search") || ""
  }

  const getFiltersFromUrl = () => {
    return (
      JSON.parse(currentURL.searchParams.get("filters")) || {
        years: [],
        categories: [],
        technologies: [],
        topics: [],
      }
    )
  }

  useEffect(() => {
    dispatch(setSearch(getSearchQueryInUrl()))
    dispatch(setFilters(getFiltersFromUrl()))
  }, [])

  useEffect(() => {
    // Don't append search params if there is no filter or searchQurey.
    if (searchQuery !== "") {
      currentURL.searchParams.set("search", searchQuery)
    } else {
      currentURL.searchParams.delete("search")
    }
    if (Object.values(filters).filter(arr => arr.length !== 0).length !== 0) {
      currentURL.searchParams.set("filters", JSON.stringify(filters))
    } else {
      currentURL.searchParams.delete("filters")
    }
    navigate(currentURL.search === "" ? "/" : currentURL.search)
  }, [searchQuery, filters])

  const [orgCards, setOrgCards] = React.useState([])

  React.useEffect(() => {
    let filteredOrganizations = getFilteredOrganizations(
      data,
      searchQuery,
      filters
    )

    const cards = []
    for (const organization of filteredOrganizations) {
      cards.push(
        <Grid.Column>
          <OrgCard data={organization} />
        </Grid.Column>
      )
    }

    setOrgCards(cards)
  }, [searchQuery, filters])

  const metaDescription =
    "View and analyse the info of the organizations participating in Google Summer of Code and filter them by various parameters."
  const meta = [
    {
      name: "description",
      content: metaDescription,
    },
    {
      name: "keywords",
      content:
        "gsoc, analysis, organizations, statistics, filter, years, google summer of code, technologies, topics, categories, projects",
    },
    {
      property: "og:type",
      content: "website",
    },
    {
      property: "og:title",
      content: data.site.siteMetadata.title,
    },
    {
      property: "og:description",
      content: metaDescription,
    },
    {
      property: "og:image",
      content: `${data.site.siteMetadata.siteUrl}/images/screenshot.png`,
    },
    {
      property: "og:site_name",
      content: data.site.siteMetadata.title,
    },
    {
      property: "og:url",
      content: data.site.siteMetadata.siteUrl,
    },
    {
      name: "twitter:card",
      content: "summary_large_image",
    },
    {
      name: "twitter:title",
      content: data.site.siteMetadata.title,
    },
    {
      name: "twitter:description",
      content: metaDescription,
    },
    {
      name: "twitter:image",
      content: `${data.site.siteMetadata.siteUrl}/images/screenshot.png`,
    },
  ]

  const cardColumns = useBreakpoint().l ? 3 : 4

  React.useEffect(() => {
    setTimeout(() => {
      ;(window.adsbygoogle = window.adsbygoogle || []).push({})
    }, 2000)
  }, [])

  return (
    <Layout>
      <SEO title={"Home"} meta={meta} />
      <Grid className="index-org-cards-grid">
        <Notification />
      </Grid>
      <div style={{ marginTop: "1rem", textAlign: "center" }}>
        <a className="ui orange label">{orgCards.length} results</a>
      </div>
      <Grid className="index-org-cards-grid" stackable columns={cardColumns}>
        {orgCards}
      </Grid>
      <div style={{ padding: "1rem" }}>
        <ins
          className="adsbygoogle"
          style={{ display: "block" }}
          data-ad-client="ca-pub-9769516184087442"
          data-ad-slot="5525920548"
          data-ad-format="auto"
          data-full-width-responsive="false"
        ></ins>
      </div>
    </Layout>
  )
}

export const query = graphql`
  query {
    site {
      siteMetadata {
        title
        siteUrl
      }
    }
    allOrganization {
      edges {
        node {
          category
          description
          name
          technologies
          image_url
          image_background_color
          topics
          url
          years {
            _2016 {
              num_projects
              projects_url
            }
            _2017 {
              num_projects
              projects_url
            }
            _2018 {
              num_projects
              projects_url
            }
            _2019 {
              num_projects
              projects_url
            }
            _2020 {
              num_projects
              projects_url
            }
            _2021 {
              num_projects
              projects_url
            }
            _2022 {
              num_projects
              projects_url
            }
          }
        }
      }
    }
  }
`

export default IndexPage