<!-- These are a collection of tags that allow a application outline or summary to be created -->

<!-- Rails.version -->
<def tag="rails-version">
  <%= Rails.version -%>
</def>

<!-- returns "vendor" or "gem" -->
<def tag="rails-location">
  <%= Rails.vendor_rails? ? "vendor" : "gem" -%>
</def>

<!-- `Rails.root` -->
<def tag="rails-root">
  <%= Rails.root -%>
</def>

<!-- `RAILS_ENV` -->
<def tag="rails-env">
  <%= Rails.env -%>
</def>

<!-- Which change management system is in use:  "git" "subversion" "other" -->
<def tag="cms-method">
  <%= if File.exist?("#{Rails.root}/.git")
        "git"
      elsif File.exist?("#{Rails.root}/.svn")
        "subversion"
      else
        "other"
      end -%>
</def>

<!-- the git branch currently in use -->
<def tag="git-branch">
  <%= File.basename(`git symbolic-ref HEAD`) -%>
</def>

<!-- the git version currently in use -->
<def tag="git-version" attrs="dir">
  <% dir=Rails.root if dir.blank? -%>
  <%= Dir.chdir(dir) {`git rev-list "HEAD^..HEAD" --abbrev-commit --abbrev=7`} -%>
</def>

<!-- returns 'clean' if there are no modified files, 'modified' otherwise. -->
<def tag="git-clean" attrs="dir">
  <% dir=Rails.root if dir.blank? -%>
  <%= Dir.chdir(dir) {`git ls-files -m`}.blank? ? "clean" : "modified"  -%>
</def>

<!-- the time & date of the last commit -->
<def tag="git-last-commit-time">
  <%= `git log "HEAD^..HEAD" --pretty=format:%cD` -%>
</def>

<!-- calls `git-clean` or `svn-clean` as appropriate.  `svn-clean` not yet written. -->
<def tag="cms-clean">
  <% method = cms_method.strip -%>
  <git-clean if="&method=='git'"/>
</def>

<!-- calls `git-last-commit-time` or `svn-last-commit-time` as appropriate.  `svn-last-commit-time` not yet written. -->
<def tag="cms-last-commit-time">
  <% method = cms_method.strip -%>
  <git-last-commit-time if="&method=='git'"/>
</def>

<!-- calls `git-version` or `svn-version` as appropriate.  `svn-version` not yet written. -->
<def tag="cms-version">
  <% method = cms_method.strip -%>
  <git-version if="&method=='git'"/>
</def>

<!-- calls `git-branch` or `svn-branch` as appropriate.  `svn-branch` not yet written. -->
<def tag="cms-branch">
  <% method = cms_method.strip -%>
  <git-branch if="&method=='git'"/>
</def>

<!-- Hobo::VERSION -->
<def tag="hobo-version">
  <%= Hobo::VERSION -%>
</def>

<!-- repeats on Rails.configuration.gems, including dependent gems -->
<def tag="with-gems">
  <% gems = ActiveSupport::OrderedHash.new -%>
  <% Rails.configuration.gems.each do |gem|
       gems[name] ||= gem
       gem.dependencies.each do |dep|
         gems[dep] ||= dep
       end
     end -%>
  <repeat with="&gems">
    <do param="default"/>
  </repeat>
</def>

<!-- inside `<with-gems>`, returns the gem name -->
<def tag="gem-name">
  <%= this.name -%>
</def>

<def tag="gem-version-requirement">
  <unless test="this.nil?"><%=
    this.requirements.map{|l| l.first+l.second.to_s}.join(",")
-%></unless>
</def>

<!-- inside `<with-gems>`, returns the version required -->
<def tag="gem-version-required">
  <gem-version-requirement:version-requirements />
</def>

<!-- inside `<with-gems>`, returns the version -->
<def tag="gem-version">
  <%= this.specification.version.to_s -%>
</def>

<!-- inside `<with-gems>`, returns 'frozen', 'installed' or 'missing' -->
<def tag="gem-frozen">
  <%= this.frozen? ? "frozen" : (this.installed? ? "installed" : "missing") -%>
</def>

<!-- inside `<with-gems>`, returns the gem dependencies -->
<def tag="gem-dependencies">
  <repeat with="&this.dependencies">
    <%= this.name -%><gem-version-requirement with="&this.requirement || this.version_requirements" />
  </repeat>
</def>

<!-- repeats on the plugins used by the application -->
<def tag="with-plugins">
  <% plugins = Rails.configuration.plugin_loader.new(Hobo.rails_initializer).plugins %>
  <repeat with="&plugins">
    <do param="default" />
  </repeat>
</def>

<!-- within `<with-plugins>`, returns the plugin name -->
<def tag="plugin-name">
  <%= this.name -%>
</def>

<!-- within `<with-plugins>`, returns the plugin location (directory) -->
<def tag="plugin-location">
  <%= this.directory -%>
</def>

<def tag="plugin-git-clean">
  <git-clean dir="&this.directory"/>
</def>

<def tag="plugin-git-version">
  <git-version dir="&this.directory"/>
</def>

