#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

# tag to read and insert a file relative to the current working directory
# (like include, but in the dir where it is invoked)

# there is also readj which reads a file and applies jekyll processing to it
# handy if we want to include a toc.json file which itself calls {% read_jekyll child/toc.json %}
# (note however variables do not seem to be exported when use readj (TODO),
# although they are exported if you have _includes/file.md and use the standard include file)

# the argument can be a variable or a filename literal (not quoted)
# TODO: figure out how to accept a quoted string as an argument

require 'pathname'

module JekyllRead
  class ReadTag < Liquid::Tag
    def initialize(tag_name, text, tokens)
      super
      @text = text
      @mode = :auto
    end

    def load_file(context, filename, context_page)
      # Pathname API ignores first arg below if second is absolute
      file = Pathname.new(File.dirname(context_page['path'])) + filename
      file = file.cleanpath

      # is there a better way to trim a leading / ?
      file = file.relative_path_from(Pathname.new("/")) unless file.relative?
      raise "No such file #{file} in read call (from #{context_page['path']})" unless file.exist?
      file
    end

    def render_jekyll(context, filename)
      file = load_file(context, filename, context['page'] || context.registers[:page])

      # support vars and paths relative to a file being readj'd
      jekyllSite = context.registers[:site]
      targetPage = Jekyll::Page.new(jekyllSite, jekyllSite.source, File.dirname(file), File.basename(file))

      relative_link_parser = JekyllRelativeLinks::Generator.new(nil)
      relative_link_parser.prepare_for_site(jekyllSite)
      relative_link_parser.replace_relative_links!(targetPage)

      targetPage.render(jekyllSite.layouts, jekyllSite.site_payload)
      targetPage.output
    end

    def render_literal(context, filename)
      file = load_file(context, filename, context['page'])

      file = File.open(file, "rb")
      return file.read
    end

    def render(context)
      filename = @text.strip
      context[filename] || filename

      mode = @mode
      if (mode == :auto)
        mode = filename.end_with?(".md") ? :jekyll : :literal
      end
      if (mode == :jekyll)
        render_jekyll(context, filename)
      elsif (mode == :literal)
        render_literal(context, filename)
      else
        raise "Unknown mode #{mode}"
      end

    end
  end

  class ReadJekyllTag < ReadTag
    def initialize(tag_name, text, tokens)
      super
      @mode = :jekyll
    end
  end
  class ReadLiteralTag < ReadTag
    def initialize(tag_name, text, tokens)
      super
      @mode = :literal
    end
  end
end

Liquid::Template.register_tag('read', JekyllRead::ReadTag)
Liquid::Template.register_tag('read_jekyll', JekyllRead::ReadJekyllTag)
Liquid::Template.register_tag('read_literal', JekyllRead::ReadLiteralTag)

# for compatibility with old markdown
Liquid::Template.register_tag('readj', JekyllRead::ReadJekyllTag)
