// This is a development script executed in the build step of pages
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const guides = require('../content/guides.json');
const roadmaps = require('../content/roadmaps.json');

const DOMAIN = 'https://roadmap.sh';
const PAGES_DIR = path.join(__dirname, '../pages');
const STORAGE_PATH = path.join(__dirname, '../content');
const SITEMAP_PATH = path.join(__dirname, '../public/sitemap.xml');

const PAGES_PATH = path.join(__dirname, '../pages');
const ROADMAPS_PATH = path.join(__dirname, '../content/roadmaps');
const GUIDES_PATH = path.join(__dirname, '../content/guides');

// Set the header
const xmlHeader = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">`;

// Wrap all pages in <urlset> tags
const xmlUrlWrapper = nodes => `${xmlHeader}
${nodes}
</urlset>`;

function getSlugPriority(pageSlug) {
  if (pageSlug === '/') {
    return '1.0';
  }

  const slugPriorities = [
    [
      '/roadmaps',
      '/guides',
      '/watch',
      '/podcasts'
    ], // 1.0
    ['/signup'], // 0.9
    ['/about'] // 0.8
  ];

  const foundIndex = slugPriorities.findIndex(
    routes => routes.some(route => pageSlug.startsWith(route))
  );

  if (foundIndex !== -1) {
    return parseFloat((10 - foundIndex) / 10)
      .toFixed(1);
  }

  return 0.5;
}

function getPageRoutes() {
  const files = glob.sync(`${PAGES_PATH}/**/*.tsx`, {
    ignore: [
      '**/_*.tsx',          // private non-page files e.g. _document.js
      '**/[[]*[]].tsx',     // Ignore dynamic pages i.e. `page/[something].js` files
      '**/[[]*[]]/*.tsx',   // Ignore files inside dynamic pages i.e. `[something]/abc.js`
      '**/components/*.tsx' // Ignore the component files
    ]
  });

  const pageRoutes = {};
  files.forEach(file => {
    const pageName = file.replace(PAGES_PATH, '').replace('.tsx', '');
    const pagePath = pageName.replace('/index', '') || '/';

    pageRoutes[pagePath] = { page: `${pageName}` };
  });

  return pageRoutes;
}

function generateNode(nodeProps) {
  const {
    slug,
    basePath,
    fileName,
    priority = null,
    date = null,
    frequency = 'monthly'
  } = nodeProps;

  const pagePath = path.join(basePath, fileName);
  let pageStats = {};
  try {
    pageStats = fs.lstatSync(pagePath);
  } catch (e) {
    console.log(`File not found: ${pagePath}`);
    pageStats = { mtime: (new Date()) };
  }

  return `<url>
              <loc>${DOMAIN}${slug}</loc>
              <changefreq>${frequency}</changefreq>
              <lastmod>${date || pageStats.mtime.toISOString()}</lastmod>
              <priority>${priority || getSlugPriority(slug)}</priority>
          </url>`;
}

function generateSiteMap() {
  const pageRoutes = getPageRoutes();
  const pageSlugs = Object.keys(pageRoutes)
    .filter(route => ![
      '/privacy',
      '/terms'
    ].includes(route));

  const pagesChunk = pageSlugs.map(pageSlug => {
    return generateNode({
      basePath: PAGES_DIR,
      fileName: `${pageRoutes[pageSlug].page}.tsx`,
      slug: pageSlug
    });
  });

  const guidesChunk = guides.map(guide => {
    return generateNode({
      basePath: GUIDES_PATH,
      fileName: `${guide.id}.md`,
      slug: `/guides/${guide.id}`,
      date: guide.updatedAt,
      priority: '1.0'
    });
  });

  const roadmapsChunk = roadmaps.map((roadmap, roadmapCounter) => {
    return generateNode({
      basePath: ROADMAPS_PATH,
      fileName: roadmap.metaPath.replace('/roadmaps', ''),
      slug: `/${roadmap.id}`,
      date: roadmap.updatedAt,
      priority: '1.0'
    });
  });

  const nodes = [
    ...roadmapsChunk,
    ...guidesChunk,
    ...pagesChunk
  ];

  const sitemap = `${xmlUrlWrapper(nodes.join('\n'))}`;

  fs.writeFileSync(SITEMAP_PATH, sitemap);

  console.log(`sitemap.xml with ${nodes.length} entries was written to ${SITEMAP_PATH}`);
}

generateSiteMap();