<!-- within `<with-plugins>`, try and determine the method that was used to install the plugin.   Returns "braid", "symlink", "git-submodule" or "other" -->
<def tag="plugin-method">
  <%=
      braids = File.open("#{Rails.root}/.braids") {|f| YAML::load(f) } rescue {}
      if !braids[this.directory.gsub(Rails.root+"/", "")].nil?
        "braid"
      elsif File.lstat(this.directory).symlink?
        "symlink"
      elsif File.exist?(this.directory+"/.git")
        "git-submodule"
      else
        "other"
      end
   -%>
</def>

<!-- within `<with-plugins>`, determine if the plugin has been modified, returning "clean" or "modified".   Returns a blank string if this information is not available.   Uses `<plugin-git-clean>` or `<plugin-braid-clean>` to do the heavy lifting. -->
<def tag="plugin-clean">
  <% method = plugin_method.strip -%>
  <plugin-git-clean if="&method=='git-submodule'"/>
  <plugin-braid-clean if="&method=='braid'"/>
</def>

<!-- within `<with-plugins>`, returns the plugin version.   Returns a blank string if this information is not available.   Uses `<plugin-git-version>` or `<plugin-braid-version>` to do the heavy lifting. -->
<def tag="plugin-version">
  <% method = plugin_method.strip -%>
  <plugin-git-version if="&method=='git-submodule'"/>
  <plugin-braid-version if="&method=='braid'"/>
</def>

<def tag="plugin-braid-clean">
  <%= diff=`braid diff #{this.directory.gsub(Rails.root+"/", "")}`
      diff.strip.empty? ? "clean" : "modified" -%>
</def>

<def tag="plugin-braid-version">
  <%=  braids = File.open("#{Rails.root}/.braids") {|f| YAML::load(f) } rescue {}
       b=braids[this.directory.gsub(Rails.root+"/", "")]
       b['revision'][0...7] if b -%>
</def>

<!-- repeats on the available execution environments, which are usually 'development', 'test' and 'production' -->
<def tag="with-environments">
  <repeat with="&Rails.configuration.database_configuration.keys">
    <do param="default" />
  </repeat>
</def>

<def tag="environment-name">
  <%= this -%>
</def>

<!-- Given an environment name in the context, return the database adapter -->
<def tag="database-type">
  <%= Rails.configuration.database_configuration[this]['adapter'] -%>
</def>

<!-- Given an environment name in the context, return the database name -->
<def tag="database-name">
  <%= Rails.configuration.database_configuration[this]['database'] -%>
</def>

<!-- repeats on available models.  Does not return models defined in libraries or plugins.  -->
<def tag="with-models">
  <%  # stolen from railroad/model_diagram.rb

    files = Dir.glob("app/models/**/*.rb")
    models = files.map do |file|
      model_name =  (model_path = file.gsub(/^(app\/models\/)([\w_\/\\]+)\.rb/, '\2')).camelize
      # Hack to skip all xxx_related.rb files
      next if /_related/i =~ model_name

      begin
        model_name.constantize
      rescue LoadError
        oldlen = model_path.length
        model_path.gsub!(/.*[\/\\]/, '')
        model_name = model_path.camelize
        if oldlen > model_path.length
          retry
        end
        next
      rescue NameError
        next
      end
    end
   -%>
  <repeat with="&models.sort_by {|m| m.to_s}">
    <do param="default" />
  </repeat>
</def>

<def tag="model-name">
  <%= this.to_s -%>
</def>

<!-- given a model, returns the table name -->
<def tag="model-table-name">
  <%= this.try.table_name -%>
</def>

<!-- given a model, returns the table comment, if it exists and if you have the activerecord-comments plugin installed. -->
<def tag="model-table-comment">
  <%= this.try.comment -%>
</def>

<!-- given a model, repeats on the database columns -->
<def tag="with-model-columns">
  <repeat with="&this.try.content_columns">
    <do param="default" />
  </repeat>
</def>

<!-- given a column, returns the type -->
<def tag="model-column-type">
  <%= this.type.to_s -%>
</def>

<!-- given a column, return the name -->
<def tag="model-column-name">
  <%= this.name -%>
</def>

<!-- given a column in the context and the model as an attribute, returns the comment for the column.  It returns the SQL comment if that is available (using the activerecord-comments plugin).  If that is not available, it returns the HoboFields comment.  -->

<def tag="model-column-comment" attrs="model">
  <%= this.try.comment || model.try.field_specs.try.get(this.name).try.comment -%>
</def>

<!-- given a model, repeats on the associations -->
<def tag="with-model-associations">
  <repeat with="&this.try.reflect_on_all_associations">
    <do param="default" />
  </repeat>
</def>

<!-- given an association, return the name -->
<def tag="model-association-name">
  <%= this.name.to_s -%>
</def>

<!-- given an association, return the macro type (`has_many`, etc.) -->
<def tag="model-association-macro">
  <%= if this.macro.to_s=='has_many' && this.options[:through]
        'has_many :through'
      else
        this.macro.to_s
      end -%>
</def>

<!-- given an association, return the name -->
<def tag="model-association-class-name">
  <%= (this.class_name.try.respond_to? 'underscore') ? this.class_name.underscore.singularize.camelize : this.try.class_name -%>
</def>