# 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.

module Buildr
  module Bnd
    class << self
      # The specs for requirements
      def dependencies
        ["biz.aQute:bnd:jar:0.0.384"]
      end

      # Repositories containing the requirements
      def remote_repository
        "http://www.aQute.biz/repo"
      end

      def bnd_main(*args)
        cp = Buildr.artifacts(self.dependencies).each(&:invoke).map(&:to_s)
        Java::Commands.java 'aQute.bnd.main.bnd', *(args + [{ :classpath => cp }])
      end
    end
    
    class BundleTask < Rake::FileTask
      attr_reader :project
      attr_accessor :classpath

      def [](key)
        @params[key]
      end

      def []=(key, value)
        @params[key] = value
      end

      def classpath_element(dependencies)
        artifacts = Buildr.artifacts([dependencies])
        self.prerequisites << artifacts
        artifacts.each do |dependency|
          self.classpath << dependency.to_s
        end
      end

      def to_params
        params = self.project.manifest.merge(@params).reject { |k, v| v.nil? }
        params["-classpath"] ||= self.classpath.collect(&:to_s).join(", ")
        params['Bundle-SymbolicName'] ||= [self.project.group, self.project.name.gsub(':', '-')].join('.')
        params['Bundle-Name'] ||= self.project.comment || self.project.name
        params['Bundle-Description'] ||= self.project.comment
        params['Bundle-Version'] ||= self.project.version
        if params["Include-Resource"].nil? && !project.resources.target.nil?
          params["Include-Resource"] = "#{project.resources.target}/"
        end
        params['-removeheaders'] ||= "Include-Resource,Bnd-LastModified,Created-By,Implementation-Title,Tool"

        params
      end

      def project=(project)
        @project = project
      end

      def classpath=(classpath)
        @classpath = []
        Buildr.artifacts([classpath.flatten.compact]).each do |dependency|
          self.prerequisites << dependency
          @classpath << dependency.to_s
        end
        @classpath
      end

      def classpath
        @classpath ||= ([project.compile.target] + project.compile.dependencies).flatten.compact
      end

      protected

      def initialize(*args) #:nodoc:
        super
        @params = {}
        enhance do
          filename = self.name
          # Generate BND file with same name as target jar but different extension
          bnd_filename = filename.sub /(\.jar)?$/, '.bnd'

          params = self.to_params
          params["-output"] = filename
          File.open(bnd_filename, 'w') do |f|
            f.print params.collect { |k, v| "#{k}=#{v}" }.join("\n")
          end

          Buildr::Bnd.bnd_main( "build", "-noeclipse", bnd_filename )
          begin
            Buildr::Bnd.bnd_main( "print", "-verify", filename )
          rescue => e
            rm filename
            raise e
          end
        end
      end
    end

    module ProjectExtension
      include Extension

      first_time do
        desc "Does `bnd print` on the packaged bundle and stdouts the output for inspection"
        Project.local_task("bnd:print")
      end

      def package_as_bundle(filename)
        project.task('bnd:print' => [filename]) do |task|
          Buildr::Bnd.bnd_main("print", filename)
        end

        dirname = File.dirname(filename)
        directory(dirname)

        # Add Buildr.application.buildfile so it will rebuild if we change settings
        task = BundleTask.define_task(filename => [Buildr.application.buildfile, dirname])
        task.project = self
        # the last task is the task considered the packaging task
        task
      end

      # Change the bundle package to .jar extension
      def package_as_bundle_spec(spec)
        spec.merge(:type => :jar)
      end
    end
  end
end

class Buildr::Project
  include Buildr::Bnd::ProjectExtension
end