text: import React, { useState, useEffect, useRef, useContext } from "react"
  import PropTypes from "prop-types"
  import styled from "styled-components"
  import { MDXRenderer } from "gatsby-plugin-mdx"
  import Img from "gatsby-image"
  import VisibilitySensor from "react-visibility-sensor"
  import { motion } from "framer-motion"
  
  import { useOnScreen } from "../../hooks"
  import Context from "../../context"
  import ContentWrapper from "../../styles/contentWrapper"
  import Underlining from "../../styles/underlining"
  import Icon from "../../components/icons"
  import { lightTheme, darkTheme } from "../../styles/theme"
  import LinkAnimated from "../linkAnimated"
  
  const StyledSection = styled.section`
    width: 100%;
    height: auto;
    background: ${({ theme }) => theme.colors.background};
    margin-top: 6rem;
    .cta-btn {
      display: block;
      text-align: center;
      margin: 2rem auto;
      @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
        margin: 0 auto;
      }
    }
  `
  
  const StyledContentWrapper = styled(ContentWrapper)`
    && {
      width: 100%;
      height: 100%;
      position: relative;
      display: flex;
      flex-direction: column;
      justify-content: center;
      padding-right: 0;
      padding-left: 0;
      @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
        padding-right: 2.5rem;
        padding-left: 2.5rem;
      }
      .section-title {
        padding-right: 2.5rem;
        padding-left: 2.5rem;
        @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
          padding-right: 0;
          padding-left: 0;
        }
      }
      .projects {
        display: flex;
        flex-direction: row;
        margin-top: -2.5rem;
        padding: 2.5rem 2.5rem;
        overflow-x: scroll;
        overflow-y: hidden;
        -webkit-overflow-scrolling: touch;
        &::-webkit-scrollbar {
          display: none;
        }
        @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
          flex-direction: column;
          margin-top: 0;
          padding: 0;
          overflow: visible;
        }
        /* Show scrollbar if desktop and wrapper width > viewport width */
        @media (hover: hover) {
          scrollbar-color: ${({ theme }) => theme.colors.scrollBar} transparent; // Firefox only
          &::-webkit-scrollbar {
            display: block;
            -webkit-appearance: none;
          }
  
          &::-webkit-scrollbar:horizontal {
            height: 0.8rem;
          }
  
          &::-webkit-scrollbar-thumb {
            border-radius: 8px;
            border: 0.2rem solid ${({ theme }) => theme.colors.background};
            background-color: ${({ theme }) => theme.colors.scrollBar};
          }
  
          &::-webkit-scrollbar-track {
            background-color: ${({ theme }) => theme.colors.background};
            border-radius: 8px;
          }
        }
      }
      .counter {
        position: absolute;
        top: 2.2rem;
        right: 2.5rem;
        font-size: 1.125rem;
        font-weight: 500;
        @media (min-width: ${({ theme }) => theme.breakpoints.sm}) {
          display: none;
        }
      }
    }
  `
  
  const StyledProject = styled(motion.div)`
    display: flex;
    flex-direction: column-reverse;
    justify-content: flex-end;
    align-items: center;
    margin-top: 0;
    margin-bottom: 2rem;
    flex-shrink: 0;
    padding-right: 2.5rem;
    max-width: 20rem;
    @media (min-width: ${({ theme }) => theme.breakpoints.xs}) {
      max-width: 25rem;
      margin-top: 2rem;
      padding-right: 5rem;
    }
    @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
      justify-content: space-between;
      flex-shrink: 1;
      max-width: 62.5rem;
      margin-bottom: 10rem;
      padding-right: 0;
      /* Positioning of image and details should vary */
      flex-direction: ${({ position }) =>
        position % 2 !== 0 ? "row" : "row-reverse"};
    }
    .details {
      width: 100%;
      max-width: 25rem;
      display: flex;
      flex-direction: column;
      margin-top: 3rem;
      @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
        margin-top: 0;
      }
      .category {
        font-size: 0.875rem;
        line-height: 1rem;
        text-transform: uppercase;
        letter-spacing: +1px;
      }
      .title {
        margin-top: 0.625rem;
        margin-bottom: 0.625rem;
        font-size: 1.375rem;
        line-height: 1.625rem;
        font-weight: 700;
      }
      .tags {
        display: flex;
        flex-wrap: wrap;
        margin-top: 1.5rem;
        line-height: 1.2rem;
        span {
          margin-right: 1rem;
          margin-bottom: 1rem;
        }
      }
      .links {
        display: flex;
        justify-content: flex-start;
        align-items: center;
        width: 100%;
        margin-top: 1rem;
        a {
          display: inline-block;
          margin-right: 2rem;
        }
        svg {
          width: 1.3rem;
          height: 1.3rem;
          transition: all 0.3s ease-out;
        }
        svg:hover {
          fill: ${({ theme }) => theme.colors.primary};
        }
      }
    }
    .screenshot {
      width: 100%;
      max-width: 25rem;
      height: 15rem;
      border-radius: ${({ theme }) => theme.borderRadius};
      box-shadow: 0 0 2.5rem rgba(0, 0, 0, 0.16);
      transition: all 0.3s ease-out;
      &:hover {
        transform: translate3d(0px, -0.125rem, 0px);
        box-shadow: 0 0 2.5rem rgba(0, 0, 0, 0.32);
      }
      @media (min-width: ${({ theme }) => theme.breakpoints.md}) {
        height: 18.75rem;
      }
    }
  `
  
  const Projects = ({ content }) => {
    const { darkMode } = useContext(Context).state
    const sectionDetails = content[0].node
    const projects = content.slice(1, content.length)
  
    // visibleProject is needed to show which project is currently
    // being viewed in the horizontal slider on mobile and tablet
    const [visibleProject, setVisibleProject] = useState(1)
  
    // projects don't track the visibility by using the onScreen hook
    // instead they use react-visibility-sensor, therefore their visibility
    // is also stored differently
    const [onScreen, setOnScreen] = useState({})
    const handleOnScreen = el => {
      if (!onScreen[el]) {
        const updatedOnScreen = { ...onScreen }
        updatedOnScreen[el] = true
        setOnScreen(updatedOnScreen)
      }
    }
    const pVariants = {
      hidden: { opacity: 0, y: 20 },
      visible: { opacity: 1, y: 0 },
    }
  
    useEffect(() => {
      // mobile and tablet only: set first project as visible in the
      // horizontal slider
      setVisibleProject(1)
      // required for animations: set visibility for all projects to
      // "false" initially
      let initial = {}
      projects.forEach(project => {
        initial[project.node.frontmatter.position] = false
      })
      setOnScreen(initial)
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [])
  
    // Required for animating the title
    const tRef = useRef()
    const tOnScreen = useOnScreen(tRef)
    const tVariants = {
      hidden: { opacity: 0 },
      visible: { opacity: 1 },
    }
  
    // Required for animating the button
    const bRef = useRef()
    const bOnScreen = useOnScreen(bRef)
    const bVariants = {
      hidden: { opacity: 0 },
      visible: { opacity: 1 },
    }
  
    return (
      <StyledSection id="projects">
        <StyledContentWrapper>
          <motion.div
            ref={tRef}
            variants={tVariants}
            animate={tOnScreen ? "visible" : "hidden"}
          >
            <h3 className="section-title">
              <LinkAnimated selected>
                {sectionDetails.frontmatter.title}
              </LinkAnimated>
            </h3>
            <div className="counter">
              {visibleProject} / {projects.length}
            </div>
          </motion.div>
          <div className="projects">
            {projects.map(project => {
              const { body, frontmatter } = project.node
              return (
                <VisibilitySensor
                  key={frontmatter.position}
                  onChange={() => handleOnScreen(frontmatter.position)}
                  partialVisibility={true}
                  minTopValue={100}
                >
                  <StyledProject
                    position={frontmatter.position}
                    variants={pVariants}
                    animate={
                      onScreen[frontmatter.position] ? "visible" : "hidden"
                    }
                  >
                    <div className="details">
                      <div className="category">
                        {frontmatter.emoji} {frontmatter.category}
                      </div>
                      <div className="title">{frontmatter.title}</div>
                      <MDXRenderer>{body}</MDXRenderer>
                      <div className="tags">
                        {frontmatter.tags.map(tag => (
                          <Underlining key={tag} highlight>
                            {tag}
                          </Underlining>
                        ))}
                      </div>
                      <div className="links">
                        {frontmatter.github && (
                          <a
                            href={frontmatter.github}
                            target="_blank"
                            rel="nofollow noopener noreferrer"
                            aria-label="External Link"
                          >
                            <Icon
                              name="github"
                              color={
                                darkMode
                                  ? darkTheme.colors.subtext
                                  : lightTheme.colors.subtext
                              }
                            />
                          </a>
                        )}
                        {frontmatter.external && (
                          <a
                            href={frontmatter.external}
                            target="_blank"
                            rel="nofollow noopener noreferrer"
                            aria-label="External Link"
                          >
                            <Icon
                              name="external"
                              color={
                                darkMode
                                  ? darkTheme.colors.subtext
                                  : lightTheme.colors.subtext
                              }
                            />
                          </a>
                        )}
                      </div>
                    </div>
                    {/* If image in viewport changes, update state accordingly */}
                    <VisibilitySensor
                      onChange={() => setVisibleProject(frontmatter.position)}
                    >
                      <Img
                        className="screenshot"
                        fluid={frontmatter.screenshot.childImageSharp.fluid}
                      />
                    </VisibilitySensor>
                  </StyledProject>
                </VisibilitySensor>
              )
            })}
          </div>
        </StyledContentWrapper>
      </StyledSection>
    )
  }
  
  Projects.propTypes = {
    content: PropTypes.arrayOf(
      PropTypes.shape({
        node: PropTypes.shape({
          body: PropTypes.string.isRequired,
          frontmatter: PropTypes.object.isRequired,
        }).isRequired,
      }).isRequired
    ).isRequired,
  }
  
  export default Projects
  