# frozen_string_literal: true

require 'fileutils'
require 'yaml'

class Book
  @@all_books = {
    "az" => "progit2-aze/progit2",
    "be" => "progit/progit2-be",
    "bg" => "progit/progit2-bg",
    "cs" => "progit-cs/progit2-cs",
    "de" => "progit/progit2-de",
    "en" => "progit/progit2",
    "es" => "progit/progit2-es",
    "fr" => "progit/progit2-fr",
    "gr" => "progit2-gr/progit2",
    "id" => "progit/progit2-id",
    "it" => "progit/progit2-it",
    "ja" => "progit/progit2-ja",
    "ko" => "progit/progit2-ko",
    "mk" => "progit2-mk/progit2",
    "ms" => "progit2-ms/progit2",
    "nl" => "progit/progit2-nl",
    "pl" => "progit2-pl/progit2-pl",
    "pt-br" => "progit/progit2-pt-br",
    "pt-pt" => "progit2-pt-pt/progit2",
    "ru" => "progit/progit2-ru",
    "sl" => "progit/progit2-sl",
    "sr" => "progit/progit2-sr",
    "tl" => "progit2-tl/progit2",
    "tr" => "progit/progit2-tr",
    "sv" => "progit2-sv/progit2",
    "uk" => "progit/progit2-uk",
    "uz" => "progit/progit2-uz",
    "zh" => "progit/progit2-zh",
    "zh-tw" => "progit/progit2-zh-tw",
    "fa" => "progit/progit2-fa"
  }

  def self.all_books
    @@all_books
  end

  attr_accessor :chapters
  attr_accessor :xrefs
  attr_accessor :ebook_pdf
  attr_accessor :ebook_epub
  attr_accessor :ebook_mobi
  attr_accessor :sha

  def initialize(edition, language_code)
    @edition = edition
    @language_code = language_code
    @chapters = []
    @xrefs = {}
  end

  def front_matter
    front_matter = {
      "category" => "book",
      "section" => "learn",
      "subsection" => "book",
      "sidebar" => "book",
      "book" => {
        "language_code" => @language_code
      }
    }
  end

  def content_note
    "### DO NOT EDIT! Generated by script/update-book2.rb"
  end

  def wrap_front_matter(front_matter)
    "#{front_matter.to_yaml.sub("---\n", "---\n#{self.content_note}\n")}---\n"
  end

  def absolute_path(path, top_level = "content")
    File.absolute_path(File.join(File.dirname(__FILE__), "..", "external", "book", top_level, "book", @language_code, "v#{@edition}", path))
  end

  def relative_url(path)
    return "book/#{@language_code}/v#{@edition}#{path.nil? || path.empty? || path == "." ? "" : "/#{path}"}"
  end

  def fixImagePath(path)
    if path == "images/tagapangasiwa.png"
      # In https://github.com/progit2-tl/progit2/pull/45 the
      # reference was changed, but the file was not renamed
      "images/collaborators.png"
    else
      path
    end
  end

  def removeAllFiles
    FileUtils.rm_rf(absolute_path("."))
  end

  def save
    chapters = []
    @chapters.each do |chapter|
      next if chapter.nil?
      sections = []
      chapter.sections.each do |section|
        next if section.nil?
        sections.append({
          "cs_number" => section.cs_number,
          "title" => section.title,
          "url" => section.relative_url(nil).gsub(/%3F/, '?')
        })
      end
      chapters.append({
        "cs_number" => chapter.cs_number,
        "title" => chapter.title,
        "sections" => sections
      })
    end
    data = {
      "language_code" => @language_code,
      "repository_url" => "https://github.com/#{@@all_books[@language_code]}",
      "chapters" => chapters
    }
    path = File.join(File.dirname(__FILE__), "..", "external", "book", "data", "book", "#{@language_code}.yml")
    FileUtils.mkdir_p(File.dirname(path))
    File.open(path, 'w') do |file|
      file.write("#{self.content_note}\n")
      file.write(data.to_yaml.strip)
    end

    front_matter = self.front_matter
    front_matter["page_title"] = "Git - Book"
    front_matter["url"] = "/book/#{@language_code}/v#{@edition}.html"
    front_matter["aliases"] = [
      "/book/#{@language_code}/v#{@edition}/index.html",
      "/book/#{@language_code}/v1/index.html",
      "/book/#{@language_code}/v1.html",
      "/book/#{@language_code}/index.html",
      "/book/#{@language_code}.html"
    ]
    if @language_code == "en"
      front_matter["aliases"].push("/book/index.html")
      front_matter["aliases"].push("/book.html")
      front_matter["aliases"].push("/book/v1/index.html")
      front_matter["aliases"].push("/book/v1.html")
    end
    front_matter["book"]["front_page"] = true
    front_matter["book"]["repository_url"] = "https://github.com/#{@@all_books[@language_code]}"
    front_matter["book"]["sha"] = self.sha
    if self.ebook_pdf
      front_matter["book"]["ebook_pdf"] = self.ebook_pdf
    end
    if self.ebook_epub
      front_matter["book"]["ebook_epub"] = self.ebook_epub
    end
    if self.ebook_mobi
      front_matter["book"]["ebook_mobi"] = self.ebook_mobi
    end

    path = self.absolute_path("_index.html")
    FileUtils.mkdir_p(File.dirname(path))
    File.open(path, 'w') do |file|
      file.write(self.wrap_front_matter(front_matter))
    end

    front_matter = { "redirect_to" => "book/#{@language_code}/v#{@edition}" }
    File.write(self.absolute_path("../_index.html"), self.wrap_front_matter(front_matter))
    FileUtils.mkdir_p(self.absolute_path("../v1"))
    File.write(self.absolute_path("../v1/_index.html"), self.wrap_front_matter(front_matter))

    if @language_code == "en"
      File.write(self.absolute_path("../../_index.html"), self.wrap_front_matter(front_matter))
      FileUtils.mkdir_p(self.absolute_path("../../v1"))
      File.write(self.absolute_path("../../v1/_index.html"), self.wrap_front_matter(front_matter))
    end

    FileUtils.mkdir_p(self.absolute_path("ch00"))
    @xrefs.each do |id_xref, section|
      path = self.absolute_path("ch00/#{id_xref}.html")
      if section == 'redirect-to-en'
	if id_xref == 'ch01-introduction'
	  id_xref = 'ch01-getting-started'
        elsif id_xref == 'ch02-git-basics' || id_xref == '_bab_dasar-dasar_git'
	  id_xref = 'ch02-git-basics-chapter'
	elsif id_xref == '_percabangan_git'
	  id_xref = 'ch03-git-branching'
	elsif id_xref == 'r_git_on_the_server'
	  id_xref = 'ch04-git-on-the-server'
	elsif id_xref == '_getting_notes' || id_xref == '_sharing_notes'
	  # Was removed in e2af0d7b (Remove dead notes content, 2014-11-09),
	  # fall back to `git fetch`
	  id_xref = '_git_fetch'
	elsif id_xref == 'r_undoing' || id_xref == '_mengembalikan_ke_sebelumnya'
	  id_xref = '_undoing'
	end
	if id_xref == '_git_notes'
	  url = "docs/git-notes"
	else
          url = "book/en/v2/ch00/#{id_xref}"
	end
      else
        url = "#{section.relative_url(nil)}##{id_xref}"
      end
      front_matter = { "redirect_to" => url }
      File.open(path, 'w') do |file|
        file.write(self.wrap_front_matter(front_matter))
      end
    end
  end

  def book_v1_aliases(cs_number)
    if @book_v1_aliases.nil?
      path = File.absolute_path(File.join(File.dirname(__FILE__), "..", "data", "book_v1.yml"))
      if File.exist?(path)
        @book_v1_aliases = YAML.load_file(path)&.[](@language_code)
      end
      @book_v1_aliases = {} if @book_v1_aliases.nil?
    end
    return @book_v1_aliases[cs_number]&.flat_map { |title|
      ["/book/#{@language_code}/#{title}.html", "/book/#{@language_code}/v1/#{title}.html"]
    }
  end
