#
# Adds a liquid tag to build a page on the contents of the folder it's in
# 
# Pulls in files in the format <Number>_<title>.md in the order of version number. Ignores files not in this format.
#

require 'rubygems'
require 'yaml'
require "kramdown"
require 'pathname'

module PageStructureUtils
  
  class ChildPage
    def initialize(yaml, content)
      @yaml=yaml
      @content=content
    end
    attr_accessor :yaml
    attr_accessor :content
    def to_s # called with print / puts
      "YAML : #{@yaml}" #, Content : #{@content}"
    end

    ##
    # Sort a list of children by their YAML containing section positions. Do this with Gem:Version
    #
    #
    def self.sortBySectionPositions(yaml)
      
      $major = "1"
      $minor = 1
      # first check all the child pages are numbered, if not, number them in the order they are
      yaml.each do |i|
        if i.yaml['section_position'] == nil
          i.yaml['section_position'] = $major+"."+$minor.to_s
          $minor += 1
        else
          # Store any major, start incrementing minor
          $major = i.yaml['section_position'].to_s
          $minor = 1
        end
      end
      
      # return the comparison between the versions
      yaml.sort{ |x,y| Gem::Version.new(x.yaml['section_position'].to_s) <=> Gem::Version.new(y.yaml['section_position'].to_s) }
    end
    ##
    # This goes through the hash looking for the keys for the different types of children
    #
    def self.getDefiningParameterFromHash(hash)
      param_name = hash['path']
      param_name = (param_name == nil ? hash['link'] : param_name)
       (param_name == nil ? hash['section'] : param_name)
    end
    ##
    # Sorts a list of yaml children, if there's no numbering, use the YAML order to create a numbering
    # NOTE: doesn't alter the returned object as that seemed to break things downstream
    #
    def self.sortYAMLSectionPositions(yaml)
          position = Hash.new
          $major = "1"
          $minor = 1
          # go through and generate a position for each
          yaml.each do |i|
            if i.instance_of? String
              position[i] = $major+"."+$minor.to_s
              $minor += 1
            else
              # get the key for this type of child
              defining_param = getDefiningParameterFromHash(i)
              if i['section_position'] == nil
                position[defining_param] = $major+"."+$minor.to_s
                $minor += 1
              else
                # Store any major, start incrementing minor
                position[defining_param] = i['section_position'].to_s
                $major = i['section_position'].to_s
                $minor = 1
              end
            end
          end
          # sort on the position (NB: sort! for in-place sorting)
          yaml.sort!{ |x,y| 
            $pos_x = nil
            $pos_y = nil
            if x.instance_of? String
              $pos_x = position[x]
            else
              defining_param = getDefiningParameterFromHash(x)
              $pos_x = position[defining_param]
            end
            if y.instance_of? String
              $pos_y = position[y]
            else
              defining_param = getDefiningParameterFromHash(y)
              $pos_y = position[defining_param]
            end
            Gem::Version.new($pos_x.to_s) <=> Gem::Version.new($pos_y.to_s) 
            }
        end
    
    ##
    # This function looks at all the *.md files at the YAML in the headers and produces a list of children ordered by section_position
    #
    #
    def self.parseChildYAMLFromParent(page)
      # get the base directory of the current file
      $baseFile = Dir.pwd+"/"+(Pathname(page['path']).dirname.to_s)
      # list all of the files in that directory
      $listings = Dir[$baseFile+"/*.md"]
      $allPages = []

      for $listing in $listings
                
        # read the file
        $fileContent = IO.read($listing)
        # try and split of any YAML
        $partitionedFileContent = $fileContent.split('---');
        # if there's potentially partitioned YAML try and parse it
        if $partitionedFileContent.size > 2
          # try and parse the YAML
          yamlContent = YAML.load($partitionedFileContent[1])
          # if we can, use it (section_type needs to be one of the allowed)
          if yamlContent != nil && yamlContent != false && yamlContent['section_type'] != nil && yamlContent['section_type'] != "default"

            if yamlContent['section_type'] == nil
              # if no section position has been specified, put it at the end
              yamlContent['section_position'] = Integer::MAX
            end
            # if there's YAML, check it has the section_position tag and put it into child pages
            ($allPages ||= []) << ChildPage.new(yamlContent, $partitionedFileContent[2..-1].join('---'))
          end
        end     
      end
      $allPages = sortBySectionPositions($allPages)
      # return the combined content
      $allPages
    end
          
    ##
    # This function looks in a parent folder for all files in the format <Number>_<title>.md
    # 
    #
    def self.parseChildPagesFromParent(page)
      # get the base directory of the current file
      $baseFile = Dir.pwd+"/"+(Pathname(page['path']).dirname.to_s)
      # list all of the files in that directory
      $listings = Dir[$baseFile+"/*"]
      # filter by the key pattern
      $listings = $listings.select{ |i| i[/[\d\.]\_.*\.md/] }
      # Sort the files based on the Gem::Version of the prefix
      $listings = $listings.sort{ |x,y| Gem::Version.new((File.basename x).partition('_').first) <=> Gem::Version.new((File.basename y).partition('_').first)  }
      # loop through them and merge the content
      $allPages = []

      for $listing in $listings
        $textContent = ""
        yamlContent = nil
                
        # read the file
        $fileContent = IO.read($listing)
        # try and split of any YAML
        $partitionedFileContent = $fileContent.split('---');
        # if there's potentially partitioned YAML try and parse it
        if $partitionedFileContent.size > 2
          # try and parse the YAML
          yamlContent = YAML.load($partitionedFileContent[1])
          # if we can, use it
          if yamlContent != nil && yamlContent != false
            $textContent = $partitionedFileContent[2..-1].join('---')
          end
        end
        
        # if there's no text content set yet, just use the whole file
        if $textContent == ""
          # use the whole file content
          $textContent = $fileContent
        end
        # append the current file to the content
        ($allPages ||= []) << ChildPage.new(yamlContent, $textContent)
                
      end
      # return the combined content
      $allPages
    end
  end
  
  class IncludePageContentTag < Liquid::Tag
      def initialize(tag_name, text, tokens)
        super
        @text = text.strip
      end
      def render(context)
#        $childPages = ChildPage.parseChildPagesFromParent(context['page'])
        $childPages = ChildPage.parseChildYAMLFromParent(context['page'])
        $content = ""
        for $childPage in $childPages
          #append the content
          $content = $content+$childPage.content()
        end
        site = context.registers[:site]
        pageHash = context.registers[:page]
          
        # not sure how to get the page object so look through site.pages for the current URL
        page = nil;
        for currPage in site.pages
          if currPage['url'] == pageHash['url']
            page = currPage
            break
          end
        end

        # render the included content with the current page renderer
        info = { :filters => [Jekyll::Filters], :registers => { :site => site, :page => page } }
        path_for_cache = "include_page-#{context['page']}"

        relative_link_parser = JekyllRelativeLinks::Generator.new(nil)
        relative_link_parser.prepare_for_site(site)
        $content = relative_link_parser.replace_relative_links_in_content($content, page.relative_path)

        page.render_liquid($content, site.site_payload, info, path_for_cache)
      end
    end
end

Liquid::Template.register_tag('child_content', PageStructureUtils::IncludePageContentTag)
