require "asciidoctor"
require "asciidoctor/standoc/converter"
require "fileutils"
require_relative "front"
require_relative "validate"

module Asciidoctor
  module Ogc
    # A {Converter} implementation that generates RSD output, and a document
    # schema encapsulation of the document for validation
    #
    class Converter < Standoc::Converter
      XML_ROOT_TAG = "ogc-standard".freeze
      XML_NAMESPACE = "https://www.metanorma.com/ns/ogc".freeze

      register_for "ogc"

      # ignore, we generate ToC outside of asciidoctor
      def toc(value)
      end

      def makexml(node)
        @draft = node.attributes.has_key?("draft")
        super
      end

      def doctype(node)
        d = node.attr("doctype")
        unless %w{abstract-specification-topic best-practice change-request-supporting-document 
          community-practice community-standard discussion-paper engineering-report other policy 
          reference-model release-notes standard user-guide white-paper test-suite}.include? d
          warn "'#{d}' is not a legal document type: reverting to 'standard'" unless @warned_doctype
          @warned_doctype = true
          d = "standard"
        end
        d
      end

      def document(node)
        init(node)
        ret1 = makexml(node)
        ret = ret1.to_xml(indent: 2)
        unless node.attr("nodoc") || !node.attr("docfile")
          filename = node.attr("docfile").gsub(/\.adoc/, ".xml").
            gsub(%r{^.*/}, "")
          File.open(filename, "w") { |f| f.write(ret) }
          html_converter(node).convert filename unless node.attr("nodoc")
          word_converter(node).convert filename unless node.attr("nodoc")
          pdf_converter(node).convert filename unless node.attr("nodoc")
        end
        @files_to_delete.each { |f| FileUtils.rm f }
        ret
      end

      def validate(doc)
        content_validate(doc)
        schema_validate(formattedstr_strip(doc.dup),
                        File.join(File.dirname(__FILE__), "ogc.rng"))
      end

      def sections_cleanup(x)
        super
        x.xpath("//*[@inline-header]").each do |h|
          h.delete("inline-header")
        end
      end

      def make_preface(x, s)
        super
        if x.at("//submitters")
          preface = s.at("//preface") || s.add_previous_sibling("<preface/>").first
          submitters = x.at("//submitters").remove
          preface.add_child submitters.remove
        end
      end

      def clause_parse(attrs, xml, node)
        clausetype = node&.attr("heading")&.downcase || node.title.downcase
        if clausetype == "submitters" then submitters_parse(attrs, xml, node)
        else
          super
        end
      end

      def bibliography_parse(attrs, xml, node)
        clausetype = node&.attr("heading")&.downcase || node.title.downcase
        if clausetype == "references" then norm_ref_parse(attrs, xml, node) 
        else
          super
        end
      end

      def submitters_parse(attrs, xml, node)
        xml.submitters **attr_code(attrs) do |xml_section|
          xml_section << node.content
        end
      end

      def style(n, t)
        return
      end

      def termdef_boilerplate_cleanup(xmldoc)
        return
      end

      def cleanup(xmldoc)
        super
      end

      def html_converter(node)
        IsoDoc::Ogc::HtmlConvert.new(html_extract_attributes(node))
      end

      def pdf_converter(node)
        IsoDoc::Ogc::PdfConvert.new(html_extract_attributes(node))
      end

      def word_converter(node)
        IsoDoc::Ogc::WordConvert.new(doc_extract_attributes(node))
      end
    end
  end
end