# 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
  # Provides the <code>pmd:rule:xml</code>, <code>pmd:rule:html</code>, <code>pmd:cpd:xml</code>
  # and <code>pmd:cpd:html</code> tasks.
  #
  # Require explicitly using <code>require 'buildr/pmd'</code>.
  module Pmd

    class << self

      # The specs for requirements
      def dependencies
        %w(net.sourceforge.pmd:pmd:jar:5.1.3 jaxen:jaxen:jar:1.1.1 commons-io:commons-io:jar:2.2 com.beust:jcommander:jar:1.27 asm:asm:jar:3.2)
      end

      def pmd(rule_set_files, format, output_file_prefix, source_paths, options = {})
        dependencies = (options[:dependencies] || []) + self.dependencies
        cp = Buildr.artifacts(dependencies).each(&:invoke).map(&:to_s)
        (options[:rule_set_paths] || []).each {|p| cp << p}

        rule_sets = rule_set_files.dup

        Buildr.artifacts(options[:rule_set_artifacts] || []).each do |artifact|
          a = artifact.to_s
          dirname = File.dirname(a)
          rule_sets << a[dirname.length + 1, a.length]
          cp << File.dirname(a)
          artifact.invoke
        end

        puts 'PMD: Analyzing source code...'
        mkdir_p File.dirname(output_file_prefix)

        Buildr.ant('pmd-report') do |ant|
          ant.taskdef :name=> 'pmd', :classpath => cp.join(';'), :classname => 'net.sourceforge.pmd.ant.PMDTask'
          ant.pmd :shortFilenames => true, :rulesetfiles => rule_sets.join(',') do
            ant.formatter :type => format, :toFile => "#{output_file_prefix}.#{format}"
            source_paths.each do |src|
              ant.fileset :dir=> src, :includes=>'**/*.java' if File.directory?(src)
            end
          end

        end
      end

      def cpd(format, output_file_prefix, source_paths, options = {})
        dependencies = (options[:dependencies] || []) + self.dependencies
        cp = Buildr.artifacts(dependencies).each(&:invoke).map(&:to_s)
        minimum_token_count = options[:minimum_token_count] || 100
        encoding = options[:encoding] || 'UTF-8'

        puts 'PMD-CPD: Analyzing source code...'
        mkdir_p File.dirname(output_file_prefix)

        Buildr.ant('cpd-report') do |ant|
          ant.taskdef :name=> 'cpd', :classpath => cp.join(';'), :classname => 'net.sourceforge.pmd.cpd.CPDTask'
          ant.cpd :format => format, :minimumTokenCount => minimum_token_count, :encoding => encoding, :outputFile => "#{output_file_prefix}.#{format}" do
            source_paths.each do |src|
              ant.fileset :dir=> src, :includes=>'**/*.java' if File.directory?(src)
            end
          end

        end
      end
    end

    class Config

      attr_writer :enabled

      def enabled?
        !!@enabled
      end

      attr_writer :rule_set_files

      def rule_set_files
        @rule_set_files ||= (self.rule_set_artifacts.empty? ? %w(rulesets/java/basic.xml rulesets/java/imports.xml rulesets/java/unusedcode.xml rulesets/java/finalizers.xml rulesets/java/braces.xml) : [])
      end

      # Support specification of rule sets that are distributed as part of a maven repository
      def rule_set_artifacts
        @rule_set_artifacts ||= []
      end

      attr_writer :rule_set_paths

      def rule_set_paths
        @rule_set_paths ||= []
      end

      attr_writer :report_dir

      def report_dir
        @report_dir || project._(:reports, :pmd)
      end

      attr_writer :output_file_prefix

      def output_file_prefix
        @output_file_prefix || "#{self.report_dir}/pmd"
      end

      attr_writer :cpd_output_file_prefix

      def cpd_output_file_prefix
        @cpd_output_file_prefix || "#{self.report_dir}/cpd"
      end

      def source_paths
        @source_paths ||= [self.project.compile.sources, self.project.test.compile.sources].flatten.compact
      end

      # An array of paths that should be excluded no matter how they are added to pmd
      def exclude_paths
        @source_paths ||= []
      end

      # An array of additional projects to scan for main and test sources
      attr_writer :additional_project_names

      def additional_project_names
        @additional_project_names ||= []
      end

      def flat_source_paths
        paths = source_paths.dup

        self.additional_project_names.each do |project_name|
          p = self.project.project(project_name)
          paths << [p.compile.sources, p.test.compile.sources].flatten.compact
        end

        paths.flatten.select{|p|!self.exclude_paths.include?(p)}.compact
      end

      protected

      def initialize(project)
        @project = project
      end

      attr_reader :project
    end

    module ProjectExtension
      include Extension

      def pmd
        @pmd ||= Buildr::Pmd::Config.new(project)
      end

      after_define do |project|
        if project.pmd.enabled?
          desc 'Generate pmd xml report.'
          project.task('pmd:rule:xml') do
            Buildr::Pmd.pmd(project.pmd.rule_set_files, 'xml', project.pmd.output_file_prefix, project.pmd.flat_source_paths, :rule_set_paths => project.pmd.rule_set_paths, :rule_set_artifacts => project.pmd.rule_set_artifacts)
          end

          desc 'Generate pmd html report.'
          project.task('pmd:rule:html') do
            Buildr::Pmd.pmd(project.pmd.rule_set_files, 'html', project.pmd.output_file_prefix, project.pmd.flat_source_paths, :rule_set_paths => project.pmd.rule_set_paths, :rule_set_artifacts => project.pmd.rule_set_artifacts)
          end

          desc 'Generate pmd cpd xml report.'
          project.task('pmd:cpd:xml') do
            Buildr::Pmd.cpd('xml', project.pmd.cpd_output_file_prefix, project.pmd.flat_source_paths)
          end

          desc 'Generate pmd cpd text report.'
          project.task('pmd:cpd:text') do
            Buildr::Pmd.cpd('text', project.pmd.cpd_output_file_prefix, project.pmd.flat_source_paths)
          end
        end
      end
    end
  end
end

class Buildr::Project
  include Buildr::Pmd::ProjectExtension
end
