#!/usr/bin/env ruby
# encoding: UTF-8
# coding: UTF-8

# Instalación:
#   sudo wget https://gitlab.com/snippets/2189719/raw /usr/local/bin && sudo mv /usr/local/bin/raw /usr/local/bin/export-pdf-li && sudo chmod +755 /usr/local/bin/export-pdf-li

require 'fileutils'

# Variables

$file     = ''
$title    = ''
$author   = ''
$press    = ''
$date     = ''
$year     = Time.now.year.to_s
$ragged   = false
$default  = true
$just_tex = false
$leave_h1 = false
$numbered = false
$en_date  = false
$no_day   = false
$bib      = false
$script   = __FILE__.gsub(/.*?\//, '')
$tmp_dir  = "tmp_#{$script}"
$tem_name = "template_#{$script}.tex"

# Plantillas

# Plantilla por defecto
$template =  <<-HEREDOC
% Universal settings
\\documentclass[11pt,extrafontsizes,openany]{book}
\\usepackage[utf8]{inputenc}
\\usepackage[T1]{fontenc}
\\usepackage[spanish,es-noindentfirst]{babel}
\\usepackage[osf]{Alegreya}

% PACKAGE DEFINITION
% Typographical packages
\\usepackage{microtype} % for micro-typographical adjustments
\\usepackage{setspace} % for line spacing
\\usepackage{lettrine} % for drop caps and awesome chapter beginnings
\\usepackage[md]{titlesec} % for manipulation of chapter titles
\\usepackage{enumitem} % for lists
\\usepackage{geometry} % page size
\\usepackage{fancyhdr} % headers and footers
\\usepackage{tocloft} % toc
\\usepackage[font=small,labelformat=empty]{caption} % captions
\\usepackage{chngcntr} % change numnering behavior
\\usepackage{csquotes} % change quoting behavior
\\usepackage{emptypage}
\\usepackage{calc}
\\usepackage{hologo}
\\usepackage[pdfencoding=auto,hidelinks]{hyperref}
\\usepackage{ragged2e}
\\usepackage{graphicx}

% Bibliography
\\usepackage[style=apa,backend=biber]{biblatex} % for bibliography
@bibliography

% Meta
\\newcommand{\\mytitle}{\\emph{@title}}
\\newcommand{\\myauthor}{@author}
\\newcommand{\\press}{@press}
\\newcommand{\\printyear}{@year}
\\newcommand{\\printdate}{@date}

\\if\\myauthor\\empty
  \\newcommand{\\myauthor}{@title}
\\fi

% Page size
\\geometry{
	paperwidth=5.5in,
	paperheight=8.5in,
	inner=1in,
	outer=1in
}

% TOC
\\addto\\captionsspanish{
  \\renewcommand{\\contentsname}{\\textsc{Índice general}}
}
\\renewcommand{\\cfttoctitlefont}{\\normalfont\\Large}
\\renewcommand{\\cftpartfont}{\\normalfont}
\\renewcommand{\\cftpartpagefont}{\\normalfont}
\\renewcommand{\\cftchapfont}{\\vspace{-1em}\\footnotesize\\normalfont}
\\renewcommand{\\cftchappagefont}{\\normalfont}

% Defining the title and the author
\\title{\\mytitle}
\\author{\\myauthor}
\\date{@year}

% Custom second title page
\\makeatletter
\\newcommand*\\halftitlepage{\\begingroup % Misericords, T&H p 153
	\\setlength\\drop{0.1\\textheight}
	\\begin{center}
		\\vspace*{\\drop}
		\\rule{\\textwidth}{0in}\\par
		{\\large\\textsc\\thetitle\\par}
		\\rule{\\textwidth}{0in}\\par
		{\\textsc\\theauthor\\par}
		\\vfill
	\\end{center}
	\\endgroup}
\\makeatother

% Part title display
\\makeatletter
\\renewcommand\\part{%
	\\if@openright
	\\cleardoublepage
	\\else
	\\clearpage
	\\fi
	\\thispagestyle{empty}
	\\if@twocolumn
	\\onecolumn
	\\@tempswatrue
	\\else
	\\@tempswafalse
	\\fi
	\\null\\vfil
	\\secdef\\@part\\@spart}
\\makeatother

\\titleformat
{\\part}
[display]
{\\normalfont\\scshape\\Large}
{\\Huge\\thepart\\centering}
{0pt}
{\\centering}[]

% Reset chapter number in each part
\\counterwithin*{chapter}{part}

% Chapter title display
\\titleformat
{\\chapter}
[display]
{\\normalfont\\scshape\\Large}
{\\Huge\\thechapter\\centering}
{0pt}
{\\centering}[]

% Quotation
\\renewenvironment{quote}
{\\small\\list{}{
  \\listparindent=1.5em
  \\leftmargin=.5cm
  \\rightmargin=0cm
  \\parsep=0cm}%
 \\item\\relax}
{\\endlist}

% Typographical settings for the body text
\\setlength{\\parskip}{0em}
\\linespread{1.09}

% Modify spaces between headers
\\titlespacing*{\\chapter}
{0pt}{2em}{1em}
\\titlespacing*{\\section}
{0pt}{1em}{1em}

% HEADER AND FOOTER MANIPULATION
\\renewcommand{\\headrulewidth}{0.0pt}
\\renewcommand{\\footrulewidth}{0.0pt}

\\setlength{\\RaggedRightParindent}{\\parindent}

%  THE DOCUMENT
\\begin{document}

% Preliminares
@ragged
\\frontmatter
\\pagestyle{empty}
\\maketitle

% Legal
\\begin{center}
	\\footnotesize
	\\vspace*{\\fill}

	\\mytitle \\\\ \\myauthor

  \\if\\press\\empty
  \\else
  	\\vskip 1em
  	Edición: \\press
  \\fi

	\\vskip 1em
  Última edición: \\printdate

	\\vskip 1em
	Permitida su reproducción y difusión por cualquier \\\\
  medio mecánico o electrónico sin la autorización \\\\
  escrita del titular de los derechos.

	\\vskip 1em
	Hecho en México / \\emph{Made in Mexico}

	\\normalsize
\\end{center}

% Principal
\\mainmatter
\\newgeometry{
	inner=.75in,
	outer=1.25in
}

\\include{@file}

% Finales
\\backmatter
@printbibliography

% Índice
% Descomentar las siguientes líneas si se quiere índice
%\\pagestyle{fancy}
%\\fancyhead{}
%\\fancyhead[CO]{\\footnotesize\\textsc{Índice general}\\normalsize}
%\\fancyhead[CE]{\\footnotesize\\textsc{\\myauthor}\\normalsize}
%\\begin{center}
%	\\tableofcontents
%\\end{center}
%\\tocloftpagestyle{empty}

% Descomentar para enviar colofón a una página par
%\\cleardoublepage\\pagestyle{empty}\\mbox{} % +2 páginas blancas
%\\clearpage\\pagestyle{empty}\\mbox{} % +1 página blanca

% Colofón
\\newgeometry{
	inner=1.5in,
	outer=1.5in
}
\\pagestyle{empty}
\\vspace*{\\fill}
\\begin{center}
	\\mytitle \\hspace{.1em} se terminó de componer
	el \\printdate. Documento hecho con
	\\fontfamily{cmr}\\LaTeX.
\\end{center}

\\end{document}
% END THE DOCUMENT
HEREDOC

# Cabeza del documento
$header = <<-HEREDOC
\\chapter*{@title}
\\addcontentsline{toc}{chapter}{@tex_chapter}

\\pagestyle{fancy}
\\fancyhead{}
\\fancyhead[CO]{\\footnotesize\\textsc{@title}\\normalsize}
\\fancyhead[CE]{\\footnotesize\\textsc{\\myauthor}\\normalsize}

\\vskip 3em

HEREDOC

# Definiciones

# Obtiene el mes
def get_month m
  if m == 1
    return 'enero'
  elsif m == 2
    return 'febrero'
  elsif m == 3
    return 'marzo'
  elsif m == 4
    return 'abril'
  elsif m == 5
    return 'mayo'
  elsif m == 6
    return 'junio'
  elsif m == 7
    return 'julio'
  elsif m == 8
    return 'agosto'
  elsif m == 9
    return 'septiembre'
  elsif m == 10
    return 'octubre'
  elsif m == 11
    return 'noviembre'
  elsif m == 12
    return 'diciembre'
  end
end

# Incorpora modificaciones a los párrafos
def get_classes txt
  clean   = txt.gsub(/((.|\n)*?)\\{\s*(\.(.|\n)*?)\\}((.|\n)*$)/, '\1').strip
  rest    = txt.gsub(/((.|\n)*?)\\{\s*(\.(.|\n)*?)\\}((.|\n)*$)/, '\5').strip
  classes = txt.gsub(/((.|\n)*?)\\{\s*(\.(.|\n)*?)\\}((.|\n)*$)/, '\3').split(/\s+/)
  avoid   = false

  # Evita falsos positivos
  classes.each do |c|
    if c !~ /^\./ || c =~ /\s/
      avoid = true
    end
  end
  
  if !avoid
    # Eliminación de sangrados
    classes.each do |c|
      if c =~ /\.sin-sangria/
        clean = "\\noindent " + clean
      end
    end

    # Alineaciones
    classes.each do |c|
  	  if c == '.derecha' || c == '.izquierda' || c == '.centrado'
  	    if    c == '.derecha'
  	      align = "flushright"
  	    elsif c == '.izquierda'
  	      align = "flushleft"
  	    elsif c == '.centrado'
  	      align = "center"
  	    end

        clean = "\\begin{" + align + "}\n" + clean + "\n\\end{" + align + "}"
      elsif c == ".frances"
        clean = "\\hangindent=\\parindent\n\\hangafter=1\n\\noindent " + clean
      end

      # Reacomoda los bloques de cita
      if clean =~ /\\begin{quote}/
        clean = "\\begin{quote}\n" + clean.gsub(/\\begin{quote}\s*/, '')
      end
      if clean =~ /\\end{quote}/
        clean = clean.gsub(/\s*\\end{quote}/, '') + "\n\\end{quote}"
      end
    end

    # Espacios verticales
    classes.each do |c|
  	  if c =~ /\.espacio-arriba\d+/
  	    num   = c.gsub(/.*?(\d+)/, '\1').to_i
  	    vskip = "\\vskip " + num.to_s + "em\n"

  	    clean = vskip + clean
  	  end
    end

    clean = clean + rest
  end

  return clean
end

# Modifica tildes y esas cosas para la tabla de contenidos
def tex_transliterate s
  chars   = s.split('')
  change  = []
  bib     = [
    ['á', "\\\\'{a}"],['é', "\\\\'{e}"],['í', "\\\\'{i}"],
    ['ó', "\\\\'{o}"],['ú', "\\\\'{u}"],['ü', "\\\\\"{u}"],
    ['ñ', "\\\\~{n}"],['Á', "\\\\'{A}"],['É', "\\\\'{E}"],
    ['Í', "\\\\'{I}"],['Ó', "\\\\'{O}"],['Ú', "\\\\'{U}"],
    ['Ü', "\\\\\"{U}"],['Ñ', "\\\\~{N}"]
  ]

  chars.each do |c|
    bib.each do |x|
      if c == x.first
        c = x.last
      end
    end

    change.push(c)
  end

  return change.join('')
end

# Genera la estructura para los gráficos
def generate_graphics s
  p = $just_tex ? '' : '../'
  return "\\bigskip\\noindent\\includegraphics[width=\\textwidth,keepaspectratio]{" +
         p + s +
         "}\\bigskip"
end

# Genera la plantilla por defecto
def print_template
  file = File.open('template.tex', 'w:utf-8')
  file.puts $template
  file.close
  puts "Archivo de la plantilla guardado en <#{Dir.pwd}/template.tex>."
  abort
end

begin
  ARGV.each do |arg|
    if arg =~ /^-h$/ || arg =~ /^--help$/
      puts "#{$script} genera un documento PDF con modificaciones hechas a Pandoc."
      puts "\nUso:"
      puts "  #{$script} [argumentos] [archivo]"
      puts "\nArgumentos:"
      puts "  --title=\"text\"      Título del texto"
      puts "  --author=\"text\"     Autor del texto"
      puts "  --press=\"text\"      Editorial del texto"
      puts "  --template=\"path\"   Plantilla para el documento"
      puts "  --bib=\"path\"        Bibliografía para el documento"
      puts "  --ragged-right      Justificación en bandera"
      puts "  --just-tex          Solo genera los archivos TeX"
      puts "  --leave-h1          Respeta los h1 del documento"
      puts "  --numbered          Numeración en partes y capítulos"
      puts "  --get-template      Genera la plantilla por defecto"
      puts "  --en-date           Genera fechas en formato inglosajón"
      puts "  --no-day            No incluye el día en la fecha"
      puts "  -h | --help         Muestra esta ayuda"
      puts "\nEjemplos:"
      puts "  #{$script} archivo.md"
      puts "  #{$script} --template=../platila.tex archivo.html"
      puts "  #{$script} --template=../platila.tex --ragged-right archivo.xhml"
      puts "\nFormatos de archivos aceptados: MD, HTML o XHTML. Por defecto solo deja un h1 con el título del documento"
      abort
    end

    # Cambia la cantidad de caracteres por línea de texto y detecta si se aplicará a todos los bloques
    if arg =~ /--template/
      $template = File.absolute_path(arg.gsub(/--\w+="*([^"]*?)"*/,'\1'))
      $default  = false
    elsif arg =~ /--title/
      $title    = arg.gsub(/--\w+="*([^"]*?)"*/,'\1')
    elsif arg =~ /--author/
      $author   = arg.gsub(/--\w+="*([^"]*?)"*/,'\1')
    elsif arg =~ /--press/
      $press    = arg.gsub(/--\w+="*([^"]*?)"*/,'\1')
    elsif arg =~ /--bib/
      $bib      = arg.gsub(/--\w+="*([^"]*?)"*/,'\1')
    elsif arg =~ /--ragged-right/
      $ragged   = true
    elsif arg =~ /--just-tex/
      $just_tex = true
    elsif arg =~ /--leave-h1/
      $leave_h1 = true
    elsif arg =~ /--numbered/
      $numbered = true
    elsif arg =~ /--en-date/
      $en_date  = true
    elsif arg =~ /--no-day/
      $no_day   = true
    elsif arg =~ /--get-template/
      print_template
    end
  end

  $file = ARGV.last

  # Comprueba el archivo
  if !File.file?($file) ||
     !(File.extname($file) == '.md' ||
       File.extname($file) == '.html' ||
       File.extname($file) == '.xhtml')
    raise
  else
    $file = File.absolute_path($file)
  end

  # Obtiene la fecha
  if $en_date
  	if $no_day
  	  $date = Time.now.strftime("%B, %Y")
  	else
      $date = Time.now.strftime("%B %d, %Y")
        	      .gsub(/0(\d,)/, '\1')
    end
  else
  	if !$no_day
  	  $date = Time.now.day.to_s + ' de '
  	end

    $date += get_month(Time.now.month) + ' del ' +
	           Time.now.year.to_s
  end

  # Produce una carpeta temporal
  Dir.mkdir($tmp_dir)
  Dir.chdir($tmp_dir)
  
  # Modifica la etiqueta para los saltos de línea
  md = File.read($file)
           .gsub(/\s*\\\n\s*/, ' @line-break ')
  tmp = File.open(File.basename($file), 'w:utf-8')
  tmp.puts md
  tmp.close

  # Convierte el archivo a .tex
  system("pandoc #{File.basename($file)} -o #{File.basename($file, '.*')}.tex")

  # Obtiene el texto procesado por pc-pandog
  raw = File.read(File.basename($file, '.*') + '.tex')

  # Obtiene el título limpio
  regex = /^(.|\n)*?\\section{((.|\n)*?)}\\label(.|\n)*$/
  if $title == ''
    $title = raw.gsub(regex, '\2')
                .gsub(/\n/, ' ')
                .gsub(/\\texorpdfstring{(.*?)}{.*}/, '\1')
  end

  title = $header.gsub('@title', $title)
                 .gsub('@tex_chapter', tex_transliterate($title))

  # Limpia cosillas
  clean = raw.gsub('@line-break', '\\\\\\')
             .gsub(/\+\+\+((.|\n)*?)\+\+\+/,){|e| e.downcase }
             .gsub(/\+\+\+((.|\n)*?)\+\+\+/, '\\textsc{' + '\1' + '}')
             .gsub(/\\hypertarget{.*?%/, '')
             .gsub(/\\label{.*?}}/, '')
             .gsub('subsection', 'subsection*')
             .gsub("\\tightlist\n", '')
             .gsub("\\def\\labelenumi{\\arabic{enumi}.}\n", '')
             .gsub('begin{itemize}', 'begin{itemize}[noitemsep]')
             .gsub('begin{enumerate}', 'begin{enumerate}[noitemsep]')
             .gsub(/\\includegraphics{(.*?)}/, generate_graphics('\1'))
             .gsub('LaTeX', '\\LaTeX')
             .gsub('TeX', '\\teX')
             .gsub("\n\n\n", "\n\n")
             .gsub('{[}', '[')
             .gsub('{]}', ']')
             .gsub(/\\end{quote}\s*\\begin{quote}/, '')
             .gsub(/@textcite\s+\[([^\[]+?)\]/, '\\textcite{' + '\1' + '}')
             .gsub(/@parencite\s+\[([^\[]+?)\]/, '\\parencite{' + '\1' + '}')
             .gsub(/\\texorpdfstring{((.|\n)*?)}{.*}/,) do |e|
               e.gsub(/\\texorpdfstring{((.|\n)*?)}{.*}/, '\1}')
                .gsub(/\n/, ' ')
              end

  # Limpieza específica del español
  if !$en_date
    clean = clean.gsub('---', '"+--')
  end

  # Da formato a los títulos
  if !$leave_h1
    clean = clean.gsub(/\\section{((.|\n)*?)}\s*\n/, '')
                 .gsub(/\n{3,}/, "\n\n")
    clean = title + "\n" + clean.strip
  else
    clean = clean.gsub(/\\section{((.|\n)*?)}\s*\n/,) do |e|
  	  if e =~ /@part/
        n = $numbered ? '' : '*'
	      e.gsub(/\s*@part/, '').gsub(/section{/, 'part' + n + '{')
	    else
        $header
          .gsub('@title', 
            e.gsub(/\\section{((.|\n)*?)}\s*\n/, '\1')
             .gsub(/\n/, ' '))
          .gsub('@tex_chapter', tex_transliterate(
            e.gsub(/\\section{((.|\n)*?)}\s*\n/, '\1')
             .gsub(/\n/, ' ')))
      end
    end
  end

  if $numbered
    clean = clean.gsub('chapter*{', 'chapter{')
                 .gsub(/\\addcontentsline{toc}{chapter}{.*?}\n/, '')
  end

  # Modifica alineaciones o espacios verticales
  final = []
  clean = clean.split(/\n{2,}/)
  clean.each do |b|
  	b = b.strip

  	if b =~ /{\s*\.(.|\n)*?}/
  	  final.push(get_classes(b))
  	else
  	  final.push(b)
  	end
  end

  # Guardado del archivo
  file = File.open(File.basename($file, '.*') + '.tex', 'w:utf-8')
  file.puts final.join("\n\n").strip
  file.close

  if $default
    template = $template
  else
    template = File.read($template)
  end

  # Modifica la plantilla
  template = template.gsub('@title', $title)
                     .gsub('@press', $press)
                     .gsub('@year', $year)
                     .gsub('@date', $date)
                     .gsub('@ragged', $ragged ? '\\RaggedRight' : '')
                     .gsub('@file', File.basename($file, '.*'))

  if $author == ''
    template = template.gsub('@author', $title)
  else
    template = template.gsub('@author', $author)
  end

  # Añade bibliografía
  if $bib
    template = template.gsub('@bibliography', "\\bibliography{../#{$bib}}")
    template = template.gsub('@printbibliography', "\\printbibliography")
  else
    template = template.gsub('@bibliography', '')
    template = template.gsub('@printbibliography', '')
  end

  # Guardado de la plantilla
  file = File.open($tem_name, 'w:utf-8')
  file.puts template
  file.close

  if !$just_tex
    # Compone el PDF
    system("lualatex -synctex=1 -interaction=batchmode #{File.basename($tem_name, '.*')}.tex")
    if $bib
      system("biber #{File.basename($tem_name, '.*')}")
      system("lualatex -synctex=1 -interaction=batchmode #{File.basename($tem_name, '.*')}.tex")
    end
    system("lualatex -synctex=1 -interaction=batchmode #{File.basename($tem_name, '.*')}.tex")

    # Compone la imposición
    system("pdfbook2 -n -p letterpaper #{File.basename($tem_name, '.*')}.pdf")

    # Mueve los archivos
    FileUtils.mv(File.basename($tem_name, '.*') + '.pdf', '../' + File.basename($file, '.*') + '.pdf')
    FileUtils.mv(File.basename($tem_name, '.*') + '-book.pdf', '../' + File.basename($file, '.*') + '_imposition.pdf')
  else
    FileUtils.mv(File.basename($file, '.*') + '.tex', '..')
    FileUtils.mv(File.basename($tem_name), '..')
  end

  # Regresa a la raíz
  Dir.chdir('..')
rescue
  puts "ERROR: el archivo no pudo ser analizado, revisa su formato o ejecuta: #{$script} --help."
end

# Elimina la carpeta temporal
FileUtils.rm_rf($tmp_dir)