'use strict'

// Gulp helper functions
const { parallel, series, watch } = require('gulp')

// Custom helper functions
const createTask = require('./gulp.d/lib/create-task')
const exportTasks = require('./gulp.d/lib/export-tasks')
const log = require('fancy-log')

// Directories
const bundleName = 'ui'
const buildDir = 'build'
const previewSrcDir = 'preview-src'
const previewDestDir = 'public'
const previewResourcesDestDir = `${previewDestDir}/_`
const srcDir = 'src'

// Constants
const { reload: livereload } = process.env.LIVERELOAD === 'true' ? require('gulp-connect') : {}
const serverConfig = { host: '0.0.0.0', port: 5252, livereload }

// Import all tasks defined in gulp.d/tasks
// Each of these tasks is a higher-order function that
// another function used as a Gulp task
const task = require('./gulp.d/tasks')

// Define the glob patterns for the CSS and JavaScript source files
const glob = {
  all: [srcDir, previewSrcDir],
  css: [`${srcDir}/css/**/*.css`, `!${srcDir}/css/boostlook.css`],
  js: ['gulpfile.js', 'gulp.d/**/*.js', `${srcDir}/{helpers,js}/**/*.js`],
}

// Create a task to clean the build and public directories
const cleanTask = createTask({
  name: 'clean',
  desc: 'Clean files and folders generated by build',
  // Run the task defined in gulp.d/tasks/remove.js
  // to create a higher-order function that removes
  // the build and public directories
  call: task.remove(['build', 'public']),
})

// Create a task to lint the CSS and JavaScript source files
// This task checks if the source files follow the coding standards
const lintTask = createTask({
  name: 'lint',
  desc: 'Lint the CSS and JavaScript source files',
  call: parallel(
    // Lint the CSS source files
    createTask({
      name: 'lint:css',
      desc: 'Lint the CSS source files using stylelint (standard config)',
      call: task.lintCss(glob.css),
    }),
    // Lint the JavaScript source files
    createTask({
      name: 'lint:js',
      desc: 'Lint the JavaScript source files using eslint (JavaScript Standard Style)',
      call: task.lintJs(glob.js),
    })
  ),
})

// Create a task to format the CSS and JavaScript source files
// This task should be run before committing changes to the repository.
// Otherwise, the CI/CD pipeline will fail at the `gulp lint` step.
const formatTask = createTask({
  name: 'format',
  desc: 'Format the JavaScript source files using prettify (JavaScript Standard Style)',
  call: parallel(
    // Format the CSS source files
    createTask({
      name: 'format:css',
      desc: 'Format the CSS source files (standard config)',
      call: task.formatCss(glob.css),
    }),
    // Format the JavaScript source files
    createTask({
      name: 'format:js',
      desc: 'Format the JavaScript source files (JavaScript Standard Style)',
      call: task.formatJs(glob.js),
    })
  ),
})

// Create a task to build the UI assets
const buildTask = createTask({
  name: 'build',
  desc: 'Build and stage the UI assets for bundling',
  // Build the UI assets
  // Run the task defined in gulp.d/tasks/build.js
  call: task.build(
    srcDir,
    previewResourcesDestDir,
    process.argv.slice(2).some((name) => name.startsWith('preview'))
  ),
})

// Create a task to build the UI assets and bundle them
const bundleBuildTask = createTask({
  name: 'bundle:build',
  call: series(
    // Clean the build and public directories
    cleanTask,
    // Lint the CSS and JavaScript source files
    lintTask,
    // Format the CSS and JavaScript source files
    buildTask
  ),
})

// Create a task to pack the UI assets
const bundlePackTask = createTask({
  name: 'bundle:pack',
  desc: 'Create a bundle of the staged UI assets for publishing',
  // Pack the UI assets into a zip file
  // Run the task defined in gulp.d/tasks/pack.js
  call: task.pack(
    previewResourcesDestDir,
    buildDir,
    bundleName,
    (bundlePath) => !process.env.CI && log(`Antora option: --ui-bundle-url=${bundlePath}`)
  ),
})

// Create a task to bundle the UI assets
const bundleTask = createTask({
  name: 'bundle',
  desc: 'Clean, lint, build, and bundle the UI for publishing',
  call: series(
    // Build the UI assets
    bundleBuildTask,
    // Pack the UI assets into a zip file
    bundlePackTask
  ),
})

// Create a task to pack the UI assets
// This is implemented as an alias for the bundle task
// The `pack` is deprecated; use the bundle task instead
const packTask = createTask({
  name: 'pack',
  desc: '(deprecated; use bundle instead)',
  call: series(bundleTask),
})

// Create a task to build the preview site
const previewBuildTask = createTask({
  name: 'preview:build',
  desc: 'Process and stage the UI assets and generate pages for the preview',
  call: parallel(
    // Build the UI assets
    buildTask,
    // Generate the preview pages
    createTask({
      name: 'preview:build-pages',
      // Process and stage the UI assets and generate pages for the preview
      // Run the task defined in gulp.d/tasks/build-preview-pages.js
      call: task.buildPreviewPages(srcDir, previewSrcDir, previewDestDir, livereload),
    })
  ),
})

// Create a task to build and preview the site
const previewTask = createTask({
  name: 'preview',
  desc: 'Generate a preview site and launch a server to view it',
  call: series(
    // Lint the CSS and JavaScript source files
    lintTask,
    // Build the preview site
    previewBuildTask,
    // Serve the preview site
    createTask({
      name: 'preview:serve',
      // Run the task defined in gulp.d/tasks/serve.js
      call: task.serve(previewDestDir, serverConfig, () => watch(glob.all, previewBuildTask)),
    })
  ),
})

module.exports = exportTasks(
  bundleTask,
  cleanTask,
  lintTask,
  formatTask,
  buildTask,
  bundleTask,
  bundlePackTask,
  previewTask,
  previewBuildTask,
  packTask
)