end

class Chapter
  def initialize(book)
    @book = book
    @sections = []
    @previous_chapter = @book.chapters[-1]
    if not @previous_chapter.nil?
      @previous_chapter.next_chapter = self
    end
  end

  def cs_number
    "#{self.chapter_type == "appendix" ? "A" : ""}#{self.chapter_number}"
  end

  def front_matter
    front_matter = @book.front_matter
    front_matter["book"]["chapter"] = {
      "title" => self.title,
      "number" => self.chapter_number
    }
    return front_matter
  end

  def wrap_front_matter(front_matter)
    @book.wrap_front_matter(front_matter)
  end

  attr_accessor :title
  attr_accessor :chapter_type
  attr_accessor :chapter_number
  attr_accessor :sha
  attr_accessor :sections
  attr_accessor :book

  def next_chapter=(chapter)
    @next_chapter = chapter
  end

  def absolute_path(path)
    return @book.absolute_path(path)
  end

  def relative_url(path)
    return @book.relative_url(path)
  end

  def previous_chapter
    return @previous_chapter
  end

  def next_chapter
    return @next_chapter
  end

  def save
    # TODO
  end

  def book_v1_aliases(cs_number)
    return @book.book_v1_aliases(cs_number)
  end
end

class Section
  def initialize(chapter, section_number)
    @chapter = chapter
    @section_number = section_number
    @previous_section = @chapter.sections[-1]
    if @previous_section.nil?
      previous_chapter = chapter.previous_chapter
      if not previous_chapter.nil?
        @previous_section = previous_chapter.sections[-1]
      end
    end
    if not @previous_section.nil?
      @previous_section.next_section = self
    end
  end

  def cs_number
    "#{@chapter.cs_number}.#{@section_number}"
  end

  def front_matter
    front_matter = @chapter.front_matter
    front_matter["title"] = "Git - #{self.title}"
    front_matter["book"]["section"] = {
      "title" => self.title,
      "number" => @section_number,
      "cs_number" => self.cs_number,
      "previous" => self.previous_section_url,
      "next" => self.next_section_url
    }
    if @slug =~ /:|[^-A-Za-z0-9_]/
      relative_url = self.relative_url(@slug)
      front_matter["url"] = "/#{relative_url.gsub(/%3F/, '?')}.html"
      if relative_url =~ /%3F/
        front_matter["aliases"] = [
	  "/#{relative_url.gsub(/%3F.*/, '')}.html"
	]
      end
    end
    v1_aliases = @chapter.book_v1_aliases(self.cs_number)
    unless v1_aliases.nil?
      front_matter["aliases"] = [] if front_matter["aliases"].nil?
      front_matter["aliases"] += v1_aliases
    end
    return front_matter
  end

  attr_accessor :title
  attr_accessor :html
  attr_accessor :slug

  def next_section=(section)
    @next_section = section
  end

  def slug
    return @slug if not @slug.nil?
    if self.title.empty?
      title = @chapter.title
    else
      title = (@chapter.title + "-" + self.title)
    end
    @slug = title.gsub(/\(|\)|\./, "").gsub(/\s+/, "-").gsub("&#39;", "-")
  end

  def absolute_path(path)
    return @chapter.absolute_path(path)
  end

  def relative_url(path)
    if path.nil? || path.empty?
      path = self.slug
    end
    return @chapter.relative_url(path.gsub(/\?/, '%3F'))
  end

  def previous_section_url
    if @previous_section.nil?
      return self.relative_url(nil)
    end
    return self.relative_url(@previous_section.slug)
  end

  def next_section_url
    if @next_section.nil?
      return self.relative_url(nil)
    end
    return self.relative_url(@next_section.slug)
  end

  def save
    return if self.slug.nil?

    path = self.absolute_path(self.slug.gsub(/[:?]/, ''))
    FileUtils.mkdir_p(File.dirname(path))
    File.open("#{path}.html", 'w') do |file|
      file.write(@chapter.wrap_front_matter(self.front_matter))
      file.write(self.html.strip)
    end
  end

  def saveImage(path, content)
    path = @chapter.book.absolute_path(path, "static")
    FileUtils.mkdir_p(File.dirname(path))
    File.open(path, 'w') do |file|
      file.write(content)
    end
  end
end
