const { graphql } = require("gatsby")
const { createFilePath } = require("gatsby-source-filesystem")
const helper = require("./scripts/buildHelpers")
const path = require(`path`)
const fs = require("fs")

const requiredArticleFrontmatter = ["authors", "date"]

const LAYOUT_RESOURCES = "resources"
const LAYOUT_SPOTLIGHTS = "spotlights"
const LAYOUT_REGULAR = "regular"
const LAYOUT_HOME = "home"

function resolveLayout(path) {
  if (path === "/") {
    return LAYOUT_HOME
  }

  if (path.match(/resources/)) {
    return LAYOUT_RESOURCES
  }

  if (path.match(/spotlights/)) {
    return LAYOUT_SPOTLIGHTS
  }

  return LAYOUT_REGULAR
}

let users = []
try {
  users = JSON.parse(fs.readFileSync("./users.json", "utf-8"))
  console.log("(◕◡◕✿) Users list loaded!")
} catch (e) {
  console.log("(◕‸ ◕✿) Users list not present, skipping user resolution...")
}

const validateResourceArticle = node => {
  const missingField = requiredArticleFrontmatter.find(
    required => node.frontmatter[required]
  )
  if (missingField) {
    console.error(
      `Article ${node.fileAbsolutePath} is missing field '${missingField}'`
    )
    process.exit(1)
  }
}

const createResources = async ({ createPage, graphql }) => {
  const resourcePage = path.resolve(`src/templates/resourcePage.tsx`)
  const resourceHome = path.resolve(`src/templates/resourceHome.tsx`)

  const languagesQuery = await graphql(
    `
      query FetchLanguages {
        allFile(filter: { sourceInstanceName: { eq: "languages" } }) {
          edges {
            node {
              relativePath
              relativeDirectory
              sourceInstanceName
            }
          }
        }
      }
    `
  )

  const topicsQuery = await graphql(
    `
      query FetchTopics {
        allFile(filter: { sourceInstanceName: { eq: "topics" } }) {
          edges {
            node {
              relativePath
              relativeDirectory
              sourceInstanceName
            }
          }
        }
      }
    `
  )

  const resources = [
    { key: "topics", query: topicsQuery },
    { key: "languages", query: languagesQuery },
  ]

  for ({ key, query } of resources) {
    if (query.errors) {
      return Promise.reject(query.errors)
    }

    const resources = query.data.allFile.edges.reduce((acc, { node }) => {
      const [resourceCategory] = node.relativePath.split("/")
      if (!acc.includes(resourceCategory)) {
        acc.push(resourceCategory)
      }
      return acc
    }, [])

    // create home page for each resources
    resources.forEach((resource) => {
      createPage({
        path: path.posix.join("resources", resource),
        component: resourceHome,
        context: {
          resourceType: key,
          entry: resource,
          layout: LAYOUT_RESOURCES,
        },
      })
    })

    query.data.allFile.edges.forEach(({ node }) => {
      createPage({
        path: path.posix.join("resources", node.relativePath),
        component: resourcePage,
        context: {
          file: node.relativePath,
          directory: node.relativeDirectory,
          layout: LAYOUT_RESOURCES,
        },
      })
    })
  }
}

const createSpotlights = async ({ createPage, graphql }) => {
  const spotlights = path.resolve(`src/templates/spotlight.tsx`)

  const result = await graphql(`
    query FetchSpotlights {
      allFile(filter: { sourceInstanceName: { eq: "spotlights" } }) {
        edges {
          node {
            relativePath
            sourceInstanceName
          }
        }
      }
    }
  `)

  if (result.errors) {
    return Promise.reject(result.errors)
  }

  return result.data.allFile.edges.forEach(({ node }) => {
    createPage({
      path: path.posix.join("spotlights", node.relativePath),
      component: spotlights,
      context: {
        file: node.relativePath,
        layout: LAYOUT_SPOTLIGHTS,
      },
    })
  })
}

exports.onCreateNode = async ({ node, getNode, actions }) => {
  const { createPage, createNodeField } = actions
  // TODO: find a better way to avoid handling non-resources
  // or better, attach authors to spotlights
  if (node.internal.type === "Mdx" && node.frontmatter.authors) {
    const { frontmatter } = node
    const isDoc = Boolean(!frontmatter.path)

    const githubLink = helper.findMarkdownLink(node.fileAbsolutePath)

    createNodeField({
      node,
      name: "githubLink",
      value: githubLink,
    })

    if (!isDoc) {
      return
    }

    const authors = helper.resolveAuthors(users, frontmatter.authors)

    createNodeField({
      node,
      name: "authors",
      value: authors,
    })
  }
}

exports.onCreatePage = async ({ page, actions }) => {
  const { createPage, deletePage } = actions

  if (page.path.match(/^\/resources\/404/)) {
    const oldPage = { ...page }
    page.matchPath = `/resources/*`
    deletePage(oldPage)
  } else if (page.path.match(/^\/spotlights\/404/)) {
    const oldPage = { ...page }
    page.matchPath = `/spotlights/*`
    deletePage(oldPage)
  }

  page.context.layout = resolveLayout(page.path)
  createPage(page)
}

exports.createPages = ({ actions, graphql }) => {
  const { createPage } = actions

  return Promise.all([
    createSpotlights({ createPage, graphql }),
    createResources({ createPage, graphql }),
  ])
}
