#!/usr/pkg/bin/ruby32

#
# Motyl 1.0.3
# Copyright (c) 2016-2022, Frederic Cambus
# https://github.com/fcambus/motyl
#
# Created: 2016-02-16
# Last Updated: 2022-07-28
#
# Motyl is released under the BSD 2-Clause license.
# See LICENSE file for details.
#
# SPDX-License-Identifier: BSD-2-Clause
#

require 'date'
require 'fileutils'
require 'kramdown'
require 'mustache'
require 'yaml'

# Enforce UTF-8 character encoding
Encoding.default_internal = Encoding::UTF_8
Encoding.default_external = Encoding::UTF_8

# Load and process Markdown file
def markdown(path)
  Kramdown::Document.new(
    File.read(path),
    smart_quotes: %w[apos apos quot quot],
    syntax_highlighter: 'rouge'
  ).to_html
end

# Display status message
def status(message)
  puts('[' + Time.now.strftime('%X') + '] ' + message)
end

# Loading configuration
data = {
  'version' => 'Motyl 1.0.3',
  'updated' => Time.now.strftime('%Y-%m-%dT%XZ'),
  'site' => YAML.load_file('motyl.conf'),
  'posts' => [],
  'categories' => {}
}

theme = 'themes/' + data['site']['theme'] + '/'

# Loading templates
templates = {
  'categories' => File.read(theme + 'templates/categories.mustache'),
  'atom' => File.read(theme + 'templates/atom.mustache'),
  'pages' => File.read(theme + 'templates/page.mustache'),
  'posts' => File.read(theme + 'templates/post.mustache')
}

Mustache.template_path = theme + 'templates/'

def render(directory, templates, data)
  Dir.foreach(directory) do |file|
    next if ['.', '..'].include?(file)

    extension = File.extname(file)

    if extension == '.md'
      basename = File.basename(file, extension)
      data['page'] = YAML.load_file(directory + '/' + basename + '.yaml')
      data['page']['content'] = Mustache.render(
        markdown(directory + '/' + file),
        data
      )
      data['page']['url'] ||= basename + '/'

      status('Rendering ' + data['page']['url'])

      if directory == 'posts'
        data['page']['datetime'] =
          DateTime.parse(data['page']['date']).strftime('%Y-%m-%dT%XZ')

        data['posts'].push(data['page'])

        data['page']['categoryDisplay'] = []

        # Populate category table
        data['page']['categories'].each do |category|
          data['categories'][category] ||= []
          data['categories'][category].push(data['page'])
          data['page']['categoryDisplay'].push(
            'category' => category,
            'url' => data['site']['categoryMap'][category]
          )
        end
      end

      FileUtils.mkdir_p('public/' + data['page']['url'])
      File.write('public/' + data['page']['url'] + 'index.html',
                 Mustache.render(templates[directory], data))

      data['page'] = {}
    end
  end
end

# Render posts
FileUtils.rm_rf('public')
render('posts', templates, data)

# Sort post archives
data['posts'].sort! { |a, b| b['date'] <=> a['date'] }

# Renger pages
render('pages', templates, data)

# Feed
data['feed'] = data['posts'][0..29]

File.write('public/atom.xml', Mustache.render(templates['atom'], data))
status('Rendering atom.xml')
data['page'] = {}

# Categories
data['categories'].keys.each do |category|
  category_url = data['site']['categoryMap'][category] + '/'

  data['categories'][category].sort! { |a, b| b['date'] <=> a['date'] }
  data['page']['title'] = category
  data['page']['url'] = 'categories/' + category_url
  data['posts'] = data['categories'][category]

  FileUtils.mkdir_p('public/categories/' + category_url)
  File.write('public/categories/' + category_url + 'index.html',
             Mustache.render(templates['categories'], data))
  status('Rendering ' + category_url)
end

# Copy static assets
status('Copying assets and static files')
FileUtils.cp_r(Dir.glob(theme + 'assets/*'), 'public')
FileUtils.cp_r(Dir.glob('assets/*'), 'public')
