module Softcover
  module Mathjax

    # Returns the MathJax configuration.
    def self.config(options = {})
      chapter_number = if options[:chapter_number]
                         if (options[:chapter_number].zero? ||
                             Softcover::Utils.article?)
                             false
                           else
                             # Call .inspect.inspect to escape the chapter
                             # number code for interpolation.
                             options[:chapter_number].inspect.inspect
                           end
                         elsif options[:chapter_number].nil?
                           '#{chapter_number}'
                       else  # chapter_number is false, i.e., it's a single page
                         false
                       end
      fn = if chapter_number
             "formatNumber: function (n) { return #{chapter_number} + '.' + n }"
           else
             ""
           end

      config = <<-EOS
      MathJax.Hub.Config({
        "HTML-CSS": {
          availableFonts: ["TeX"],
        },
        TeX: {
          extensions: ["AMSmath.js", "AMSsymbols.js", "color.js"],
          equationNumbers: {
            autoNumber: "AMS",
            #{fn}
          },
          Macros: {
            PolyTeX:    "Poly{\\\\TeX}",
            PolyTeXnic: "Poly{\\\\TeX}nic",
            #{custom_macros}
          }
        },
        showProcessingMessages: false,
        messageStyle: "none",
        imageFont: null,
        "AssistiveMML": { disabled: true }
      });
      EOS
      config
    end

    # Rerturns a version of the MathJax configuration escaped for the server.
    # There's an extra interpolation somewhere between here and the server,
    # which this method corrects for.
    def self.escaped_config(options={})
      self.config(options).gsub('\\', '\\\\\\\\')
    end

    MATHJAX  = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config='
    AMS_HTML = MATHJAX + 'TeX-AMS_HTML'
    AMS_SVG  = MATHJAX + 'TeX-AMS-MML_SVG'

    # Returns the custom macros as defined in the custom style file.
    def self.custom_macros
      extract_macros(Softcover.custom_styles)
    end

    private

      # Extracts and formats the macros from the given string of style commands.
      # The output format is compatible with the macro configuration described
      # at http://docs.mathjax.org/en/latest/tex.html.
      def self.extract_macros(styles)
        # For some reason, \ensuremath doesn't work in MathJax, so remove it.
        styles.gsub!('\ensuremath', '')
        # First extract commands with no arguments.
        cmd_no_args = /^\s*\\newcommand\{\\(.*?)\}\{(.*)\}/
        cna = styles.scan(cmd_no_args).map do |name, definition|
          escaped_definition = definition.gsub('\\', '\\\\\\\\')
          %("#{name}": "#{escaped_definition}")
        end
        # Then grab the commands with arguments.
        cmd_with_args = /^\s*\\newcommand\{\\(.*?)\}\[(\d+)\]\{(.*)\}/
        cwa = styles.scan(cmd_with_args).map do |name, number, definition|
          escaped_definition = definition.gsub('\\', '\\\\\\\\')
          %("#{name}": ["#{escaped_definition}", #{number}])
        end
        (cna + cwa).join(",\n")
      end
  end
end