require 'open-uri'
require "rexml/document"
require 'digest/md5'

module Grump
  module Plugin
    module Maven

      def maven_plugin_setup
        plugin(:java)
        @temp = File.join(path, '.grump', 'temp')
      end

      def download(url)
        FileUtils.mkdir_p(@temp)
        d = Digest::MD5.hexdigest(url)
        if File.exists?("#{@temp}/#{d}")
          return File.read("#{@temp}/#{d}")
        end
        temp = nil
        open(url) do |io|
          temp = io.read
        end
        File.open("#{@temp}/#{d}", "w") do |file|
          file.write(temp)
        end
        temp
      end

      def maven(*args)
        (@maven ||= []) << args.join(':')
      end

      def maven_root
        'http://central.maven.org/maven2'
      end

      def maven_artifact(dependency)
        group, artifact, version = dependency.split(':')
        File.join(maven_root, group.gsub('.','/'), artifact, version,  artifact + '-' + version)
      end

      def maven_pom(dependency)
        maven_artifact(dependency) + '.pom'
      end

      def maven_jar(dependency)
        maven_artifact(dependency) + '.jar'
      end

      def maven_latest(dependency)
        group, artifact = dependency.split(':')
        xml = download(File.join(maven_root, group.gsub('.','/'), artifact, 'maven-metadata.xml'))
        xml = REXML::Document.new(xml)
        (REXML::XPath.match(xml, '/metadata/versioning/latest').first || REXML::XPath.match(xml, '/metadata/version').first).text
      end

      def maven_subst(xml, str)
        str.gsub(/\$\{([^\}]+)\}/) { |var| var = var.split('.').last; REXML::XPath.match(xml, "/project/parent/#{var}").first.text }
      end

      def maven_tree
        @maven.each do |artifact|

          xml = download(maven_pom(artifact))
          xml = REXML::Document.new(xml)

          REXML::XPath.match(xml, '/project/dependencies/dependency').each do |dependency|

            next if dependency.elements['optional'] && dependency.elements['optional'].text == 'true'
            next if dependency.elements['scope'] && dependency.elements['scope'].text == 'test'

            group = dependency.elements['groupId'].text
            group = maven_subst(xml, group)

            artifact = dependency.elements['artifactId'].text
            artifact = maven_subst(xml, artifact)

            if dependency.elements['version']
              version = dependency.elements['version'].text
              version = maven_subst(xml, version)
            else
              version = maven_latest(group + ':' + artifact)
            end

            id = "#{group}:#{artifact}:#{version}"

            unless @maven.include?(id)
              maven(group, artifact, version)
            end
          end

        end
        @maven
      end

      def maven_download
        FileUtils.mkdir_p(@java_libs)
        maven_tree.each do |dependency|
          jar = maven_jar(dependency)
          file = File.join(@java_libs, File.basename(jar))
          `curl -o #{file} #{jar}` unless File.exists?(file)
        end
      end

    end
  end
end

Grump::Plugin.register(:maven, Grump::Plugin::Maven)